diff --git a/src/assets/scss/components/formBuilder.scss b/src/assets/scss/components/formBuilder.scss index 0eac29a..9f70641 100644 --- a/src/assets/scss/components/formBuilder.scss +++ b/src/assets/scss/components/formBuilder.scss @@ -191,16 +191,109 @@ } .formElementSettings__repeater { - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: 1fr; gap: 0.5rem; } .formElementSettings__repeaterItem { + display: grid; + grid-template-columns: 4.5fr 2.4fr 1fr 1.4fr 0.7fr; + gap: 12px; + > div { + display: flex; + align-items: center; + width: 100%; + box-sizing: border-box; + + input, select, .p-dropdown { + width: 100%; + box-sizing: border-box; + } + } } -.formElementSettings__subRepeater { - padding: 10px 20px; - background-color: #f9f9f9; +.formElementSettings__subRepeaterWrapper { + display: grid; + grid-template-columns: 1fr; + gap: 7px; +} + +.formElementSettings__subRepeaterItem { + display: grid; + grid-template-columns: 9.3fr 0.7fr; + gap: 12px; + + > div { + display: flex; + align-items: center; + width: 100%; + box-sizing: border-box; + + input, select, .p-dropdown { + width: 100%; + box-sizing: border-box; + } + } +} + +.formElementSettings__repeaterItemIconBtn { + border: none; + background: transparent; + padding: 0; + font-size: 2rem; + color: var(--table-border-color); + + i { + font-size: 2rem; + } + + &:hover { + cursor: pointer; + color: var(--menuitem-active-background); + } + + &:not([data-active="false"]) { + color: var(--menuitem-active-background); + } +} + +.formElementSettings__lastRowHeader { + display: grid; + grid-template-columns: 8.3fr 1.7fr; + gap: 7px; +} + +.formElementSettings__lastRowHeaderTitle { + display: flex; + height: 40px; + padding: 10.5px 17.5px; + justify-content: center; + align-items: center; + border-radius: 4px; + background: #f8f9fa; + border: 1px solid #dee2e6; + font-size: 14px; + font-style: normal; + font-weight: 700; + color: white; +} + +.formElementSettings__lastRowItem { + display: grid; + grid-template-columns: 1.7fr 8.3fr; + gap: 7px; + + > div { + display: flex; + align-items: center; + width: 100%; + box-sizing: border-box; + + input, select, .p-dropdown { + width: 100%; + box-sizing: border-box; + } + } } \ No newline at end of file diff --git a/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js b/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js new file mode 100644 index 0000000..6351f92 --- /dev/null +++ b/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js @@ -0,0 +1,25 @@ +const DefaultCell = ({ getValue, row: { index }, column: { id }, table }) => { + const initialValue = getValue(); + const disabled = table.options.meta?.disabled; + + const onBlur = (e) => { + table.options.meta?.updateData(index, id, e.target.value); + }; + + const onFocus = (e) => { + e.target.select(); + } + + return ( + table.options.meta?.updateData(index, id, e.target.value)} + onBlur={onBlur} + onFocus={onFocus} + className="w-full px-2 py-1 border rounded" + /> + ); +}; + +export default DefaultCell; \ No newline at end of file diff --git a/src/components/FormField/components/Table/RenderTable/components/LastRowCell/index.js b/src/components/FormField/components/Table/RenderTable/components/LastRowCell/index.js new file mode 100644 index 0000000..3a35e77 --- /dev/null +++ b/src/components/FormField/components/Table/RenderTable/components/LastRowCell/index.js @@ -0,0 +1,21 @@ +import { head, isEmpty, isNil, sum } from 'ramda'; + +const LastRowCell = ({columnId, lastRows, columnMeta = {}, getColumnDataFn}) => { + const cellData = head(lastRows.filter(o => !isNil(o[columnId]))); + let cellValue = cellData[columnId]; + + if (columnMeta.enableFormula) { + const getAllRowsValues = getColumnDataFn(columnId) + .map(v => isEmpty(v) || isNil(v) ? 0 : v); + + if (cellValue === 'sum') { + cellValue = sum(getAllRowsValues); + } else { + cellValue = 0; + } + } + + return {cellValue}; +}; + +export default LastRowCell; \ No newline at end of file diff --git a/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js b/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js new file mode 100644 index 0000000..58a6f25 --- /dev/null +++ b/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js @@ -0,0 +1,34 @@ +const NumericFormulaCell = ({ getValue, row: { index }, column: { id }, table }) => { + const initialValue = getValue(); + const disabled = table.options.meta?.disabled; + + const onBlur = (e) => { + const numValue = e.target.value === 0 ? null : Number(e.target.value); + table.options.meta?.updateData(index, id, numValue); + }; + + const onFocus = (e) => { + e.target.select(); + } + + const onChange = (e) => { + if (e.target.value === 0 || !isNaN(e.target.value)) { + table.options.meta?.updateData(index, id, e.target.value); + } + }; + + return ( + + ); +}; + +export default NumericFormulaCell; \ No newline at end of file diff --git a/src/components/FormField/components/Table/RenderTable/index.js b/src/components/FormField/components/Table/RenderTable/index.js index e30ac5e..604a453 100644 --- a/src/components/FormField/components/Table/RenderTable/index.js +++ b/src/components/FormField/components/Table/RenderTable/index.js @@ -1,31 +1,22 @@ import React from 'react'; import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { wrap } from 'object-path-immutable'; +import { isEmpty } from 'ramda'; -const RenderTable = ({ data, columns, setRowsFn, disabled }) => { +// components +import DefaultCell from './components/DefaultCell'; +import LastRowCell from './components/LastRowCell'; + +const RenderTable = ({ data, columns, lastRow, setRowsFn, disabled }) => { const table = useReactTable({ data, columns, defaultColumn: { - cell: ({ getValue, row: { index }, column: { id }, table }) => { - const initialValue = getValue(); - - const onBlur = (e) => { - table.options.meta?.updateData(index, id, e.target.value); - }; - - return ( - table.options.meta?.updateData(index, id, e.target.value)} - onBlur={onBlur} - /> - ); - }, + cell: DefaultCell }, getCoreRowModel: getCoreRowModel(), meta: { + disabled, updateData: (rowIndex, columnId, value) => { const newRowsData = wrap(data).set([rowIndex, columnId], value).value(); setRowsFn(newRowsData); @@ -33,6 +24,11 @@ const RenderTable = ({ data, columns, setRowsFn, disabled }) => { } }); + const getColumnData = (columnId) => { + const rows = table.getRowModel().rows; + return rows.map(row => row.getValue(columnId)); + }; + return ( @@ -72,6 +68,16 @@ const RenderTable = ({ data, columns, setRowsFn, disabled }) => { ); })} + {!isEmpty(lastRow) + ? + {columns.map((o) => )} + + : null}
) diff --git a/src/components/FormField/components/Table/index.js b/src/components/FormField/components/Table/index.js index d08e21e..8ebd19b 100644 --- a/src/components/FormField/components/Table/index.js +++ b/src/components/FormField/components/Table/index.js @@ -10,6 +10,7 @@ import { Button } from 'primereact/button'; import RenderTable from './RenderTable'; import { klona } from 'klona'; import { nonEmptyTables } from '../../../../helpers/validators'; +import NumericFormulaCell from './RenderTable/components/NumericFormulaCell'; const Table = ({ fieldName, @@ -25,6 +26,7 @@ const Table = ({ const [columnsCfg, setColumnsCfg] = useState([]); const [rowsCfg, setRowsCfg] = useState([]); const [columns, setColumns] = useState([]); + const [lastRow, setLastRow] = useState([]); const [rows, setRows] = useState(null); const [shouldDisableNewRows, setShouldDisableNewRows] = useState(false); const [rowIndexToDelete, rowRowIndexToDelete] = useState(null); @@ -72,19 +74,23 @@ const Table = ({ useEffect(() => { let shouldDisableNewRows = false; - let newColumns = columnsCfg.map((o) => { const item = { accessorKey: o.name, header: () => o.label, - footer: (props) => props.column.id + footer: (props) => props.column.id, + meta: { + predefined: o.predefined, + enableFormula: o.enableFormula, + fieldtype: o.fieldtype + } } if (o.predefined) { shouldDisableNewRows = true; - item.cell = (info) => { - return info.getValue(); - } + item.cell = (info) => info.getValue(); + } else if (o.enableFormula || o.fieldtype === 'numeric') { + item.cell = NumericFormulaCell; } return item; @@ -97,7 +103,7 @@ const Table = ({ accessorKey: 'actions', header: () => '', footer: (props) => props.column.id, - cell: ({row: { index }}) => + +
setChecked(e.value, i)}/>
+
+
} const properSubField = (item, i, name) => { - return onSubInputChange(e, name, i)}/> + return <> +
+ onSubInputChange(e, name, i)}/> +
+
+
+ } + const properFieldsLastRow = (item, i) => { + return <> +
+ {sprintf(__('Colonna %d'), i + 1)} +
+ {item.enableFormula + ?
+ onLastRowFormulaChange(e.value, i)} + options={[ + { value: 'sum', label: __('Somma automatica', 'gepafin') } + ]}/> +
+ :
+ onLastRowInputChange(e, i)}/> +
} + + } + + const lastRow = useCallback(() => { + return
+
+
+ {__('Definisci ultima righa', 'gepafin')} +
+
+ {stateFieldData.map((o, i) =>
+ {properFieldsLastRow(o, i)} +
)} +
+ }, [stateFieldData]); + useEffect(() => { const stateFieldData = pathOr([], ['stateFieldData'], value); setStateFieldData(stateFieldData); @@ -114,44 +248,51 @@ const ElementSettingTableColumns = ({ }); }, [stateFieldData, rowsData]); - stateFieldData.filter(o => o.predefined) - return ( <>
+ {stateFieldData.length > 0 + ?
+
{__('Colonne', 'gepafin')}
+
{__('Tipo', 'gepafin')}
+
{__('Calcola', 'gepafin')}
+
{__('Predefinito?', 'gepafin')}
+
+
: null} {stateFieldData.map((o, i) =>
-
- {properField(o, i)} -
+ {properFields(o, i)}
)} -
{stateFieldData - .filter(o => o.predefined) - .map((o, i) =>
-
- -
- {rowsData.map((c, k) => { - return
-
- {properSubField(c, k, o.name)} -
-
- })} -
-
-
)} + .filter(o => o.predefined).length > 0 + ?
+ + {stateFieldData + //.filter(o => o.predefined) + .map((o, i) => + o.predefined + ? +
+ {rowsData.map((c, k) => { + return
+ {properSubField(c, k, o.name)} +
+ })} +
+
: null)} +
+
+ : null} + {lastRow()} ) } diff --git a/src/pages/BandoFormsPreview/index.js b/src/pages/BandoFormsPreview/index.js index 8d34160..d9e3d30 100644 --- a/src/pages/BandoFormsPreview/index.js +++ b/src/pages/BandoFormsPreview/index.js @@ -155,8 +155,8 @@ const BandoFormsPreview = () => { }, {}); return ['paragraph'].includes(o.name) && text - ?
-
+ ?
+
{renderHtmlContent(text.value)}