- updated code, added new settings;

This commit is contained in:
Vitalii Kiiko
2025-01-17 15:46:29 +01:00
parent 57995e9646
commit 61763a961b
9 changed files with 114 additions and 167 deletions

View File

@@ -58,6 +58,11 @@
flex-direction: column; flex-direction: column;
gap: 5px; gap: 5px;
align-items: flex-start; align-items: flex-start;
.tagHeader {
display: flex;
gap: 10px;
}
} }
.label { .label {

View File

@@ -31,6 +31,10 @@
} }
} }
.p-tag { .p-tag {
&.p-tag-secondary {
background-color: var(--table-border-color);
}
.p-tag-value { .p-tag-value {
color: var(--menuitem-active-color); color: var(--menuitem-active-color);
} }
@@ -147,7 +151,7 @@
max-width: 100%; max-width: 100%;
} }
.p-dropdown { .p-dropdown, .p-chips, .p-chips-multiple-container {
width: 100%; width: 100%;
} }

View File

@@ -1,7 +1,8 @@
import React, { useRef } from 'react' import React, { useEffect, useRef, useState } from 'react'
import { useDrag, useDrop } from 'react-dnd' import { useDrag, useDrop } from 'react-dnd'
import { ItemTypes } from '../ItemTypes'; import { ItemTypes } from '../ItemTypes';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { head, isEmpty } from 'ramda';
// store // store
import { storeSet, useStore } from '../../../../store'; import { storeSet, useStore } from '../../../../store';
@@ -14,6 +15,10 @@ import BuilderElementProperLabel from '../BuilderElementProperLabel';
const BuilderElement = ({ id, name, label, index, bandoStatus }) => { const BuilderElement = ({ id, name, label, index, bandoStatus }) => {
const draggingElementId = useStore().main.draggingElementId(); const draggingElementId = useStore().main.draggingElementId();
const ref = useRef(null); const ref = useRef(null);
const elements = useStore().main.formElements();
const element = head(elements.filter(o => o.id === id));
const [isVariable, setIsVariable] = useState('secondary');
const [isFormula, setIsFormula] = useState('secondary');
const [{ handlerId }, drop] = useDrop({ const [{ handlerId }, drop] = useDrop({
accept: ItemTypes.FIELD, accept: ItemTypes.FIELD,
@@ -97,6 +102,19 @@ const BuilderElement = ({ id, name, label, index, bandoStatus }) => {
const opacity = isDragging ? 0 : 1; const opacity = isDragging ? 0 : 1;
drag(drop(ref)); drag(drop(ref));
useEffect(() => {
const variable = head(element.settings.filter(o => o.name === 'variable'));
const formula = head(element.settings.filter(o => o.name === 'formula'));
if (variable && !isEmpty(variable.value)) {
setIsVariable('warning');
}
if (formula && !isEmpty(formula.value)) {
setIsFormula('warning');
}
}, [elements]);
return ( return (
draggingElementId === id draggingElementId === id
? <div ref={ref} className="formBuilder__elementNew"> ? <div ref={ref} className="formBuilder__elementNew">
@@ -104,7 +122,13 @@ const BuilderElement = ({ id, name, label, index, bandoStatus }) => {
</div> </div>
: <div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}> : <div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}>
<div className="meta"> <div className="meta">
<Tag value={label} severity="info"/> <div className="tagHeader">
<Tag value={label} severity="info"/>
{name === 'numberinput'
? <Tag value="var" severity={isVariable}/> : null}
{name === 'numberinput'
? <Tag value="f(x)" severity={isFormula}/> : null}
</div>
<BuilderElementProperLabel id={id} defaultLabel={label}/> <BuilderElementProperLabel id={id} defaultLabel={label}/>
</div> </div>
<div className="actions"> <div className="actions">

View File

@@ -11,6 +11,7 @@ import { Editor } from 'primereact/editor';
import { mimeTypes } from '../../../../../../configData'; import { mimeTypes } from '../../../../../../configData';
import ElementSettingTableColumns from '../ElementSettingTableColumns'; import ElementSettingTableColumns from '../ElementSettingTableColumns';
import { InputSwitch } from 'primereact/inputswitch'; import { InputSwitch } from 'primereact/inputswitch';
import ElementSettingChips from '../ElementSettingChips';
const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
@@ -24,6 +25,8 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
mime: __('Tipo di file', 'gepafin'), mime: __('Tipo di file', 'gepafin'),
text: __('Testo formattato', 'gepafin'), text: __('Testo formattato', 'gepafin'),
table_columns: '', table_columns: '',
variable: __('Variable (only letters and "_")', 'gepafin'),
formula: __('Auto calculation formula', 'gepafin')
} }
const renderHeader = () => { const renderHeader = () => {
@@ -85,6 +88,11 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
return <InputSwitch return <InputSwitch
checked={setting.value} checked={setting.value}
onChange={(e) => changeFn(e.value, setting.name)}/> onChange={(e) => changeFn(e.value, setting.name)}/>
} else if (['variable'].includes(setting.name)) {
return <ElementSettingChips
restrictedValues={[]}
changeFn={(value) => changeFn(value, setting.name)}
value={setting.value}/>
} else { } else {
return <InputText id={setting.name} aria-describedby={`${setting.name}-help`} return <InputText id={setting.name} aria-describedby={`${setting.name}-help`}
value={setting.value} value={setting.value}

View File

@@ -0,0 +1,43 @@
import React, { useState } from 'react';
// components
import { Chips } from 'primereact/chips';
const ElementSettingChips = ({ restrictedValues = [], changeFn, value }) => {
const [lastTyped, setLastTyped] = useState([])
const isValidValue = (newVal) => {
const validationRegex = /^[a-zA-Z_]+$/;
return validationRegex.test(newVal);
};
const handleAdd = (e) => {
const newValue = e.value[e.value.length - 1];
if (restrictedValues.includes(newValue)) {
changeFn([]);
return;
}
if (!isValidValue(newValue)) {
changeFn(lastTyped);
return;
}
setLastTyped(e.value)
changeFn(e.value);
};
return (
<div>
<Chips
value={value}
addOnBlur={true}
onChange={handleAdd}
max={1}
/>
</div>
);
}
export default ElementSettingChips;

View File

@@ -1,159 +0,0 @@
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,
bandoStatus
}) => {
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}
disabled={bandoStatus === 'PUBLISH'}
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" disabled={bandoStatus === 'PUBLISH'} className="p-button-danger" onClick={() => removeItem(i)}/>
</div>
</div>)}
<Button type="button" disabled={bandoStatus === 'PUBLISH'} 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"
disabled={bandoStatus === 'PUBLISH'}
className="p-button-danger"
onClick={() => removeRow(k)}/>
</div>
</div>
})}
<Button type="button"
outlined
disabled={bandoStatus === 'PUBLISH'}
label={__('Aggiungi una riga', 'gepafin')}
onClick={addNewRow}/>
</div>
</div>
</div>)}
</>
)
}
export default ElementSettingTableColumns;

