diff --git a/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/footer.js b/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/footer.js new file mode 100644 index 000000000..3bbf259e7 --- /dev/null +++ b/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/footer.js @@ -0,0 +1,170 @@ +import React, { useState } from 'react' + +import { ButtonDropdown, Button, + DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap' +import { range } from 'lodash' + +import Icon from '../../../../../Icon' +//import FactorialModal from './components/FactorialModal' +import { useArrayContext } from '../../../../../Form/array' + +import Uploader from '../../../../../Uploader' +import { saveAs } from 'file-saver' +import { parse, unparse } from 'papaparse' + +const exportGrid = (data, columns) => { + const output = unparse({ + fields: columns.map(c => c.name), + data + }) + + return saveAs( + new Blob( + [ output ], + { type: 'text/csv;charset=utf-8' } + ), + 'loop.csv' + ) +} + +export default ({ columns, data }) => { + const [dropdownOpen, setDropdownOpen] = useState(false) + //const factorialModal = createRef() + const { addRow, overwriteAll } = useArrayContext() + + return ( + + + + + { /* + + */ } + setDropdownOpen(!dropdownOpen) } + > + + + + { /* + Generate + factorialModal.current.show().then(result => { + overwriteAll(result.rows, result.columns) + }) } + > + Factorial design + + */ } + + Repeat + { + const n = window.prompt('How many times?') + if (n) { + overwriteAll( + data.flatMap(r => range(n).map(() => r)), + columns, + ) + } + } } + > + Each row + + { + const n = window.prompt('How many times?') + if (n) { + overwriteAll( + range(n).flatMap(() => data), + columns, + ) + } + } } + > + Entire grid + + + CSV / TSV + { + // TODO: Close the dropdown when the file selector + // is shown. This needs some more work to make sure + // that the uploader component isn't removed from the + // page in between + setDropdownOpen(false) + + const parseResult = parse( + content.trim(), + { header: true } + ) + + if ( + // No detected issues + parseResult.errors.length === 0 || + // Data is present, but no delimiter found + (parseResult.data && parseResult.errors.length === 1 && + parseResult.errors[0].code === 'UndetectableDelimiter') + ) { + overwriteAll( + parseResult.data.map(r => Object.values(r)), + Object.keys(parseResult.data[0]) + .map(c => ({ name: c, type: 'string' })), + ) + } else { + console.log( + 'CSV import found errors: ', + parseResult.errors + ) + alert( + 'Sorry, I couldn\'t parse that CSV file. ' + + 'There seems to be an error. ' + + 'Could you check it, please?' + ) + } + } + } + > +
+ Import +
+
+ exportGrid(data, columns) } + > + Export + +
+
+ + + + + ) +} diff --git a/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/index.js b/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/index.js index 2ec1c2bcf..5ab79cf25 100644 --- a/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/index.js +++ b/packages/builder/src/components/ComponentOptions/components/Content/Loop/Grid/index.js @@ -4,6 +4,7 @@ import { FastField, useFormikContext } from 'formik' import classnames from 'classnames' import Header from './header' +import Footer from './footer' import { Table, DefaultRow } from '../../../../../Form/table' import './style.css' @@ -34,6 +35,7 @@ export default () => { row={ Row } columns={ columns } header={ Header } + footer={ Footer } defaultItem={ Array(columns).fill('') } className={ classnames({ 'table': true,