- added Table field;
This commit is contained in:
@@ -45,6 +45,20 @@
|
|||||||
input[disabled], div.p-disabled:not(.p-inputswitch) {
|
input[disabled], div.p-disabled:not(.p-inputswitch) {
|
||||||
background-color: #e3e3e3;
|
background-color: #e3e3e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.table {
|
||||||
|
div.addNewTableRow {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
background: var(--table-border-color);
|
||||||
|
color: var(--primary-text);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.appForm__fieldItem {
|
.appForm__fieldItem {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
.label {
|
.label {
|
||||||
p {
|
p {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 0;
|
||||||
|
|
||||||
&.ql-indent-1 {
|
&.ql-indent-1 {
|
||||||
padding-left: 3em;
|
padding-left: 3em;
|
||||||
@@ -179,4 +179,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formElementSettings__repeaterItem {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.formElementSettings__subRepeater {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -102,4 +103,48 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:where(table) {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
text-indent: 0;
|
||||||
|
border-right: 1px solid var(--table-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid var(--table-border-color);
|
||||||
|
border-bottom: 1px solid var(--table-border-color);
|
||||||
|
border-left: 1px solid var(--table-border-color);
|
||||||
|
background-color: white;
|
||||||
|
color: var(--global-textColor);
|
||||||
|
font-size: 15px;
|
||||||
|
text-align: left;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 15px 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 3px 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tfoot td,
|
||||||
|
tfoot th {
|
||||||
|
border-top: 1px solid var(--table-border-color);
|
||||||
|
border-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
table.striped tbody tr:nth-child(odd) td,
|
||||||
|
table.striped tbody tr:nth-child(odd) th {
|
||||||
|
background-color: var(--table-border-color)
|
||||||
}
|
}
|
||||||
@@ -106,6 +106,16 @@
|
|||||||
background-color: rgba(255,255,255,0.3)
|
background-color: rgba(255,255,255,0.3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-inputgroup {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.mb-2 {
|
.mb-2 {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,10 @@
|
|||||||
--global-textColor: #4B5563;
|
--global-textColor: #4B5563;
|
||||||
--theme-highlight-background: #BADEBE;
|
--theme-highlight-background: #BADEBE;
|
||||||
--primary-text: #3B7C43;
|
--primary-text: #3B7C43;
|
||||||
|
--table-border-color: #B7B7B7B2;
|
||||||
--message-error-background: #ffdbdb;
|
--message-error-background: #ffdbdb;
|
||||||
--message-error-color: #C2504D;
|
--message-error-color: #C2504D;
|
||||||
--message-info-background: rgba(219, 234, 254, 0.70);
|
--message-info-background: rgba(183, 183, 183, 0.7);
|
||||||
--message-info-color: #3B82F6;
|
--message-info-color: #3B82F6;
|
||||||
|
|
||||||
--card-full-background-color-2: #EEC137;
|
--card-full-background-color-2: #EEC137;
|
||||||
|
|||||||
150
src/components/FormField/components/Table/index.js
Normal file
150
src/components/FormField/components/Table/index.js
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { classNames } from 'primereact/utils';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import {
|
||||||
|
useReactTable,
|
||||||
|
getCoreRowModel,
|
||||||
|
flexRender,
|
||||||
|
} from '@tanstack/react-table';
|
||||||
|
import { pathOr, isEmpty } from 'ramda';
|
||||||
|
import { wrap } from 'object-path-immutable';
|
||||||
|
|
||||||
|
const Table = ({
|
||||||
|
fieldName,
|
||||||
|
label,
|
||||||
|
register,
|
||||||
|
errors,
|
||||||
|
config = {},
|
||||||
|
defaultValue = [],
|
||||||
|
tableColumns = []
|
||||||
|
}) => {
|
||||||
|
const [stateFieldData, setStateFieldData] = useState([]);
|
||||||
|
const [rowsData, setRowsData] = useState([]);
|
||||||
|
const [isDisabledNewRow, setIsDisabledNewRow] = useState(false);
|
||||||
|
const [columns, setColumns] = useState([]);
|
||||||
|
const table = useReactTable({
|
||||||
|
data: rowsData,
|
||||||
|
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 (
|
||||||
|
<input
|
||||||
|
value={initialValue}
|
||||||
|
onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)}
|
||||||
|
onBlur={onBlur}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
meta: {
|
||||||
|
updateData: (rowIndex, columnId, value) => {
|
||||||
|
const newRowsData = wrap(rowsData).set([rowIndex, columnId], value).value();
|
||||||
|
setRowsData(newRowsData);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
debugTable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const addNewRow = () => {
|
||||||
|
const obj = stateFieldData
|
||||||
|
.reduce((acc, cur) => {
|
||||||
|
acc[cur.name] = ''
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
setRowsData([...rowsData, obj]);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let shouldDisableNewRows = false;
|
||||||
|
|
||||||
|
const columns = stateFieldData.map((o) => {
|
||||||
|
const item = {
|
||||||
|
accessorKey: o.name,
|
||||||
|
header: () => o.label,
|
||||||
|
footer: (props) => props.column.id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.predefined) {
|
||||||
|
shouldDisableNewRows = true;
|
||||||
|
item.cell = (info) => {
|
||||||
|
return info.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsDisabledNewRow(shouldDisableNewRows);
|
||||||
|
setColumns(columns);
|
||||||
|
}, [stateFieldData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||||
|
const rowsData = pathOr([], ['rowsData'], tableColumns);
|
||||||
|
setStateFieldData(stateFieldData);
|
||||||
|
setRowsData(rowsData);
|
||||||
|
}, [tableColumns]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
register(fieldName, config)
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||||
|
{label}{config.required || config.isRequired ? '*' : null}
|
||||||
|
</label>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<tr key={headerGroup.id}>
|
||||||
|
{headerGroup.headers.map((header) => {
|
||||||
|
return (
|
||||||
|
<th key={header.id} colSpan={header.colSpan}>
|
||||||
|
{header.isPlaceholder ? null : (
|
||||||
|
<>
|
||||||
|
{flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{table.getRowModel().rows.map((row) => {
|
||||||
|
return (
|
||||||
|
<tr key={row.id}>
|
||||||
|
{row.getVisibleCells().map((cell) => {
|
||||||
|
return (
|
||||||
|
<td key={cell.id}>
|
||||||
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{!isDisabledNewRow && !isEmpty(columns)
|
||||||
|
? <div className="addNewTableRow" onClick={addNewRow}>{__('Aggiungi una righa', 'gepafin')}</div>
|
||||||
|
: null}
|
||||||
|
</>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Table;
|
||||||
@@ -15,6 +15,7 @@ import Radio from './components/Radio';
|
|||||||
import Wysiwyg from './components/Wysiwyg';
|
import Wysiwyg from './components/Wysiwyg';
|
||||||
import Checkboxes from './components/Checkboxes';
|
import Checkboxes from './components/Checkboxes';
|
||||||
import Fileupload from './components/Fileupload';
|
import Fileupload from './components/Fileupload';
|
||||||
|
import Table from './components/Table';
|
||||||
|
|
||||||
const FormField = (props) => {
|
const FormField = (props) => {
|
||||||
const fields = {
|
const fields = {
|
||||||
@@ -29,7 +30,8 @@ const FormField = (props) => {
|
|||||||
select: Select,
|
select: Select,
|
||||||
radio: Radio,
|
radio: Radio,
|
||||||
wysiwyg: Wysiwyg,
|
wysiwyg: Wysiwyg,
|
||||||
checkboxes: Checkboxes
|
checkboxes: Checkboxes,
|
||||||
|
table: Table
|
||||||
}
|
}
|
||||||
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { MultiSelect } from 'primereact/multiselect';
|
|||||||
import { Editor } from 'primereact/editor';
|
import { Editor } from 'primereact/editor';
|
||||||
|
|
||||||
import { mimeTypes } from '../../../../../../configData';
|
import { mimeTypes } from '../../../../../../configData';
|
||||||
|
import ElementSettingTableColumns from '../ElementSettingTableColumns';
|
||||||
|
|
||||||
const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
|
const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
|
||||||
|
|
||||||
@@ -18,7 +19,8 @@ const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
|
|||||||
step: __('Numero Decimali', 'gepafin'),
|
step: __('Numero Decimali', 'gepafin'),
|
||||||
options: __('Opzioni', 'gepafin'),
|
options: __('Opzioni', 'gepafin'),
|
||||||
mime: __('Tipo di file', 'gepafin'),
|
mime: __('Tipo di file', 'gepafin'),
|
||||||
text: __('Testo formattato', 'gepafin')
|
text: __('Testo formattato', 'gepafin'),
|
||||||
|
table_columns: __('Colonne', 'gepafin'),
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderHeader = () => {
|
const renderHeader = () => {
|
||||||
@@ -41,31 +43,42 @@ const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
|
|||||||
|
|
||||||
const header = renderHeader();
|
const header = renderHeader();
|
||||||
|
|
||||||
return <div className="formElementSettings__field" key={setting.name}>
|
const getProperField = (setting) => {
|
||||||
<label htmlFor={setting.name}>{settingLabels[setting.name]}</label>
|
if (setting.name === 'options') {
|
||||||
{setting.name === 'options'
|
return <ElementSettingRepeater
|
||||||
? <ElementSettingRepeater
|
|
||||||
value={is(Array, setting.value) ? setting.value : []}
|
value={is(Array, setting.value) ? setting.value : []}
|
||||||
name={setting.name}
|
name={setting.name}
|
||||||
setDataFn={updateDataFn}/>
|
setDataFn={updateDataFn}/>
|
||||||
: setting.name === 'mime'
|
} else if (setting.name === 'mime') {
|
||||||
? <MultiSelect
|
return <MultiSelect
|
||||||
value={is(Array, setting.value) ? setting.value : []}
|
value={is(Array, setting.value) ? setting.value : []}
|
||||||
onChange={(e) => updateDataFn(setting.name, e.value)}
|
onChange={(e) => updateDataFn(setting.name, e.value)}
|
||||||
options={mimeTypes}
|
options={mimeTypes}
|
||||||
optionLabel="name"
|
optionLabel="name"
|
||||||
display="chip"
|
display="chip"
|
||||||
placeholder={__('Scegli', 'gepafin')} />
|
placeholder={__('Scegli', 'gepafin')} />
|
||||||
: setting.name === 'text'
|
} else if (setting.name === 'text') {
|
||||||
? <Editor
|
return <Editor
|
||||||
value={setting.value}
|
value={setting.value}
|
||||||
headerTemplate={header}
|
headerTemplate={header}
|
||||||
onTextChange={(e) => changeFn(e.htmlValue, setting.name)}
|
onTextChange={(e) => changeFn(e.htmlValue, setting.name)}
|
||||||
style={{ height: 80 * 4 }}
|
style={{ height: 80 * 4 }}
|
||||||
/>
|
/>
|
||||||
: <InputText id={setting.name} aria-describedby={`${setting.name}-help`}
|
} else if (setting.name === 'table_columns') {
|
||||||
value={setting.value}
|
return <ElementSettingTableColumns
|
||||||
onChange={(e) => changeFn(e.target.value, setting.name)}/>}
|
value={is(Object, setting.value) ? setting.value : {}}
|
||||||
|
name={setting.name}
|
||||||
|
setDataFn={updateDataFn}/>
|
||||||
|
} else {
|
||||||
|
return <InputText id={setting.name} aria-describedby={`${setting.name}-help`}
|
||||||
|
value={setting.value}
|
||||||
|
onChange={(e) => changeFn(e.target.value, setting.name)}/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="formElementSettings__field" key={setting.name}>
|
||||||
|
<label htmlFor={setting.name}>{settingLabels[setting.name]}</label>
|
||||||
|
{getProperField(setting)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,10 +45,9 @@ const ElementSettingRepeater = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('useEffect', [...stateFieldData])
|
|
||||||
setDataFn(name, [...stateFieldData]);
|
setDataFn(name, [...stateFieldData]);
|
||||||
}, [stateFieldData])
|
}, [stateFieldData])
|
||||||
console.log('stateFieldData', stateFieldData, value)
|
|
||||||
return (
|
return (
|
||||||
<div className="formElementSettings__repeater">
|
<div className="formElementSettings__repeater">
|
||||||
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { wrap } from 'object-path-immutable';
|
||||||
|
import { findIndex, propEq } from 'ramda';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { InputText } from 'primereact/inputtext';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { InputSwitch } from 'primereact/inputswitch';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import uniqid from '../../../../../../helpers/uniqid';
|
||||||
|
|
||||||
|
const ElementSettingTableColumns = ({
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
setDataFn
|
||||||
|
}) => {
|
||||||
|
const [stateFieldData, setStateFieldData] = useState([]);
|
||||||
|
const [rowsData, setRowsData] = useState([]);
|
||||||
|
|
||||||
|
const removeItem = (index) => {
|
||||||
|
const newData = stateFieldData.toSpliced(index, 1);
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addNewItem = () => {
|
||||||
|
setStateFieldData([...stateFieldData, { name: uniqid('o'), label: '', predefined: false }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addNewRow = (index) => {
|
||||||
|
const newStateFieldData = wrap(stateFieldData)
|
||||||
|
.insert([index, 'rows'], { label: '' }, stateFieldData[index].rows.length)
|
||||||
|
.value();
|
||||||
|
setStateFieldData(newStateFieldData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeRow = (index, indexK) => {
|
||||||
|
const newStateFieldData = wrap(stateFieldData)
|
||||||
|
.del([index, 'rows', indexK])
|
||||||
|
.value();
|
||||||
|
setStateFieldData(newStateFieldData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInputChange = (e, index) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
const newData = stateFieldData.map((o, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
o.label = value;
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
})
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSubInputChange = (e, index, indexK) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
const newStateFieldData = wrap(stateFieldData)
|
||||||
|
.set([index, 'rows', indexK, 'label'], value)
|
||||||
|
.value();
|
||||||
|
setStateFieldData(newStateFieldData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setChecked = (value, index) => {
|
||||||
|
const newData = stateFieldData.map((o, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
o.predefined = value;
|
||||||
|
if (value === false) {
|
||||||
|
o.rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
})
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const properField = (item, i) => {
|
||||||
|
return <>
|
||||||
|
<InputText value={item.label} onInput={(e) => onInputChange(e, i)}/>
|
||||||
|
<div className="flex-1">
|
||||||
|
<span>{__('Predefinito?', 'gepafin')}</span>
|
||||||
|
<InputSwitch checked={item.predefined} onChange={(e) => setChecked(e.value, i)}/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const properSubField = (item, i, k) => {
|
||||||
|
return <InputText value={item.label} onInput={(e) => onSubInputChange(e, i, k)}/>
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const storeFieldData = value ?? [];
|
||||||
|
setStateFieldData(storeFieldData);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDataFn(name, [...stateFieldData]);
|
||||||
|
}, [stateFieldData]);
|
||||||
|
|
||||||
|
stateFieldData.filter(o => o.predefined)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="formElementSettings__repeater">
|
||||||
|
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="p-inputgroup flex-1">
|
||||||
|
{properField(o, i)}
|
||||||
|
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
<Button type="button" outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/>
|
||||||
|
</div>
|
||||||
|
{stateFieldData
|
||||||
|
.filter(o => o.predefined)
|
||||||
|
.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="formElementSettings__repeater formElementSettings__subRepeater">
|
||||||
|
<label>{__('Righe per colonna:', 'gepafin')} <strong>{o.label}</strong></label>
|
||||||
|
<div className="formElementSettings__repeater">
|
||||||
|
{o.rows.map((c, k) => {
|
||||||
|
const properIndex = findIndex(propEq(o.name, 'name'))(stateFieldData);
|
||||||
|
return <div key={k} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="p-inputgroup flex-1">
|
||||||
|
{properSubField(c, properIndex, k)}
|
||||||
|
<Button icon="pi pi-times" className="p-button-danger"
|
||||||
|
onClick={() => removeRow(properIndex, k)}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
})}
|
||||||
|
<Button type="button" outlined
|
||||||
|
label={__('Aggiungi una righa', 'gepafin')}
|
||||||
|
onClick={() => addNewRow(findIndex(propEq(o.name, 'name'))(stateFieldData))}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ElementSettingTableColumns;
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { wrap } from 'object-path-immutable';
|
||||||
|
import { pathOr } from 'ramda';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import { InputText } from 'primereact/inputtext';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { InputSwitch } from 'primereact/inputswitch';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import uniqid from '../../../../../../helpers/uniqid';
|
||||||
|
|
||||||
|
const ElementSettingTableColumns = ({
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
setDataFn
|
||||||
|
}) => {
|
||||||
|
const [stateFieldData, setStateFieldData] = useState([]);
|
||||||
|
const [rowsData, setRowsData] = useState([]);
|
||||||
|
|
||||||
|
const removeItem = (index) => {
|
||||||
|
const newData = stateFieldData.toSpliced(index, 1);
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addNewItem = () => {
|
||||||
|
setStateFieldData([...stateFieldData, { name: uniqid('o'), label: '', predefined: false }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addNewRow = () => {
|
||||||
|
const obj = stateFieldData
|
||||||
|
.filter(o => o.predefined)
|
||||||
|
.reduce((acc, cur) => {
|
||||||
|
acc[cur.name] = ''
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
setRowsData([...rowsData, obj]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeRow = (index) => {
|
||||||
|
const newRowsData = wrap(rowsData).del([index]).value();
|
||||||
|
setRowsData(newRowsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInputChange = (e, index) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
const newData = stateFieldData.map((o, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
o.label = value;
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
})
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSubInputChange = (e, name, index) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
const newRowsData = wrap(rowsData).set([index, name], value).value();
|
||||||
|
setRowsData(newRowsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setChecked = (value, index) => {
|
||||||
|
let name = '';
|
||||||
|
const newData = stateFieldData.map((o, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
o.predefined = value;
|
||||||
|
name = o.name;
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
});
|
||||||
|
|
||||||
|
let newRowsData = [];
|
||||||
|
|
||||||
|
if (value === false) {
|
||||||
|
newRowsData = rowsData.map(o => wrap(o).set([name], '').value());
|
||||||
|
} else {
|
||||||
|
newRowsData = rowsData.map(o => wrap(o).set([name], '').value());
|
||||||
|
}
|
||||||
|
|
||||||
|
setRowsData(newRowsData);
|
||||||
|
setStateFieldData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const properField = (item, i) => {
|
||||||
|
return <>
|
||||||
|
<InputText value={item.label} onInput={(e) => onInputChange(e, i)}/>
|
||||||
|
<div className="flex-1">
|
||||||
|
<span>{__('Predefinito?', 'gepafin')}</span>
|
||||||
|
<InputSwitch checked={item.predefined} onChange={(e) => setChecked(e.value, i)}/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const properSubField = (item, i, name) => {
|
||||||
|
return <InputText value={item[name]} onInput={(e) => onSubInputChange(e, name, i)}/>
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const stateFieldData = pathOr([], ['stateFieldData'], value);
|
||||||
|
setStateFieldData(stateFieldData);
|
||||||
|
const rowsData = pathOr([], ['rowsData'], value);
|
||||||
|
setRowsData(rowsData);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDataFn(name, {
|
||||||
|
stateFieldData,
|
||||||
|
rowsData
|
||||||
|
});
|
||||||
|
}, [stateFieldData, rowsData]);
|
||||||
|
|
||||||
|
stateFieldData.filter(o => o.predefined)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="formElementSettings__repeater">
|
||||||
|
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="p-inputgroup flex-1">
|
||||||
|
{properField(o, i)}
|
||||||
|
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
<Button type="button" outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/>
|
||||||
|
</div>
|
||||||
|
{stateFieldData
|
||||||
|
.filter(o => o.predefined)
|
||||||
|
.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="formElementSettings__repeater formElementSettings__subRepeater">
|
||||||
|
<label>{__('Righe per colonna:', 'gepafin')} <strong>{o.label}</strong></label>
|
||||||
|
<div className="formElementSettings__repeater">
|
||||||
|
{rowsData.map((c, k) => {
|
||||||
|
return <div key={k} className="formElementSettings__repeaterItem">
|
||||||
|
<div className="p-inputgroup flex-1">
|
||||||
|
{properSubField(c, k, o.name)}
|
||||||
|
<Button icon="pi pi-times" className="p-button-danger"
|
||||||
|
onClick={() => removeRow(k)}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
})}
|
||||||
|
<Button type="button" outlined
|
||||||
|
label={__('Aggiungi una righa', 'gepafin')}
|
||||||
|
onClick={addNewRow}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ElementSettingTableColumns;
|
||||||
@@ -121,6 +121,7 @@ const BandoFormsPreview = () => {
|
|||||||
const text = head(o.settings.filter(o => o.name === 'text'));
|
const text = head(o.settings.filter(o => o.name === 'text'));
|
||||||
const placeholder = head(o.settings.filter(o => o.name === 'placeholder'));
|
const placeholder = head(o.settings.filter(o => o.name === 'placeholder'));
|
||||||
const options = head(o.settings.filter(o => o.name === 'options'));
|
const options = head(o.settings.filter(o => o.name === 'options'));
|
||||||
|
const tableColumns = head(o.settings.filter(o => o.name === 'table_columns'));
|
||||||
const step = head(o.settings.filter(o => o.name === 'step'));
|
const step = head(o.settings.filter(o => o.name === 'step'));
|
||||||
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||||
let mimeValue = '';
|
let mimeValue = '';
|
||||||
@@ -166,6 +167,7 @@ const BandoFormsPreview = () => {
|
|||||||
options={options ? options.value : []}
|
options={options ? options.value : []}
|
||||||
setDataFn={setValue}
|
setDataFn={setValue}
|
||||||
sourceId={0}
|
sourceId={0}
|
||||||
|
tableColumns={tableColumns.value ? tableColumns.value : {}}
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const routes = ({ role }) => {
|
|||||||
{'ROLE_BENEFICIARY' === role ? <BandoApplication/> : null}
|
{'ROLE_BENEFICIARY' === role ? <BandoApplication/> : null}
|
||||||
</DefaultLayout>}/>
|
</DefaultLayout>}/>
|
||||||
<Route path="/profilo" element={<DefaultLayout>
|
<Route path="/profilo" element={<DefaultLayout>
|
||||||
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
|
{'ROLE_SUPER_ADMIN' === role ? <Profile/> : null}
|
||||||
{'ROLE_BENEFICIARY' === role ? <Profile/> : null}
|
{'ROLE_BENEFICIARY' === role ? <Profile/> : null}
|
||||||
</DefaultLayout>}/>
|
</DefaultLayout>}/>
|
||||||
<Route path="/profilo-aziendale" element={<DefaultLayout>
|
<Route path="/profilo-aziendale" element={<DefaultLayout>
|
||||||
|
|||||||
@@ -747,7 +747,7 @@ export const elementItems = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "table_columns",
|
name: "table_columns",
|
||||||
value: "Tabella"
|
value: {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
validators: {}
|
validators: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user