View File

@@ -160,7 +160,9 @@ const BuilderElementSettings = ({ closeSettingsFn, bandoStatus }) => {
<TabView className="formElementSettings__tabs"> <TabView className="formElementSettings__tabs">
<TabPanel header={__('Presentation', 'gepafin')}> <TabPanel header={__('Presentation', 'gepafin')}>
{settings {settings
? settings.map((o) => <ElementSetting ? settings
.filter(o => !['variable', 'formula'].includes(o.name))
.map((o) => <ElementSetting
key={o.name} key={o.name}
setting={o} setting={o}
bandoStatus={bandoStatus} bandoStatus={bandoStatus}
@@ -248,6 +250,18 @@ const BuilderElementSettings = ({ closeSettingsFn, bandoStatus }) => {
placeholder={__('Scegli', 'gepafin')}/> placeholder={__('Scegli', 'gepafin')}/>
</div> </div>
</TabPanel> </TabPanel>
<TabPanel header={__('Calculation', 'gepafin')}>
{settings
? settings
.filter(o => ['variable', 'formula'].includes(o.name))
.map((o) => <ElementSetting
key={o.name}
setting={o}
bandoStatus={bandoStatus}
changeFn={onChange}
updateDataFn={onUpdateOptions}/>)
: null}
</TabPanel>
</TabView> </TabView>
<Button label={__('Salva', 'gepafin')} onClick={saveSettings}/> <Button label={__('Salva', 'gepafin')} onClick={saveSettings}/>

View File

@@ -24,7 +24,7 @@ import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import BandoService from '../../service/bando-service'; import BandoService from '../../service/bando-service';
// TODO temp data // TODO temp data
//import { elementItems } from '../../tempData'; import { elementItems } from '../../tempData';
const BandoFormsEdit = () => { const BandoFormsEdit = () => {
const { id, formId } = useParams(); const { id, formId } = useParams();
@@ -215,8 +215,8 @@ const BandoFormsEdit = () => {
const getElementItemsCallback = (data) => { const getElementItemsCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
//storeSet.main.elementItems(elementItems.sort((a, b) => a.sortOrder - b.sortOrder)); storeSet.main.elementItems(elementItems.sort((a, b) => a.sortOrder - b.sortOrder));
storeSet.main.elementItems(data.data.sort((a, b) => a.sortOrder - b.sortOrder)); //storeSet.main.elementItems(data.data.sort((a, b) => a.sortOrder - b.sortOrder));
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }

View File

@@ -92,7 +92,15 @@ export const elementItems = [
{ {
name: "isRequestedAmount", name: "isRequestedAmount",
value: false value: false
} },
{
name: "variable",
value: ""
},
{
name: "formula",
value: ""
},
], ],
validators: { validators: {
isRequired: false, isRequired: false,