diff --git a/src/assets/scss/components/appForm.scss b/src/assets/scss/components/appForm.scss index 2f5ef85..dad056e 100644 --- a/src/assets/scss/components/appForm.scss +++ b/src/assets/scss/components/appForm.scss @@ -59,11 +59,8 @@ &.table, &.criteria_table { div.addNewTableRow { - width: 100%; text-align: center; - padding: 5px 0; - background: var(--table-border-color); - color: var(--primary-text); + justify-content: center; &:hover { cursor: pointer; @@ -99,14 +96,12 @@ min-width: 120px; input { width: 100%; - padding: 3px 5px; } } - tfoot td, - tfoot th { + tfoot td { + border-top: 1px solid var(--table-border-color); border-top: 1px solid var(--table-border-color); - border-bottom: 0 } table.striped tbody tr:nth-child(odd) td, diff --git a/src/assets/scss/components/formBuilder.scss b/src/assets/scss/components/formBuilder.scss index 178cd4a..db9b8ad 100644 --- a/src/assets/scss/components/formBuilder.scss +++ b/src/assets/scss/components/formBuilder.scss @@ -181,7 +181,7 @@ gap: 0.5rem; } -.formElementSettings__fieldDescription { +.formElementSettings__fieldDescription, .formElementSettings__fieldVarsList { padding: 15px; background-color: #ffe0c5; border: 1px solid #e6a973; @@ -191,14 +191,31 @@ color: #c68e5e; font-size: 15px; line-height: 1.5; + } - code { - font-size: 14px; - padding: 3px 6px; - border: 1px solid #e1b48b; - background-color: #fbeadb; - border-radius: 3px; - } + code { + font-size: 14px; + padding: 3px 6px; + border: 1px solid #e1b48b; + background-color: #fbeadb; + border-radius: 3px; + user-select: all; + } +} + +.formElementSettings__fieldVarsList { + background-color: #e7fddd; + border: 1px solid #9de673; + + p { + color: #5eae30; + } + + code { + border: 1px solid #9de673; + background-color: #effaea; + margin-right: 4px; + user-select: all; } } diff --git a/src/components/FormField/components/CriteriaTable/RenderTable/components/DefaultCell/index.js b/src/components/FormField/components/CriteriaTable/RenderTable/components/DefaultCell/index.js index 6351f92..0df7324 100644 --- a/src/components/FormField/components/CriteriaTable/RenderTable/components/DefaultCell/index.js +++ b/src/components/FormField/components/CriteriaTable/RenderTable/components/DefaultCell/index.js @@ -1,24 +1,19 @@ +import { InputText } from 'primereact/inputtext'; + 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} + disabled={disabled} onFocus={onFocus} - className="w-full px-2 py-1 border rounded" - /> + onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)} /> ); }; diff --git a/src/components/FormField/components/CriteriaTable/RenderTable/components/NumericFormulaCell/index.js b/src/components/FormField/components/CriteriaTable/RenderTable/components/NumericFormulaCell/index.js index 58a6f25..75f3b3a 100644 --- a/src/components/FormField/components/CriteriaTable/RenderTable/components/NumericFormulaCell/index.js +++ b/src/components/FormField/components/CriteriaTable/RenderTable/components/NumericFormulaCell/index.js @@ -1,32 +1,28 @@ +import { InputNumber } from 'primereact/inputnumber'; + 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); - } + const onChange = (value) => { + table.options.meta?.updateData(index, id, value); }; return ( - onChange(e.value)} onFocus={onFocus} - onBlur={onBlur} - step="any" - className="w-full px-2 py-1 border rounded" + minFractionDigits={0} + maxFractionDigits={2} + locale='it-IT' + useGrouping={false} + showButtons /> ); }; diff --git a/src/components/FormField/components/CriteriaTable/RenderTable/index.js b/src/components/FormField/components/CriteriaTable/RenderTable/index.js index c15d7c8..e888433 100644 --- a/src/components/FormField/components/CriteriaTable/RenderTable/index.js +++ b/src/components/FormField/components/CriteriaTable/RenderTable/index.js @@ -82,17 +82,17 @@ const RenderTable = ({ tableValue = {}, columnsCfg, lastRowCfg, setTableValueFn, ); })} + {!isEmpty(lastRowCfg) - ? + ? {columnsCfg.map((o) => )} - + : null} - ) } diff --git a/src/components/FormField/components/CriteriaTable/index.js b/src/components/FormField/components/CriteriaTable/index.js index 3801617..f965321 100644 --- a/src/components/FormField/components/CriteriaTable/index.js +++ b/src/components/FormField/components/CriteriaTable/index.js @@ -58,10 +58,10 @@ const Table = ({ } } - if (o.predefined) { - item.cell = (info) => info.getValue(); - } else if (o.enableFormula || o.fieldtype === 'numeric') { + if (o.enableFormula || o.fieldtype === 'numeric') { item.cell = NumericFormulaCell; + } else { + item.cell = (info) => info.getValue(); } return item; @@ -84,7 +84,7 @@ const Table = ({ let rowsData = pathOr([obj], ['rowsData'], tableColumns); rowsData = isEmpty(rowsData) ? [obj] : rowsData; setColumnsCfg(stateFieldData); - setRowsCfg({rows: rowsData, total: 0}); + setRowsCfg({ rows: rowsData, total: 0 }); let lastRowData = stateFieldData.reduce((acc, cur) => { const value = cur.enableFormula ? cur.lastRowFormula : (cur.lastRowText ? cur.lastRowText : ''); diff --git a/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js b/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js index 6351f92..0df7324 100644 --- a/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js +++ b/src/components/FormField/components/Table/RenderTable/components/DefaultCell/index.js @@ -1,24 +1,19 @@ +import { InputText } from 'primereact/inputtext'; + 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} + disabled={disabled} onFocus={onFocus} - className="w-full px-2 py-1 border rounded" - /> + onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)} /> ); }; diff --git a/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js b/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js index 58a6f25..75f3b3a 100644 --- a/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js +++ b/src/components/FormField/components/Table/RenderTable/components/NumericFormulaCell/index.js @@ -1,32 +1,28 @@ +import { InputNumber } from 'primereact/inputnumber'; + 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); - } + const onChange = (value) => { + table.options.meta?.updateData(index, id, value); }; return ( - onChange(e.value)} onFocus={onFocus} - onBlur={onBlur} - step="any" - className="w-full px-2 py-1 border rounded" + minFractionDigits={0} + maxFractionDigits={2} + locale='it-IT' + useGrouping={false} + showButtons /> ); }; diff --git a/src/components/FormField/components/Table/RenderTable/index.js b/src/components/FormField/components/Table/RenderTable/index.js index 43cf9ac..c925bcd 100644 --- a/src/components/FormField/components/Table/RenderTable/index.js +++ b/src/components/FormField/components/Table/RenderTable/index.js @@ -68,17 +68,17 @@ const RenderTable = ({ rowsData, columnsCfg, lastRowCfg, setRowsFn, disabled }) ); })} + {!isEmpty(lastRowCfg) - ? + ? {columnsCfg.map((o) => )} - + : null} - ) } diff --git a/src/components/FormField/components/Table/index.js b/src/components/FormField/components/Table/index.js index c925b08..02d33be 100644 --- a/src/components/FormField/components/Table/index.js +++ b/src/components/FormField/components/Table/index.js @@ -176,7 +176,7 @@ const Table = ({ setRowsFn={updateRows} disabled={disabled}/> : null} {!isEmpty(columns) && !shouldDisableNewRows - ?
+ ?
{__('Aggiungi una riga', 'gepafin')}
: null} diff --git a/src/helpers/keepKeys.js b/src/helpers/keepKeys.js new file mode 100644 index 0000000..170bbe6 --- /dev/null +++ b/src/helpers/keepKeys.js @@ -0,0 +1,3 @@ +const keepKeys = (arr, keys) => arr.map(obj => Object.fromEntries(keys.map(k => [k, obj[k]]))); + +export default keepKeys; \ No newline at end of file diff --git a/src/helpers/removeKey.js b/src/helpers/removeKey.js new file mode 100644 index 0000000..fc591a9 --- /dev/null +++ b/src/helpers/removeKey.js @@ -0,0 +1,3 @@ +const removeKey = (arr, key) => arr.map(({[key]: _, ...rest}) => rest); + +export default removeKey; \ No newline at end of file diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js index cb50706..ed7fa42 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js @@ -1,6 +1,9 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { __ } from '@wordpress/i18n'; -import { is } from 'ramda'; +import { head, is, isEmpty, isNil, uniq } from 'ramda'; + +// store +import { storeGet } from '../../../../../../store'; // tools import renderHtmlContent from '../../../../../../helpers/renderHtmlContent'; @@ -19,6 +22,8 @@ import { mimeTypes } from '../../../../../../configData'; const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { + const [existingVars, setExistingVars] = useState([]); + const settingLabels = { label: __('Label', 'gepafin'), placeholder: __('Segnaposto', 'gepafin'), @@ -72,7 +77,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { options={mimeTypes} optionLabel="name" display="chip" - placeholder={__('Scegli', 'gepafin')} /> + placeholder={__('Scegli', 'gepafin')}/> } else if (setting.name === 'text') { return { } } + useEffect(() => { + const elements = storeGet.main.formElements(); + const activeElement = storeGet.main.activeElement(); + const vars = elements + .filter(o => o.id !== activeElement) + // eslint-disable-next-line + .map((o) => { + const variableSetting = head(o.settings.filter(s => s.name === 'variable')); + if (variableSetting) { + return variableSetting.value[0]; + } + }) + .filter(v => !isNil(v)); + + setExistingVars(uniq(vars)); + }, []); + return
{getProperField(setting)} + {setting.name === 'formula' && !isEmpty(existingVars) + ?
+

Existing variables: {existingVars.map(v => {`{${v}}`})}

+
: null} {settingDescription[setting.name] ?

{renderHtmlContent(settingDescription[setting.name])}

-
: null} +
: null}
} diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingCriteriaTableColumns/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingCriteriaTableColumns/index.js index 0053d76..cd1a251 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingCriteriaTableColumns/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingCriteriaTableColumns/index.js @@ -1,17 +1,18 @@ import React, { useCallback, useEffect, useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import { wrap } from 'object-path-immutable'; -import { isEmpty, pathOr } from 'ramda'; +import { isEmpty, last, pathOr } from 'ramda'; // components import { InputText } from 'primereact/inputtext'; import { Button } from 'primereact/button'; import { InputSwitch } from 'primereact/inputswitch'; +import { Dropdown } from 'primereact/dropdown'; +import { Accordion, AccordionTab } from 'primereact/accordion'; // tools import uniqid from '../../../../../../helpers/uniqid'; -import { Dropdown } from 'primereact/dropdown'; -import { Accordion, AccordionTab } from 'primereact/accordion'; +import removeKey from '../../../../../../helpers/removeKey'; const ElementSettingCriteriaTableColumns = ({ value, @@ -24,13 +25,15 @@ const ElementSettingCriteriaTableColumns = ({ const removeItem = (index) => { let newData = stateFieldData - .toSpliced(index, 1) + .toSpliced(index, 1); newData = newData.map((o, i) => { return i === newData.length - 1 ? {...o, fieldtype: 'numeric', predefined: false, enableFormula: true} : {...o, fieldtype: 'text', predefined: true, enableFormula: false} }); setStateFieldData(newData); + const newRowsData = removeKey(rowsData, last(newData.map(o => o.name))); + setRowsData(newRowsData); } const addNewItem = () => { diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingTableColumns/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingTableColumns/index.js index 30eb834..cb2337a 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingTableColumns/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingTableColumns/index.js @@ -1,17 +1,18 @@ import React, { useCallback, useEffect, useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import { wrap } from 'object-path-immutable'; -import { isEmpty, pathOr } from 'ramda'; +import { isEmpty, last, pathOr } from 'ramda'; // components import { InputText } from 'primereact/inputtext'; import { Button } from 'primereact/button'; import { InputSwitch } from 'primereact/inputswitch'; +import { Dropdown } from 'primereact/dropdown'; +import { Accordion, AccordionTab } from 'primereact/accordion'; // tools import uniqid from '../../../../../../helpers/uniqid'; -import { Dropdown } from 'primereact/dropdown'; -import { Accordion, AccordionTab } from 'primereact/accordion'; +import removeKey from '../../../../../../helpers/removeKey'; const ElementSettingTableColumns = ({ value, @@ -25,6 +26,8 @@ const ElementSettingTableColumns = ({ const removeItem = (index) => { const newData = stateFieldData.toSpliced(index, 1); setStateFieldData(newData); + const newRowsData = removeKey(rowsData, last(newData.map(o => o.name))); + setRowsData(newRowsData); } const addNewItem = () => { diff --git a/src/pages/BandoFormsPreview/index.js b/src/pages/BandoFormsPreview/index.js index 4f2de9e..7da1102 100644 --- a/src/pages/BandoFormsPreview/index.js +++ b/src/pages/BandoFormsPreview/index.js @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { __ } from '@wordpress/i18n'; import { useNavigate, useParams } from 'react-router-dom'; import { klona } from 'klona'; -import { head, isNil , isEmpty } from 'ramda'; +import { head, isNil, isEmpty, pathOr } from 'ramda'; import { useForm } from 'react-hook-form'; import 'quill/dist/quill.core.css'; import { evaluate } from 'mathjs'; @@ -84,23 +84,6 @@ const BandoFormsPreview = () => { if (data.status === 'SUCCESS') { setFormName(data.data.label); const elements = klona(data.data.content); - let allvars = {}; - let allformulas = {}; - - // eslint-disable-next-line array-callback-return - elements.map((o) => { - const variable = head(o.settings.filter(o => o.name === 'variable')); - if (variable && !isEmpty(variable.value)) { - allvars[o.id] = variable.value[0]; - } - const formula = head(o.settings.filter(o => o.name === 'formula')); - if (formula && !isEmpty(formula.value)) { - allformulas[o.id] = formula.value; - } - }); - - setFieldsWithVars(allvars); - setFieldsWithFormula(allformulas); setFormData(elements); } storeSet.main.unsetAsyncRequest(); @@ -112,37 +95,39 @@ const BandoFormsPreview = () => { } useEffect(() => { - if (!isEmpty(fieldsWithVars) && !isEmpty(fieldsWithFormula)) { - const updatedFormValues = klona(formValues); - let context = {}; + let updatedFormValues = klona(formValues); + let context = {}; - // eslint-disable-next-line array-callback-return - Object.keys(updatedFormValues).map(fieldId => { - if (!isNil(fieldsWithFormula[fieldId])) { - const formula = fieldsWithFormula[fieldId]; - context = getTokens(formula) - .filter(v => !['false', 'null', 'true'].includes(v)) - .reduce((acc, cur) => { - acc[cur] = isNil(context[cur]) ? 0 : context[cur]; - return acc; - }, {}); - const mathFormula = renderWithDataVars(formula, context); - try { - updatedFormValues[fieldId] = evaluate(mathFormula); - } catch (e) { - console.log('Error in math formula: "', mathFormula, '"', e.message); - updatedFormValues[fieldId] = 0; - } - } - if (!isNil(fieldsWithVars[fieldId])) { - context[fieldsWithVars[fieldId]] = updatedFormValues[fieldId] - } - }); + // eslint-disable-next-line array-callback-return + formData.map((o) => { + const variable = head(o.settings.filter(o => o.name === 'variable')); + const formula = head(o.settings.filter(o => o.name === 'formula')); - if (!isEmpty(updatedFormValues) && !equal(updatedFormValues, formValues)) { - reset(updatedFormValues); + if (formula && !isEmpty(formula.value)) { + context = getTokens(formula.value) + .filter(v => !['false', 'null', 'true'].includes(v)) + .reduce((acc, cur) => { + acc[cur] = isNil(context[cur]) ? 0 : context[cur]; + return acc; + }, context); + const mathFormula = renderWithDataVars(formula.value, context); + try { + updatedFormValues[o.id] = evaluate(mathFormula); + } catch (e) { + console.log('Error in math formula: "', mathFormula, '"', e.message); + updatedFormValues[o.id] = 0; + } } + if (variable && !isEmpty(variable.value)) { + context[variable.value[0]] = 'criteria_table' === o.name + ? pathOr(0, [o.id, 'total'], updatedFormValues) + : pathOr(0, [o.id], updatedFormValues); + } + }); + + if (!isEmpty(updatedFormValues) && !equal(updatedFormValues, formValues)) { + reset(updatedFormValues); } }, [formValues]); diff --git a/src/pages/ResetPassword/index.js b/src/pages/ResetPassword/index.js index a43724f..6f3364d 100644 --- a/src/pages/ResetPassword/index.js +++ b/src/pages/ResetPassword/index.js @@ -1,8 +1,8 @@ -import React, { useRef, useState, useEffect, useMemo } from 'react'; +import React, { useRef, useState, useEffect } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import { useForm } from 'react-hook-form'; import { classNames } from 'primereact/utils'; -import { isEmpty, isNil } from 'ramda'; +import { isEmpty } from 'ramda'; import { useNavigate, useSearchParams } from 'react-router-dom'; // tools