- updates and fixes;
This commit is contained in:
@@ -43,6 +43,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.appForm__fieldItem {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.appForm__fileUploadItem {
|
.appForm__fileUploadItem {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -73,11 +78,13 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
container-name: form_two_cols;
|
||||||
|
container-type: inline-size;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
max-width: 700px;
|
max-width: 48%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
@@ -87,6 +94,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@container form_two_cols (max-width: 620px) {
|
||||||
|
.appForm__twoCols {
|
||||||
|
> div {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.appForm__repeaterItem {
|
.appForm__repeaterItem {
|
||||||
padding: 0.5rem 0.5rem 0.5rem 1rem;
|
padding: 0.5rem 0.5rem 0.5rem 1rem;
|
||||||
border-left: 3px solid #dadada;
|
border-left: 3px solid #dadada;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { FileUpload } from 'primereact/fileupload';
|
|||||||
import { Tag } from 'primereact/tag';
|
import { Tag } from 'primereact/tag';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
|
|
||||||
const Fileupload = ({
|
const FileuploadAsync = ({
|
||||||
fieldName,
|
fieldName,
|
||||||
setDataFn,
|
setDataFn,
|
||||||
label,
|
label,
|
||||||
@@ -150,4 +150,4 @@ const Fileupload = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Fileupload;
|
export default FileuploadAsync;
|
||||||
41
src/components/FormField/components/Radio/index.js
Normal file
41
src/components/FormField/components/Radio/index.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { classNames } from 'primereact/utils';
|
||||||
|
import { Controller } from 'react-hook-form';
|
||||||
|
import { RadioButton } from 'primereact/radiobutton';
|
||||||
|
|
||||||
|
const Radio = ({
|
||||||
|
fieldName,
|
||||||
|
label,
|
||||||
|
control,
|
||||||
|
errors,
|
||||||
|
defaultValue,
|
||||||
|
config = {},
|
||||||
|
infoText = null,
|
||||||
|
options = []
|
||||||
|
}) => {
|
||||||
|
const input = <Controller
|
||||||
|
name={fieldName}
|
||||||
|
control={control}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
rules={config}
|
||||||
|
render={({ field, fieldState }) =>
|
||||||
|
options.map(o => <div className="appForm__fieldItem" key={o.name}>
|
||||||
|
<RadioButton
|
||||||
|
id={`${fieldName}_${o.name}`}
|
||||||
|
name={fieldName}
|
||||||
|
value={o.name}
|
||||||
|
onChange={(e) => field.onChange(e.value)}
|
||||||
|
checked={field.value === o.name}/>
|
||||||
|
<label htmlFor={`${fieldName}_${o.name}`}>{o.label}</label>
|
||||||
|
</div>)}/>
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||||
|
{label}{config.required ? '*' : null}
|
||||||
|
</label>
|
||||||
|
{input}
|
||||||
|
{infoText ? <small>{infoText}</small> : null}
|
||||||
|
</>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Radio;
|
||||||
50
src/components/FormField/components/Select/index.js
Normal file
50
src/components/FormField/components/Select/index.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { classNames } from 'primereact/utils';
|
||||||
|
import { Controller } from 'react-hook-form';
|
||||||
|
import { Dropdown } from 'primereact/dropdown';
|
||||||
|
|
||||||
|
const Select = ({
|
||||||
|
fieldName,
|
||||||
|
label,
|
||||||
|
control,
|
||||||
|
errors,
|
||||||
|
defaultValue,
|
||||||
|
config = {},
|
||||||
|
infoText = null,
|
||||||
|
inputgroup = false,
|
||||||
|
icon = null,
|
||||||
|
placeholder = '',
|
||||||
|
options = []
|
||||||
|
}) => {
|
||||||
|
const input = <Controller
|
||||||
|
name={fieldName}
|
||||||
|
control={control}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
rules={config}
|
||||||
|
render={({ field, fieldState }) => (
|
||||||
|
<Dropdown
|
||||||
|
value={field.value}
|
||||||
|
onChange={(e) => field.onChange(e.value)}
|
||||||
|
options={options}
|
||||||
|
optionLabel="label"
|
||||||
|
placeholder={placeholder}
|
||||||
|
className={classNames({ 'p-invalid': fieldState.invalid })}/>
|
||||||
|
)}/>
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||||
|
{label}{config.required ? '*' : null}
|
||||||
|
</label>
|
||||||
|
{inputgroup
|
||||||
|
? <div className="p-inputgroup flex-1">
|
||||||
|
<span className="p-inputgroup-addon">
|
||||||
|
{icon}
|
||||||
|
</span>
|
||||||
|
{input}
|
||||||
|
</div>
|
||||||
|
: input}
|
||||||
|
{infoText ? <small>{infoText}</small> : null}
|
||||||
|
</>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Select;
|
||||||
@@ -7,9 +7,11 @@ import TextInput from './components/TextInput';
|
|||||||
import TextArea from './components/TextArea';
|
import TextArea from './components/TextArea';
|
||||||
import Datepicker from './components/Datepicker';
|
import Datepicker from './components/Datepicker';
|
||||||
import DatepickerRange from './components/DatepickerRange';
|
import DatepickerRange from './components/DatepickerRange';
|
||||||
import Fileupload from './components/Fileupload';
|
import FileuploadAsync from './components/FileuploadAsync';
|
||||||
import NumberInput from './components/NumberInput';
|
import NumberInput from './components/NumberInput';
|
||||||
import Switch from './components/Switch';
|
import Switch from './components/Switch';
|
||||||
|
import Select from './components/Select';
|
||||||
|
import Radio from './components/Radio';
|
||||||
|
|
||||||
const FormField = (props) => {
|
const FormField = (props) => {
|
||||||
const fields = {
|
const fields = {
|
||||||
@@ -17,9 +19,11 @@ const FormField = (props) => {
|
|||||||
textarea: TextArea,
|
textarea: TextArea,
|
||||||
datepicker: Datepicker,
|
datepicker: Datepicker,
|
||||||
datepickerrange: DatepickerRange,
|
datepickerrange: DatepickerRange,
|
||||||
fileupload: Fileupload,
|
fileuploadasync: FileuploadAsync,
|
||||||
numberinput: NumberInput,
|
numberinput: NumberInput,
|
||||||
switch: Switch
|
switch: Switch,
|
||||||
|
select: Select,
|
||||||
|
radio: Radio
|
||||||
}
|
}
|
||||||
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
||||||
import { classNames } from 'primereact/utils';
|
import { classNames } from 'primereact/utils';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { head, isNil, pluck } from 'ramda';
|
import { head, isEmpty, isNil } from 'ramda';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { InputText } from 'primereact/inputtext';
|
import { InputText } from 'primereact/inputtext';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { Menu } from 'primereact/menu';
|
import { Menu } from 'primereact/menu';
|
||||||
import { Dropdown } from 'primereact/dropdown';
|
import { Dropdown } from 'primereact/dropdown';
|
||||||
|
import { diff } from 'deep-object-diff';
|
||||||
|
|
||||||
const FormFieldRepeater = ({
|
const FormFieldRepeater = ({
|
||||||
data,
|
data,
|
||||||
@@ -84,11 +85,20 @@ const FormFieldRepeater = ({
|
|||||||
}, [stateFieldData]);
|
}, [stateFieldData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storeFieldData = data[fieldName] ?? [];
|
const storeFieldData = data ?? [];
|
||||||
setStateFieldData(storeFieldData);
|
setStateFieldData(storeFieldData);
|
||||||
register(fieldName, config);
|
register(fieldName, config);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const diffData = diff(data, stateFieldData);
|
||||||
|
|
||||||
|
if (!isEmpty(diffData)) {
|
||||||
|
const storeFieldData = data ?? [];
|
||||||
|
setStateFieldData(storeFieldData);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setStateOptionsData([...options]);
|
setStateOptionsData([...options]);
|
||||||
}, [options]);
|
}, [options]);
|
||||||
|
|||||||
@@ -36,15 +36,15 @@ const FormFieldRepeaterFaq = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectItem = (e) => {
|
const selectItem = (e) => {
|
||||||
const targetedOption = head(stateOptionsData.filter(o => o.question === e.value));
|
const targetedOption = head(stateOptionsData.filter(o => o.value === e.value));
|
||||||
|
console.log('selected:', e, stateOptionsData, targetedOption)
|
||||||
if (targetedOption) {
|
if (targetedOption) {
|
||||||
setStateFieldData([...stateFieldData, targetedOption]);
|
setStateFieldData([...stateFieldData, targetedOption]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewItem = () => {
|
const addNewItem = () => {
|
||||||
const newItem = { id: null, lookUpDataId: null, question: '', response: '', visible: true };
|
const newItem = { id: null, lookUpDataId: null, title: '', value: '', isVisible: true };
|
||||||
setStateFieldData([...stateFieldData, newItem]);
|
setStateFieldData([...stateFieldData, newItem]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +61,8 @@ const FormFieldRepeaterFaq = ({
|
|||||||
|
|
||||||
const editItem = (e, index) => {
|
const editItem = (e, index) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setQuestion(stateFieldData[index].question);
|
setQuestion(stateFieldData[index].title);
|
||||||
setAnswer(stateFieldData[index].response);
|
setAnswer(stateFieldData[index].value);
|
||||||
setEditDataIndex(index);
|
setEditDataIndex(index);
|
||||||
setIsVisibleEditDialog(true);
|
setIsVisibleEditDialog(true);
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ const FormFieldRepeaterFaq = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onChangeEditItem = (value, key) => {
|
const onChangeEditItem = (value, key) => {
|
||||||
if (key === 'question') {
|
if (key === 'title') {
|
||||||
setQuestion(value);
|
setQuestion(value);
|
||||||
} else {
|
} else {
|
||||||
setAnswer(value)
|
setAnswer(value)
|
||||||
@@ -85,8 +85,8 @@ const FormFieldRepeaterFaq = ({
|
|||||||
const saveEditDialog = () => {
|
const saveEditDialog = () => {
|
||||||
const newData = stateFieldData.map((o, i) => {
|
const newData = stateFieldData.map((o, i) => {
|
||||||
if (i === editDataIndex) {
|
if (i === editDataIndex) {
|
||||||
o.question = question;
|
o.title = question;
|
||||||
o.response = answer;
|
o.value = answer;
|
||||||
return o
|
return o
|
||||||
} else {
|
} else {
|
||||||
return o;
|
return o;
|
||||||
@@ -113,7 +113,7 @@ const FormFieldRepeaterFaq = ({
|
|||||||
const usedExistingValues = useCallback(() => {
|
const usedExistingValues = useCallback(() => {
|
||||||
return stateFieldData
|
return stateFieldData
|
||||||
.filter(o => o.lookUpDataId)
|
.filter(o => o.lookUpDataId)
|
||||||
.map(o => o.question)
|
.map(o => o.title)
|
||||||
}, [stateFieldData]);
|
}, [stateFieldData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -149,9 +149,9 @@ const FormFieldRepeaterFaq = ({
|
|||||||
<Button type="button" iconPos="left" label={__('Aggiungi', 'gepafin')}
|
<Button type="button" iconPos="left" label={__('Aggiungi', 'gepafin')}
|
||||||
icon="pi pi-plus" onClick={addNewItem}/>
|
icon="pi pi-plus" onClick={addNewItem}/>
|
||||||
<Dropdown onChange={(e) => selectItem(e)}
|
<Dropdown onChange={(e) => selectItem(e)}
|
||||||
optionDisabled={(opt) => usedExistingValues().includes(opt.value)}
|
optionDisabled={(opt) => usedExistingValues().includes(opt.title)}
|
||||||
options={stateOptionsData}
|
options={stateOptionsData}
|
||||||
optionLabel="question"/>
|
optionLabel="title"/>
|
||||||
</div>
|
</div>
|
||||||
<Accordion activeIndex={0}>
|
<Accordion activeIndex={0}>
|
||||||
{stateFieldData.map((o, i) => <AccordionTab key={i}
|
{stateFieldData.map((o, i) => <AccordionTab key={i}
|
||||||
@@ -165,21 +165,21 @@ const FormFieldRepeaterFaq = ({
|
|||||||
offLabel=""
|
offLabel=""
|
||||||
checked={o.isVisible}
|
checked={o.isVisible}
|
||||||
onChange={(e) => setChecked(e, i)}/>
|
onChange={(e) => setChecked(e, i)}/>
|
||||||
{o.question}
|
{o.title}
|
||||||
</div>
|
</div>
|
||||||
<div className="appForm__faqTabItem">
|
<div className="appForm__faqTabItem">
|
||||||
<Button icon="pi pi-pencil" severity="success"
|
<Button icon="pi pi-pencil" severity="success"
|
||||||
aria-label="Edit"
|
aria-label={__('Modifica', 'gepafin')}
|
||||||
onClick={(e) => editItem(e, i)}/>
|
onClick={(e) => editItem(e, i)}/>
|
||||||
<Button icon="pi pi-times" severity="danger"
|
<Button icon="pi pi-times" severity="danger"
|
||||||
aria-label="Cancel"
|
aria-label={__('Cancella', 'gepafin')}
|
||||||
onClick={() => removeItem(i)}/>
|
onClick={() => removeItem(i)}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="m-0">
|
<p className="m-0">
|
||||||
{o.response}
|
{o.value}
|
||||||
</p>
|
</p>
|
||||||
</AccordionTab>)}
|
</AccordionTab>)}
|
||||||
</Accordion>
|
</Accordion>
|
||||||
@@ -192,11 +192,11 @@ const FormFieldRepeaterFaq = ({
|
|||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
<div className="appForm__field">
|
<div className="appForm__field">
|
||||||
<label>{__('Titolo FAQ', 'gepafin')}</label>
|
<label>{__('Titolo FAQ', 'gepafin')}</label>
|
||||||
<InputText value={question} onChange={(e) => onChangeEditItem(e.target.value, 'question')}/>
|
<InputText value={question} onChange={(e) => onChangeEditItem(e.target.value, 'title')}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="appForm__field">
|
<div className="appForm__field">
|
||||||
<label>{__('Risposta', 'gepafin')}</label>
|
<label>{__('Risposta', 'gepafin')}</label>
|
||||||
<InputTextarea value={answer} onChange={(e) => onChangeEditItem(e.target.value, 'response')}
|
<InputTextarea value={answer} onChange={(e) => onChangeEditItem(e.target.value, 'value')}
|
||||||
rows={5}
|
rows={5}
|
||||||
cols={30}/>
|
cols={30}/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Navigate, Outlet } from 'react-router-dom';
|
import { Navigate, Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
// store
|
|
||||||
import { useStore } from '../../store';
|
|
||||||
|
|
||||||
// tools
|
// tools
|
||||||
import AuthenticationService from '../../service/authentication-service';
|
import AuthenticationService from '../../service/authentication-service';
|
||||||
|
|
||||||
const ProtectedRoute = () => {
|
const ProtectedRoute = () => {
|
||||||
// we need this to track existance of the token
|
|
||||||
const token = useStore().main.token();
|
|
||||||
|
|
||||||
if (!AuthenticationService.wasLoggedIn()) {
|
if (!AuthenticationService.wasLoggedIn()) {
|
||||||
return (<Navigate to={'/login'} replace/>);
|
return (<Navigate to={'/login'} replace/>);
|
||||||
}
|
}
|
||||||
@@ -23,9 +17,9 @@ const ProtectedRoute = () => {
|
|||||||
return (<Navigate to={'/login?redirectReason=auth_required'} replace/>);
|
return (<Navigate to={'/login?redirectReason=auth_required'} replace/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (window.location.pathname === '/') {
|
if (window.location.pathname === '/') {
|
||||||
return (<Navigate to={'/'} replace/>);
|
return (<Navigate to={'/'} replace/>);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return <Outlet/>;
|
return <Outlet/>;
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/helpers/set404FromErrorResponse.js
Normal file
9
src/helpers/set404FromErrorResponse.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { storeSet } from '../store';
|
||||||
|
|
||||||
|
const set404FromErrorResponse = (data) => {
|
||||||
|
if (data && data.status === 'NOT_FOUND') {
|
||||||
|
storeSet.main.isError404(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default set404FromErrorResponse;
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { useStore, storeSet } from '../../store';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Toolbar } from 'primereact/toolbar';
|
import { Toolbar } from 'primereact/toolbar';
|
||||||
@@ -15,6 +19,12 @@ import AppSidebar from './components/AppSidebar';
|
|||||||
|
|
||||||
const DefaultLayout = ({ children }) => {
|
const DefaultLayout = ({ children }) => {
|
||||||
const menuLeft = useRef(null);
|
const menuLeft = useRef(null);
|
||||||
|
const isError404 = useStore().main.isError404();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
storeSet.main.isError404(false);
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
const startContent = <Link to="/">
|
const startContent = <Link to="/">
|
||||||
<LogoIcon/>
|
<LogoIcon/>
|
||||||
@@ -47,7 +57,9 @@ const DefaultLayout = ({ children }) => {
|
|||||||
<div className="inner">
|
<div className="inner">
|
||||||
<AppSidebar/>
|
<AppSidebar/>
|
||||||
<main>
|
<main>
|
||||||
{children}
|
{isError404
|
||||||
|
? <p>Error 404</p>
|
||||||
|
: children}
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>{__('© 2024 Gepafin. Tutti i diritti riservati.', 'gepafin')}</p>
|
<p>{__('© 2024 Gepafin. Tutti i diritti riservati.', 'gepafin')}</p>
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ const AllBandiTable = () => {
|
|||||||
const [statuses, setStatuses] = useState([]);
|
const [statuses, setStatuses] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const isAsyncRequest = storeGet.main.isAsyncRequest();
|
|
||||||
if (isAsyncRequest !== 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
BandoService.getBandi(getCallback, errGetCallbacks);
|
BandoService.getBandi(getCallback, errGetCallbacks);
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FormFieldRepeater
|
<FormFieldRepeater
|
||||||
data={values}
|
data={values['aimedTo']}
|
||||||
setDataFn={setValue}
|
setDataFn={setValue}
|
||||||
fieldName="aimedTo"
|
fieldName="aimedTo"
|
||||||
options={aimedToOptions}
|
options={aimedToOptions}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
}}/>
|
}}/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
type="fileupload"
|
type="fileuploadasync"
|
||||||
setDataFn={setValue}
|
setDataFn={setValue}
|
||||||
fieldName="docs"
|
fieldName="docs"
|
||||||
label={__('Documentazione', 'gepafin')}
|
label={__('Documentazione', 'gepafin')}
|
||||||
@@ -173,7 +173,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
type="fileupload"
|
type="fileuploadasync"
|
||||||
setDataFn={setValue}
|
setDataFn={setValue}
|
||||||
fieldName="images"
|
fieldName="images"
|
||||||
label={__('Immagine del Bando', 'gepafin')}
|
label={__('Immagine del Bando', 'gepafin')}
|
||||||
@@ -186,7 +186,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FormFieldRepeater
|
<FormFieldRepeater
|
||||||
data={values}
|
data={values['checkList']}
|
||||||
setDataFn={setValue}
|
setDataFn={setValue}
|
||||||
fieldName="checkList"
|
fieldName="checkList"
|
||||||
options={checklistOptions}
|
options={checklistOptions}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import BandoEditFormStep1 from './components/BandoEditFormStep1';
|
|||||||
import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
||||||
import { Messages } from 'primereact/messages';
|
import { Messages } from 'primereact/messages';
|
||||||
import FormsService from '../../service/forms-service';
|
import FormsService from '../../service/forms-service';
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
|
||||||
const BandoEdit = () => {
|
const BandoEdit = () => {
|
||||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||||
@@ -94,6 +95,10 @@ const BandoEdit = () => {
|
|||||||
navigate(`/bandi/${id}/forms`);
|
navigate(`/bandi/${id}/forms`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openBandoFlowManagement = () => {
|
||||||
|
navigate(`/bandi/${id}/flow`);
|
||||||
|
}
|
||||||
|
|
||||||
const validateBando = () => {
|
const validateBando = () => {
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
bandoMsgs.current.clear();
|
bandoMsgs.current.clear();
|
||||||
@@ -182,7 +187,8 @@ const BandoEdit = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const errGetCallback = (data) => {
|
const errGetCallback = (data) => {
|
||||||
standardErrCallback(data);
|
set404FromErrorResponse(data);
|
||||||
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
const standardErrCallback = (data) => {
|
const standardErrCallback = (data) => {
|
||||||
@@ -289,11 +295,21 @@ const BandoEdit = () => {
|
|||||||
|
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
<h2>{__('Crea o modifica il Form compilabile dal Beneficiario', 'gepafin')}</h2>
|
<h2>{__('Crea o modifica il Form compilabile dal Beneficiario', 'gepafin')}</h2>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={openBandoFormManagement}
|
onClick={openBandoFormManagement}
|
||||||
label={__('Crea/modifica form', 'gepafin')}/>
|
label={__('Crea/modifica form', 'gepafin')}/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
onClick={openBandoFlowManagement}
|
||||||
|
icon="pi pi-sitemap"
|
||||||
|
iconPos="right"
|
||||||
|
label={__('Gestisci flusso dei form', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{forms.length
|
{forms.length
|
||||||
? <ul className="">
|
? <ul className="">
|
||||||
{forms.map(o => <li key={o.id}>
|
{forms.map(o => <li key={o.id}>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import FormsService from '../../service/forms-service';
|
|||||||
|
|
||||||
// store
|
// store
|
||||||
import { storeSet } from '../../store';
|
import { storeSet } from '../../store';
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
|
||||||
const BandoForms = () => {
|
const BandoForms = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@@ -30,6 +31,10 @@ const BandoForms = () => {
|
|||||||
navigate(`/bandi/${id}`);
|
navigate(`/bandi/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openBandoFlowManagement = () => {
|
||||||
|
navigate(`/bandi/${id}/flow`);
|
||||||
|
}
|
||||||
|
|
||||||
const goToEditForm = () => {
|
const goToEditForm = () => {
|
||||||
if (selectedForm && selectedForm !== 0) {
|
if (selectedForm && selectedForm !== 0) {
|
||||||
navigate(`/bandi/${id}/forms/${selectedForm}`);
|
navigate(`/bandi/${id}/forms/${selectedForm}`);
|
||||||
@@ -49,6 +54,11 @@ const BandoForms = () => {
|
|||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errGetFormsCallback = (data) => {
|
||||||
|
set404FromErrorResponse(data);
|
||||||
|
storeSet.main.unsetAsyncRequest();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const parsed = parseInt(id)
|
const parsed = parseInt(id)
|
||||||
const bandoId = !isNaN(parsed) ? parsed : 0;
|
const bandoId = !isNaN(parsed) ? parsed : 0;
|
||||||
@@ -58,7 +68,7 @@ const BandoForms = () => {
|
|||||||
])
|
])
|
||||||
|
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
FormsService.getFormsForCall(bandoId, getFormsCallback, () => {});
|
FormsService.getFormsForCall(bandoId, getFormsCallback, errGetFormsCallback);
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -73,14 +83,6 @@ const BandoForms = () => {
|
|||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
<div className="appPage__content">
|
<div className="appPage__content">
|
||||||
<div className="appPageSection">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
outlined
|
|
||||||
onClick={goToEditBando}
|
|
||||||
label={__('Modifica bando', 'gepafin')}
|
|
||||||
icon="pi pi-arrow-left" iconPos="left"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="appPageSection__withBorder disabled">
|
<div className="appPageSection__withBorder disabled">
|
||||||
<h2>{__('Usa un template', 'gepafin')}</h2>
|
<h2>{__('Usa un template', 'gepafin')}</h2>
|
||||||
@@ -136,6 +138,25 @@ const BandoForms = () => {
|
|||||||
icon="pi pi-cog" iconPos="right"/>
|
icon="pi pi-cog" iconPos="right"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="appPageSection">
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
outlined
|
||||||
|
onClick={goToEditBando}
|
||||||
|
label={__('Indietro', 'gepafin')}
|
||||||
|
icon="pi pi-arrow-left" iconPos="left"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
onClick={openBandoFlowManagement}
|
||||||
|
icon="pi pi-sitemap"
|
||||||
|
iconPos="right"
|
||||||
|
label={__('Gestisci flusso dei form', 'gepafin')}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import { InputText } from 'primereact/inputtext';
|
|||||||
|
|
||||||
// api
|
// api
|
||||||
import FormsService from '../../service/forms-service';
|
import FormsService from '../../service/forms-service';
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
import { elementItems } from '../../tempData';
|
||||||
|
|
||||||
const BandoFormsEdit = () => {
|
const BandoFormsEdit = () => {
|
||||||
const { id, formId } = useParams();
|
const { id, formId } = useParams();
|
||||||
@@ -76,6 +78,7 @@ const BandoFormsEdit = () => {
|
|||||||
confirmPopup({
|
confirmPopup({
|
||||||
target: event.currentTarget,
|
target: event.currentTarget,
|
||||||
message: __('Sei sicuro di cancellare questo form?', 'gepafin'),
|
message: __('Sei sicuro di cancellare questo form?', 'gepafin'),
|
||||||
|
acceptLabel: __('Si', 'gepafin'),
|
||||||
icon: 'pi pi-info-circle',
|
icon: 'pi pi-info-circle',
|
||||||
defaultFocus: 'reject',
|
defaultFocus: 'reject',
|
||||||
acceptClassName: 'p-button-danger',
|
acceptClassName: 'p-button-danger',
|
||||||
@@ -84,9 +87,9 @@ const BandoFormsEdit = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const doPublish = () => {
|
/*const doPublish = () => {
|
||||||
console.log('doPublish');
|
console.log('doPublish');
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const doDelete = () => {
|
const doDelete = () => {
|
||||||
storeSet.main.setAsyncRequest();
|
storeSet.main.setAsyncRequest();
|
||||||
@@ -108,7 +111,8 @@ const BandoFormsEdit = () => {
|
|||||||
|
|
||||||
const getElementItemsCallback = (data) => {
|
const getElementItemsCallback = (data) => {
|
||||||
if (data.status === 'SUCCESS') {
|
if (data.status === 'SUCCESS') {
|
||||||
storeSet.main.elementItems(data.data);
|
storeSet.main.elementItems(elementItems);
|
||||||
|
//storeSet.main.elementItems(data.data);
|
||||||
}
|
}
|
||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
@@ -130,7 +134,7 @@ const BandoFormsEdit = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const errGetFormCallbacks = (data) => {
|
const errGetFormCallbacks = (data) => {
|
||||||
console.log('errGetElementItemsCallbacks', data)
|
set404FromErrorResponse(data);
|
||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,10 +202,10 @@ const BandoFormsEdit = () => {
|
|||||||
outlined
|
outlined
|
||||||
onClick={openPreview}
|
onClick={openPreview}
|
||||||
label={__('Visualizza Anteprima Beneficiario', 'gepafin')} icon="pi pi-image" iconPos="right"/>
|
label={__('Visualizza Anteprima Beneficiario', 'gepafin')} icon="pi pi-image" iconPos="right"/>
|
||||||
<Button
|
{/*<Button
|
||||||
disabled={true}
|
disabled={true}
|
||||||
onClick={doPublish}
|
onClick={doPublish}
|
||||||
label={__('Pubblica', 'gepafin')}/>
|
label={__('Pubblica', 'gepafin')}/>*/}
|
||||||
</div>
|
</div>
|
||||||
<div className="appPageSection__actions">
|
<div className="appPageSection__actions">
|
||||||
<ConfirmPopup />
|
<ConfirmPopup />
|
||||||
|
|||||||
@@ -1,68 +1,75 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { bandoTest, formData } from '../../tempData';
|
import { klona } from 'klona';
|
||||||
|
import { head } from 'ramda';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
// tools
|
// store
|
||||||
import getNumberWithCurrency from '../../helpers/getNumberWithCurrency';
|
import { storeSet, useStore } from '../../store';
|
||||||
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
|
|
||||||
|
// api
|
||||||
|
import FormsService from '../../service/forms-service';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Skeleton } from 'primereact/skeleton';
|
import { Skeleton } from 'primereact/skeleton';
|
||||||
import { Accordion } from 'primereact/accordion';
|
|
||||||
import { AccordionTab } from 'primereact/accordion';
|
|
||||||
import { InputTextarea } from 'primereact/inputtextarea';
|
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { useForm } from 'react-hook-form';
|
|
||||||
import { is, isNil } from 'ramda';
|
|
||||||
import FormField from '../../components/FormField';
|
import FormField from '../../components/FormField';
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
|
||||||
const BandoFormsPreview = () => {
|
const BandoFormsPreview = () => {
|
||||||
const { id, formId } = useParams();
|
const { id, formId } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [bando, setBando] = useState({});
|
const [formData, setFormData] = useState([]);
|
||||||
const [data, setData] = useState({});
|
const [formName, setFormName] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors, isValid },
|
formState: { errors },
|
||||||
setValue,
|
|
||||||
register,
|
|
||||||
trigger,
|
|
||||||
getValues,
|
getValues,
|
||||||
clearErrors
|
|
||||||
} = useForm({ defaultValues: {}, mode: 'onChange' });
|
} = useForm({ defaultValues: {}, mode: 'onChange' });
|
||||||
const values = getValues();
|
const values = getValues();
|
||||||
|
|
||||||
const onSubmit = (formData) => {
|
const onSubmit = () => {}
|
||||||
console.log('onSubmit', formData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const closePreview = () => {
|
const closePreview = () => {
|
||||||
navigate(`/bandi/${id}`);
|
const parsedId = parseInt(id)
|
||||||
|
const bandoId = !isNaN(parsedId) ? parsedId : 0;
|
||||||
|
const parsedFormId = parseInt(formId)
|
||||||
|
const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
||||||
|
navigate(`/bandi/${bandoId}/forms/${bandoFormId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFormCallback = (data) => {
|
||||||
|
if (data.status === 'SUCCESS') {
|
||||||
|
setFormName(data.data.label);
|
||||||
|
const elements = klona(data.data.content);
|
||||||
|
setFormData(elements);
|
||||||
|
}
|
||||||
|
storeSet.main.unsetAsyncRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
const errGetFormCallbacks = (data) => {
|
||||||
|
set404FromErrorResponse(data);
|
||||||
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//const parsed = parseInt(id)
|
const parsedFormId = parseInt(formId)
|
||||||
//const bandoId = !isNaN(parsed) ? parsed : 0;
|
const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
||||||
|
|
||||||
setTimeout(() => {
|
if (bandoFormId) {
|
||||||
const data = formData;
|
storeSet.main.setAsyncRequest();
|
||||||
setData(data);
|
FormsService.getFormById(bandoFormId, getFormCallback, errGetFormCallbacks);
|
||||||
|
}
|
||||||
const bandoData = bandoTest;
|
}, [id, formId]);
|
||||||
setBando(bandoData);
|
|
||||||
|
|
||||||
setIsLoading(false)
|
|
||||||
}, 3000);
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="appPage">
|
<div className="appPage">
|
||||||
{!isLoading
|
{!isAsyncRequest
|
||||||
? <div className="appPage__pageHeader">
|
? <div className="appPage__pageHeader">
|
||||||
<h1>{sprintf(__('Domanda per il Bando: %s', 'gepafin'), bando.name)}</h1>
|
<h1>{formName}</h1>
|
||||||
</div>
|
</div>
|
||||||
: <>
|
: <>
|
||||||
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
|
||||||
@@ -71,7 +78,7 @@ const BandoFormsPreview = () => {
|
|||||||
|
|
||||||
<div className="appPage__spacer"></div>
|
<div className="appPage__spacer"></div>
|
||||||
|
|
||||||
{!isLoading
|
{!isAsyncRequest
|
||||||
? <div className="appPage__content">
|
? <div className="appPage__content">
|
||||||
<div className="appPageSection__preview">
|
<div className="appPageSection__preview">
|
||||||
<Button
|
<Button
|
||||||
@@ -83,15 +90,23 @@ const BandoFormsPreview = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
|
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
|
||||||
{data.content.map(o => <FormField
|
{formData.map(o => {
|
||||||
|
const label = head(o.settings.filter(o => o.name === 'label'));
|
||||||
|
const placeholder = head(o.settings.filter(o => o.name === 'placeholder'));
|
||||||
|
const options = head(o.settings.filter(o => o.name === 'options'));
|
||||||
|
return <FormField
|
||||||
key={o.id}
|
key={o.id}
|
||||||
type={o.name}
|
type={o.name}
|
||||||
fieldName={`field_${o.id}`}
|
fieldName={`field_${o.id}`}
|
||||||
label={o.label}
|
label={label ? label.value : ''}
|
||||||
|
placeholder={placeholder ? placeholder.value : ''}
|
||||||
control={control}
|
control={control}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
defaultValue={values[`field_${o.id}`]}
|
defaultValue={values[`field_${o.id}`]}
|
||||||
/>)}
|
config={o.validators}
|
||||||
|
options={options ? options.value : []}
|
||||||
|
/>
|
||||||
|
})}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className="appPageSection__preview">
|
<div className="appPageSection__preview">
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { InputTextarea } from 'primereact/inputtextarea';
|
|||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import BandoService from '../../service/bando-service';
|
import BandoService from '../../service/bando-service';
|
||||||
import { Messages } from 'primereact/messages';
|
import { Messages } from 'primereact/messages';
|
||||||
|
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||||
|
|
||||||
const BandoView = () => {
|
const BandoView = () => {
|
||||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||||
@@ -64,6 +65,7 @@ const BandoView = () => {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
set404FromErrorResponse(data);
|
||||||
storeSet.main.unsetAsyncRequest();
|
storeSet.main.unsetAsyncRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import BandoForms from './pages/BandoForms';
|
|||||||
import BandoFormsPreview from './pages/BandoFormsPreview';
|
import BandoFormsPreview from './pages/BandoFormsPreview';
|
||||||
|
|
||||||
const routes = ({ role }) => {
|
const routes = ({ role }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<ProtectedRoute/>}>
|
<Route element={<ProtectedRoute/>}>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const initialStore = {
|
const initialStore = {
|
||||||
// ui related
|
// ui related
|
||||||
isAsyncRequest: 0, // number
|
isAsyncRequest: 0, // number
|
||||||
|
isError404: false,
|
||||||
// user
|
// user
|
||||||
userData: {},
|
userData: {},
|
||||||
token: '',
|
token: '',
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ export const elementItems = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: 'textinput',
|
name: 'numberinput',
|
||||||
label: 'Number Input',
|
label: 'Number Input',
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
@@ -272,7 +272,7 @@ export const elementItems = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "placeholder",
|
name: "placeholder",
|
||||||
value: ""
|
value: 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
validators: {
|
validators: {
|
||||||
@@ -317,14 +317,50 @@ export const elementItems = [
|
|||||||
{
|
{
|
||||||
name: "options",
|
name: "options",
|
||||||
value: [
|
value: [
|
||||||
{ name: "opt1", label: "Opt1" }
|
{ name: "opt1", label: "Opt1" },
|
||||||
|
{ name: "opt2", label: "Opt2" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
validators: {
|
validators: {
|
||||||
isRequired: false,
|
isRequired: false,
|
||||||
min: null,
|
custom: null
|
||||||
max: null,
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: 'select',
|
||||||
|
label: 'Select',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Select"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "options",
|
||||||
|
value: [
|
||||||
|
{ name: "opt1", label: "Opt1" },
|
||||||
|
{ name: "opt2", label: "Opt2" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
|
custom: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: 'datepicker',
|
||||||
|
label: 'Datepicker',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Datepicker"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {
|
||||||
|
isRequired: false,
|
||||||
custom: null
|
custom: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user