- styled asteriks sign;
- fixed issue with validation on registration page; - fixed issue with inputnumber; - fixed issue with editor field;; - added editors for new faq item form; - fixed displaying html as simple text; - fixed saving company data after saving; - added toast for edit bando form; - improved edit forms form; - fixed styles for various elements;
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
gap: 24px;
|
||||
}
|
||||
.appForm__field {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
@@ -58,9 +59,58 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
: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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.appForm__field--required.appForm__field--required {
|
||||
margin-left: 2px;
|
||||
color: var(--message-error-color);
|
||||
}
|
||||
|
||||
.appForm__fieldItem {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
|
||||
@@ -218,6 +218,16 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.appPageSection__titleClickable {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.appTableHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -104,47 +104,3 @@ 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)
|
||||
}
|
||||
@@ -110,6 +110,12 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.p-accordion-header-text, .p-accordion-content {
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -65,7 +65,7 @@ const Checkboxes = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
{input}
|
||||
{infoText ? <small>{infoText}</small> : null}
|
||||
|
||||
@@ -20,7 +20,7 @@ const Datepicker = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
<Controller
|
||||
name={fieldName}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { head } from 'ramda'
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import FileUploadService from '../../../../service/file-upload-service';
|
||||
|
||||
import { FileUpload } from 'primereact/fileupload';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Button } from 'primereact/button';
|
||||
|
||||
import { mimeTypes } from '../../../../configData';
|
||||
|
||||
const Fileupload = ({
|
||||
fieldName,
|
||||
setDataFn,
|
||||
@@ -17,7 +20,7 @@ const Fileupload = ({
|
||||
defaultValue = [],
|
||||
config = {},
|
||||
infoText = null,
|
||||
accept = 'image/*',
|
||||
accept = ['image/*'],
|
||||
doctype = 'images',
|
||||
maxSize = 100000000,
|
||||
emptyText = __('Trascina qui il tuo file', 'gepafin'),
|
||||
@@ -119,6 +122,21 @@ const Fileupload = ({
|
||||
});
|
||||
}
|
||||
|
||||
const getPropeMimeLabels = (acceptFormats) => {
|
||||
return acceptFormats
|
||||
.map(v => {
|
||||
const found = head(mimeTypes.filter(o => o.code === v));
|
||||
let res = v;
|
||||
|
||||
if (found) {
|
||||
res = found.name;
|
||||
}
|
||||
|
||||
return res;
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setStateFieldData(defaultValue);
|
||||
register(fieldName, config)
|
||||
@@ -126,7 +144,7 @@ const Fileupload = ({
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
setAcceptFormats(accept.replace(/\*/g, '.\*').replace(/,/g, '|'));
|
||||
setAcceptFormats(accept.join(',').replace(/\*/g, '.\*').replace(/,/g, '|'));
|
||||
}, [accept]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -140,8 +158,8 @@ const Fileupload = ({
|
||||
sourceId || sourceId === 0
|
||||
? <>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{acceptFormats ? ' (' + acceptFormats.split('|').join(', ') + ')' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
{acceptFormats ? ' (' + getPropeMimeLabels(accept) + ')' : null}
|
||||
</label>
|
||||
<FileUpload
|
||||
ref={inputRef}
|
||||
|
||||
@@ -7,6 +7,8 @@ import FileUploadService from '../../../../service/file-upload-service';
|
||||
import { FileUpload } from 'primereact/fileupload';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Button } from 'primereact/button';
|
||||
import { head } from 'ramda';
|
||||
import { mimeTypes } from '../../../../configData';
|
||||
|
||||
const FileuploadAsync = ({
|
||||
fieldName,
|
||||
@@ -17,7 +19,7 @@ const FileuploadAsync = ({
|
||||
defaultValue = [],
|
||||
config = {},
|
||||
infoText = null,
|
||||
accept = 'image/*',
|
||||
accept = ['image/*'],
|
||||
doctype = 'images',
|
||||
maxSize = 100000000,
|
||||
emptyText = __('Trascina qui il tuo file', 'gepafin'),
|
||||
@@ -121,6 +123,21 @@ const FileuploadAsync = ({
|
||||
});
|
||||
}
|
||||
|
||||
const getPropeMimeLabels = (acceptFormats) => {
|
||||
return acceptFormats
|
||||
.map(v => {
|
||||
const found = head(mimeTypes.filter(o => o.code === v));
|
||||
let res = v;
|
||||
|
||||
if (found) {
|
||||
res = found.name;
|
||||
}
|
||||
|
||||
return res;
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setStateFieldData(defaultValue);
|
||||
register(fieldName, config)
|
||||
@@ -128,7 +145,7 @@ const FileuploadAsync = ({
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
setAcceptFormats(accept.replace(/\*/g, '.\*').replace(/,/g, '|'));
|
||||
setAcceptFormats(accept.join(',').replace(/\*/g, '.\*').replace(/,/g, '|'));
|
||||
}, [accept]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -143,7 +160,7 @@ const FileuploadAsync = ({
|
||||
? <>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required ? '*' : null}
|
||||
{acceptFormats ? ' (' + acceptFormats.split('|').join(', ') + ')' : null}
|
||||
{acceptFormats ? ' (' + getPropeMimeLabels(accept) + ')' : null}
|
||||
</label>
|
||||
<FileUpload
|
||||
ref={inputRef}
|
||||
|
||||
@@ -20,8 +20,9 @@ const NumberInput = ({
|
||||
min,
|
||||
max,
|
||||
disabled = false,
|
||||
useGrouping = true
|
||||
useGrouping = false
|
||||
}) => {
|
||||
console.log('defaultValue', defaultValue);
|
||||
const input = <Controller
|
||||
name={fieldName}
|
||||
control={control}
|
||||
@@ -43,10 +44,10 @@ const NumberInput = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
{inputgroup
|
||||
? <div className="p-inputgroup flex-1">
|
||||
? <div className="p-inputgroup">
|
||||
<span className="p-inputgroup-addon">
|
||||
{icon}
|
||||
</span>
|
||||
|
||||
@@ -34,7 +34,7 @@ const Radio = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
{input}
|
||||
{infoText ? <small>{infoText}</small> : null}
|
||||
|
||||
@@ -36,10 +36,10 @@ const Select = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
{inputgroup
|
||||
? <div className="p-inputgroup flex-1">
|
||||
? <div className="p-inputgroup">
|
||||
<span className="p-inputgroup-addon">
|
||||
{icon}
|
||||
</span>
|
||||
|
||||
@@ -36,7 +36,7 @@ const Switch = ({
|
||||
<>
|
||||
<div className="appForm__row">
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] }, 'mr-8')}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
<div className="appForm__row">
|
||||
{offLabel ? <span>{offLabel}</span> : null}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
const RenderTable = ({ data, columns, setRowsFn }) => {
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
defaultColumn: {
|
||||
cell: ({ getValue, row: { index }, column: { id }, table }) => {
|
||||
const initialValue = getValue();
|
||||
|
||||
const onBlur = (e) => {
|
||||
table.options.meta?.updateData(index, id, e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<input
|
||||
value={initialValue ? initialValue : ''}
|
||||
onChange={(e) => table.options.meta?.updateData(index, id, e.target.value)}
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
meta: {
|
||||
updateData: (rowIndex, columnId, value) => {
|
||||
const newRowsData = wrap(data).set([rowIndex, columnId], value).value();
|
||||
setRowsFn(newRowsData);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
||||
export default RenderTable
|
||||
@@ -1,17 +1,16 @@
|
||||
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, isNil } from 'ramda';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
//components
|
||||
import { Button } from 'primereact/button';
|
||||
import RenderTable from './RenderTable';
|
||||
|
||||
const Table = ({
|
||||
fieldName,
|
||||
setDataFn,
|
||||
label,
|
||||
register,
|
||||
errors,
|
||||
@@ -19,59 +18,46 @@ const Table = ({
|
||||
defaultValue = [],
|
||||
tableColumns = []
|
||||
}) => {
|
||||
const [stateFieldData, setStateFieldData] = useState([]);
|
||||
const [rowsData, setRowsData] = useState([]);
|
||||
const [rowsDataLength, setRowsDataLength] = useState(0);
|
||||
const [rowIndexToDelete, rowRowIndexToDelete] = useState(null);
|
||||
const [isDisabledNewRow, setIsDisabledNewRow] = useState(false);
|
||||
const [columnsCfg, setColumnsCfg] = useState([]);
|
||||
const [rowsCfg, setRowsCfg] = useState([]);
|
||||
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 [rows, setRows] = useState([]);
|
||||
const [shouldDisableNewRows, setShouldDisableNewRows] = useState(false);
|
||||
const [rowIndexToDelete, rowRowIndexToDelete] = useState(null);
|
||||
|
||||
const addNewRow = () => {
|
||||
const obj = stateFieldData
|
||||
const obj = columnsCfg
|
||||
.reduce((acc, cur) => {
|
||||
acc[cur.name] = ''
|
||||
return acc;
|
||||
}, {});
|
||||
setRowsData([...rowsData, obj]);
|
||||
const newRowsData = [...rows, obj];
|
||||
setRows(newRowsData);
|
||||
setDataFn(fieldName, newRowsData, { shouldValidate: true });
|
||||
}
|
||||
|
||||
const removeRow = (index) => {
|
||||
rowRowIndexToDelete(index)
|
||||
rowRowIndexToDelete(index);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isNil(rowIndexToDelete)) {
|
||||
const newRowsData = wrap(rows).del([rowIndexToDelete]).value();
|
||||
setRows(newRowsData);
|
||||
setDataFn(fieldName, [...newRowsData], { shouldValidate: true });
|
||||
}
|
||||
rowRowIndexToDelete(null);
|
||||
}, [rowIndexToDelete]);
|
||||
|
||||
const updateRows = (data) => {
|
||||
setRows(data);
|
||||
setDataFn(fieldName, data, { shouldValidate: true });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
let shouldDisableNewRows = false;
|
||||
|
||||
let columns = stateFieldData.map((o) => {
|
||||
let newColumns = columnsCfg.map((o) => {
|
||||
const item = {
|
||||
accessorKey: o.name,
|
||||
header: () => o.label,
|
||||
@@ -88,10 +74,10 @@ const Table = ({
|
||||
return item;
|
||||
});
|
||||
|
||||
setIsDisabledNewRow(shouldDisableNewRows);
|
||||
setShouldDisableNewRows(shouldDisableNewRows);
|
||||
|
||||
if (!shouldDisableNewRows && !isEmpty(columns)) {
|
||||
columns.push({
|
||||
if (!shouldDisableNewRows && !isEmpty(newColumns)) {
|
||||
newColumns.push({
|
||||
accessorKey: 'actions',
|
||||
header: () => '',
|
||||
footer: (props) => props.column.id,
|
||||
@@ -104,20 +90,12 @@ const Table = ({
|
||||
})
|
||||
}
|
||||
|
||||
setColumns(columns);
|
||||
}, [stateFieldData, rowsDataLength]);
|
||||
setColumns(newColumns);
|
||||
}, [columnsCfg]);
|
||||
|
||||
useEffect(() => {
|
||||
setRowsDataLength(rowsData.length);
|
||||
}, [rowsData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isNil(rowIndexToDelete)) {
|
||||
const newRowsData = wrap(rowsData).del([rowIndexToDelete]).value();
|
||||
setRowsData(newRowsData);
|
||||
}
|
||||
rowRowIndexToDelete(null);
|
||||
}, [rowIndexToDelete]);
|
||||
setRows(rowsCfg);
|
||||
}, [rowsCfg]);
|
||||
|
||||
useEffect(() => {
|
||||
const stateFieldData = pathOr([], ['stateFieldData'], tableColumns);
|
||||
@@ -128,60 +106,21 @@ const Table = ({
|
||||
}, {});
|
||||
let rowsData = pathOr([obj], ['rowsData'], tableColumns);
|
||||
rowsData = isEmpty(rowsData) ? [obj] : rowsData;
|
||||
setStateFieldData(stateFieldData);
|
||||
setRowsData(rowsData);
|
||||
setColumnsCfg(stateFieldData);
|
||||
setRowsCfg(rowsData);
|
||||
}, [tableColumns]);
|
||||
|
||||
useEffect(() => {
|
||||
register(fieldName, config)
|
||||
register(fieldName, config);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : 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)
|
||||
<RenderTable columns={columns} data={rows} setRowsFn={updateRows}/>
|
||||
{!isEmpty(columns) && !shouldDisableNewRows
|
||||
? <div className="addNewTableRow" onClick={addNewRow}>{__('Aggiungi una righa', 'gepafin')}</div>
|
||||
: null}
|
||||
</>)
|
||||
|
||||
@@ -17,7 +17,7 @@ const TextArea = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
<Controller
|
||||
name={fieldName}
|
||||
|
||||
@@ -37,10 +37,10 @@ const TextInput = ({
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
{inputgroup
|
||||
? <div className="p-inputgroup flex-1">
|
||||
? <div className="p-inputgroup">
|
||||
<span className="p-inputgroup-addon">
|
||||
{icon}
|
||||
</span>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { Editor } from 'primereact/editor';
|
||||
import BlockingOverlay from '../../../BlockingOverlay';
|
||||
|
||||
const Wysiwyg = ({
|
||||
fieldName,
|
||||
@@ -12,6 +13,7 @@ const Wysiwyg = ({
|
||||
defaultValue,
|
||||
config = {},
|
||||
infoText = null,
|
||||
placeholder={placeholder},
|
||||
disabled = false
|
||||
}) => {
|
||||
|
||||
@@ -36,8 +38,9 @@ const Wysiwyg = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<BlockingOverlay shouldDisplay={disabled}/>
|
||||
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
|
||||
{label}{config.required || config.isRequired ? '*' : null}
|
||||
{label}{config.required || config.isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</label>
|
||||
<Controller
|
||||
name={fieldName}
|
||||
@@ -50,6 +53,7 @@ const Wysiwyg = ({
|
||||
readOnly={disabled}
|
||||
{...field}
|
||||
headerTemplate={header}
|
||||
placeholder={placeholder}
|
||||
onTextChange={(e) => field.onChange(e.htmlValue)}
|
||||
style={{ height: 80 * rows }}
|
||||
className={classNames({ 'p-invalid': fieldState.invalid })}
|
||||
|
||||
@@ -9,9 +9,9 @@ import { Button } from 'primereact/button';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Accordion, AccordionTab } from 'primereact/accordion';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
import { Editor } from 'primereact/editor';
|
||||
|
||||
const FormFieldRepeaterFaq = ({
|
||||
data,
|
||||
@@ -108,7 +108,8 @@ const FormFieldRepeaterFaq = ({
|
||||
|
||||
const footerEditDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" disabled={disabled} label={__('Anulla', 'gepafin')} onClick={hideEditDialog} outlined/>
|
||||
<Button type="button" disabled={disabled} label={__('Anulla', 'gepafin')} onClick={hideEditDialog}
|
||||
outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={isEmpty(title) || isEmpty(question) || isEmpty(answer) || disabled}
|
||||
@@ -122,6 +123,26 @@ const FormFieldRepeaterFaq = ({
|
||||
.map(o => o.title)
|
||||
}, [stateFieldData]);
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<span className="ql-formats">
|
||||
<button className="ql-bold" aria-label="Bold"></button>
|
||||
<button className="ql-italic" aria-label="Italic"></button>
|
||||
<button className="ql-underline" aria-label="Underline"></button>
|
||||
<button className="ql-link" aria-label="Link"></button>
|
||||
<button className="ql-list" value="ordered"></button>
|
||||
<button className="ql-header" value="2"></button>
|
||||
<button className="ql-header" value="3"></button>
|
||||
<button className="ql-blockquote"></button>
|
||||
<button className="ql-list" value="bullet"></button>
|
||||
<button className="ql-indent" value="-1"></button>
|
||||
<button className="ql-indent" value="+1"></button>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
useEffect(() => {
|
||||
const storeFieldData = data ?? [];
|
||||
setStateFieldData(storeFieldData);
|
||||
@@ -163,41 +184,42 @@ const FormFieldRepeaterFaq = ({
|
||||
optionLabel="title"/>
|
||||
</div>
|
||||
<Accordion activeIndex={0}>
|
||||
{stateFieldData.map((o, i) => <AccordionTab key={i} tabIndex={i}
|
||||
header={
|
||||
<div className="appForm__faqTab">
|
||||
<div className="appForm__faqTabItem">
|
||||
{stateFieldData.map((o, i) =>
|
||||
<AccordionTab key={i} tabIndex={i}
|
||||
header={
|
||||
<div className="appForm__faqTab">
|
||||
<div className="appForm__faqTabItem">
|
||||
<span>
|
||||
{o.value}
|
||||
{renderHtmlContent(o.value)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="appForm__faqTabItem">
|
||||
{o.isVisible
|
||||
? <i className="pi pi-eye"
|
||||
style={{ fontSize: '1.5rem' }}></i> : null}
|
||||
{!o.isVisible
|
||||
? <i className="pi pi-eye-slash"
|
||||
style={{ fontSize: '1.5rem' }}></i> : null}
|
||||
<Button icon="pi pi-pencil" severity="success"
|
||||
disabled={disabled}
|
||||
className="actionBtn"
|
||||
type="button"
|
||||
aria-label={__('Modifica', 'gepafin')}
|
||||
onClick={(e) => editItem(e, i)}/>
|
||||
<Button icon="pi pi-times" severity="danger"
|
||||
disabled={disabled}
|
||||
className="actionBtn"
|
||||
type="button"
|
||||
aria-label={__('Cancella', 'gepafin')}
|
||||
onClick={() => removeItem(i)}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<p className="m-0">
|
||||
{o.response}
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
</div>
|
||||
<div className="appForm__faqTabItem">
|
||||
{o.isVisible
|
||||
? <i className="pi pi-eye"
|
||||
style={{ fontSize: '1.5rem' }}></i> : null}
|
||||
{!o.isVisible
|
||||
? <i className="pi pi-eye-slash"
|
||||
style={{ fontSize: '1.5rem' }}></i> : null}
|
||||
<Button icon="pi pi-pencil" severity="success"
|
||||
disabled={disabled}
|
||||
className="actionBtn"
|
||||
type="button"
|
||||
aria-label={__('Modifica', 'gepafin')}
|
||||
onClick={(e) => editItem(e, i)}/>
|
||||
<Button icon="pi pi-times" severity="danger"
|
||||
disabled={disabled}
|
||||
className="actionBtn"
|
||||
type="button"
|
||||
aria-label={__('Cancella', 'gepafin')}
|
||||
onClick={() => removeItem(i)}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<p className="m-0">
|
||||
{renderHtmlContent(o.response)}
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
</Accordion>
|
||||
<Dialog
|
||||
visible={isVisibleEditDialog}
|
||||
@@ -205,26 +227,41 @@ const FormFieldRepeaterFaq = ({
|
||||
footer={footerEditDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideEditDialog}>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appForm__field">
|
||||
<label>{__('Titolo FAQ', 'gepafin')}</label>
|
||||
<InputText value={title} onChange={(e) => onChangeEditItem(e.target.value, 'title')}/>
|
||||
<label for="faqTitle">{__('Titolo FAQ', 'gepafin')}</label>
|
||||
<Editor
|
||||
id="faqTitle"
|
||||
value={title}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'title')}
|
||||
style={{ height: 80 * 1 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label>{__('Domanda', 'gepafin')}</label>
|
||||
<InputText value={question} onChange={(e) => onChangeEditItem(e.target.value, 'value')}/>
|
||||
<label for="faqValue">{__('Domanda', 'gepafin')}</label>
|
||||
<Editor
|
||||
id="faqValue"
|
||||
value={question}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'value')}
|
||||
style={{ height: 80 * 1 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label>{__('Risposta', 'gepafin')}</label>
|
||||
<InputTextarea value={answer} onChange={(e) => onChangeEditItem(e.target.value, 'response')}
|
||||
rows={5}
|
||||
cols={30}/>
|
||||
<label for="faqResponse">{__('Risposta', 'gepafin')}</label>
|
||||
<Editor
|
||||
id="faqResponse"
|
||||
value={answer}
|
||||
headerTemplate={header}
|
||||
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'response')}
|
||||
style={{ height: 80 * 2 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label>{__('Pubblicato?', 'gepafin')}</label>
|
||||
<InputSwitch checked={isVisible} onChange={(e) => onChangeEditItem(e.value, 'isVisible')}/>
|
||||
<InputSwitch checked={isVisible}
|
||||
onChange={(e) => onChangeEditItem(e.value, 'isVisible')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
export const mimeTypes = [
|
||||
{ name: 'PDF file', code: 'application/pdf' },
|
||||
{ name: 'ZIP file', code: 'application/zip' },
|
||||
{ name: 'PDF', code: 'application/pdf' },
|
||||
{ name: 'ZIP', code: 'application/zip' },
|
||||
{ name: 'Immagine', code: 'image/*' },
|
||||
{ name: 'Word doc', code: 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document' }
|
||||
{
|
||||
name: 'Word doc',
|
||||
code: 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
},
|
||||
{ name: 'Excel doc', code: 'application/vnd.ms-excel' }
|
||||
];
|
||||
@@ -98,6 +98,10 @@ const AllBandiTable = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData) => {
|
||||
return <span>{rowData.name}</span>
|
||||
}
|
||||
|
||||
const dateStartBodyTemplate = (rowData) => {
|
||||
return getDateFromISOstring(rowData.dates[0]);
|
||||
};
|
||||
@@ -137,7 +141,8 @@ const AllBandiTable = () => {
|
||||
globalFilterFields={['name', 'status']}
|
||||
header={header}
|
||||
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name"
|
||||
<Column field="name" header={__('Nome Bando', 'gepafin')}
|
||||
filter filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
|
||||
style={{ minWidth: '10rem' }}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useState, useEffect} from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import { is, uniq, isNil } from 'ramda';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
|
||||
// store
|
||||
import { storeSet, storeGet } from '../../../../store';
|
||||
import { storeSet, useStore } from '../../../../store';
|
||||
|
||||
// tools
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
@@ -23,12 +24,13 @@ import getNumberWithCurrency from '../../../../helpers/getNumberWithCurrency';
|
||||
import renderHtmlContent from '../../../../helpers/renderHtmlContent';
|
||||
import { Button } from 'primereact/button';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
|
||||
|
||||
|
||||
const AllBandiAccordion = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const [items, setItems] = useState(null);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [expandedRows, setExpandedRows] = useState(null);
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
@@ -47,7 +49,7 @@ const AllBandiAccordion = () => {
|
||||
}
|
||||
|
||||
const errGetCallbacks = (data) => {
|
||||
console.log('errGetCallbacks', data)
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
@@ -58,6 +60,22 @@ const AllBandiAccordion = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData) => {
|
||||
return <span
|
||||
className="appPageSection__titleClickable"
|
||||
onClick={() => {
|
||||
let newExpandedRows;
|
||||
if (isNil(expandedRows) || isNil(expandedRows[rowData.id])) {
|
||||
newExpandedRows = isNil(expandedRows)
|
||||
? wrap({}).set([rowData.id], true).value()
|
||||
: wrap(expandedRows).set([rowData.id], true).value();
|
||||
} else {
|
||||
newExpandedRows = wrap(expandedRows).del([rowData.id]).value();
|
||||
}
|
||||
setExpandedRows(newExpandedRows);
|
||||
}}>{rowData.name}</span>
|
||||
}
|
||||
|
||||
const amountBodyTemplate = (rowData) => {
|
||||
return getNumberWithCurrency(rowData.amount);
|
||||
};
|
||||
@@ -108,13 +126,16 @@ const AllBandiAccordion = () => {
|
||||
|
||||
return(
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={items} paginator rows={10} loading={loading} dataKey="id"
|
||||
<DataTable value={items} paginator rows={10} loading={isAsyncRequest} dataKey="id"
|
||||
filters={filters} emptyMessage="Nothing found."
|
||||
expandedRows={expandedRows} onRowToggle={(e) => setExpandedRows(e.data)}
|
||||
expandedRows={expandedRows}
|
||||
onRowToggle={(e) => setExpandedRows(e.data)}
|
||||
rowExpansionTemplate={rowExpansionTemplate}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column expander={allowExpansion} style={{ width: '5rem' }} />
|
||||
<Column field="name" header={__('Bando', 'gepafin')} style={{ minWidth: '12rem' }}/>
|
||||
<Column field="name" header={__('Bando', 'gepafin')}
|
||||
body={nameBodyTemplate}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column header={__('Importo totale', 'gepafin')} filterField="amount"
|
||||
style={{ minWidth: '10rem' }} body={amountBodyTemplate} sortable/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')} filterMenuStyle={{ width: '14rem' }}
|
||||
|
||||
26
src/pages/BandoApplication/ApplicationSteps/index.js
Normal file
26
src/pages/BandoApplication/ApplicationSteps/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { range } from 'ramda';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// components
|
||||
import { Steps } from 'primereact/steps';
|
||||
|
||||
const ApplicationSteps = ({ totalSteps = 0, activeStepIndex }) => {
|
||||
const rangeArr = range(1, totalSteps + 1);
|
||||
const items = rangeArr.map(() => ({ label: 'Passo' }));
|
||||
|
||||
// TODO update to using Steps after primereact is updated
|
||||
return(
|
||||
0 !== totalSteps
|
||||
? <span>{__('Passo', 'gepafin')}: {activeStepIndex + 1}</span>
|
||||
: null
|
||||
)
|
||||
|
||||
/*return(
|
||||
0 !== totalSteps
|
||||
? <Steps model={items} activeIndex={activeStepIndex} readOnly/>
|
||||
: null
|
||||
)*/
|
||||
}
|
||||
|
||||
export default ApplicationSteps
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { klona } from 'klona';
|
||||
import { head, range, is, pluck } from 'ramda';
|
||||
import { head, is, pluck, isEmpty } from 'ramda';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { TZDate } from '@date-fns/tz';
|
||||
|
||||
@@ -30,9 +30,9 @@ import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import { Skeleton } from 'primereact/skeleton';
|
||||
import { Button } from 'primereact/button';
|
||||
import FormField from '../../components/FormField';
|
||||
import { Steps } from 'primereact/steps';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Messages } from 'primereact/messages';
|
||||
import ApplicationSteps from './ApplicationSteps';
|
||||
|
||||
const BandoApplication = () => {
|
||||
const { id } = useParams();
|
||||
@@ -43,7 +43,6 @@ const BandoApplication = () => {
|
||||
const [totalSteps, setTotalSteps] = useState(0);
|
||||
const [completedSteps, setCompletedSteps] = useState(0);
|
||||
const [activeStep, setActiveStep] = useState(1);
|
||||
const [stepItems, setStepItems] = useState([{ label: 'Passo' }]);
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const toast = useRef(null);
|
||||
const formMsgs = useRef(null);
|
||||
@@ -54,7 +53,7 @@ const BandoApplication = () => {
|
||||
setValue,
|
||||
trigger,
|
||||
register,
|
||||
getValues,
|
||||
getValues
|
||||
} = useForm({ defaultValues: {}, mode: 'onChange' });
|
||||
const values = getValues();
|
||||
const validationFns = {
|
||||
@@ -67,6 +66,7 @@ const BandoApplication = () => {
|
||||
isUrl,
|
||||
isMarcaDaBollo
|
||||
}
|
||||
const activeStepIndex = activeStep - 1;
|
||||
|
||||
const onSubmit = () => {
|
||||
const applId = getApplicationId();
|
||||
@@ -91,7 +91,6 @@ const BandoApplication = () => {
|
||||
}
|
||||
|
||||
const errSubmitApplicationCallback = (data) => {
|
||||
console.log(data)
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
if (data.status === 'VALIDATION_ERROR') {
|
||||
if (formMsgs.current) {
|
||||
@@ -120,7 +119,7 @@ const BandoApplication = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const saveDraft = () => {
|
||||
const saveDraft = (saveAndMove = '') => {
|
||||
trigger();
|
||||
const formValues = getValues();
|
||||
const usedFieldsIds = pluck('id', formData);
|
||||
@@ -157,7 +156,7 @@ const BandoApplication = () => {
|
||||
formMsgs.current.clear();
|
||||
}
|
||||
|
||||
ApplicationService.saveDraft(applId, submitData, saveDraftCallback, errSaveDraftCallback, [
|
||||
ApplicationService.saveDraft(applId, submitData, (data) => saveDraftCallback(data, saveAndMove), errSaveDraftCallback, [
|
||||
['formId', formId]
|
||||
]);
|
||||
}
|
||||
@@ -168,7 +167,7 @@ const BandoApplication = () => {
|
||||
return !isNaN(parsed) ? parsed : 0;
|
||||
}
|
||||
|
||||
const saveDraftCallback = (data) => {
|
||||
const saveDraftCallback = (data, saveAndMove) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
@@ -177,8 +176,16 @@ const BandoApplication = () => {
|
||||
detail: __('Salvato!', 'gepafin')
|
||||
});
|
||||
}
|
||||
// update info about application completeness
|
||||
ApplicationService.getApplicationForm(data.data.id, getStatusCheckCallback, errGetStatusCheckCallbacks);
|
||||
if (!isEmpty(saveAndMove)) {
|
||||
storeSet.main.setAsyncRequest();
|
||||
ApplicationService.getApplicationForm(data.data.id, getApplFormCallback, errGetApplFormCallbacks, [
|
||||
['formId', formId],
|
||||
['action', saveAndMove]
|
||||
]);
|
||||
} else {
|
||||
// update info about application completeness
|
||||
ApplicationService.getApplicationForm(data.data.id, getStatusCheckCallback, errGetStatusCheckCallbacks);
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
@@ -213,31 +220,37 @@ const BandoApplication = () => {
|
||||
}
|
||||
|
||||
const goBackward = () => {
|
||||
if (formId) {
|
||||
saveDraft('PREVIOUS');
|
||||
/*if (formId) {
|
||||
const applId = getApplicationId();
|
||||
storeSet.main.setAsyncRequest();
|
||||
ApplicationService.getApplicationForm(applId, getApplFormCallback, errGetApplFormCallbacks, [
|
||||
['formId', formId],
|
||||
['action', 'PREVIOUS']
|
||||
]);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
const goForward = () => {
|
||||
if (formId) {
|
||||
saveDraft('NEXT');
|
||||
/*if (formId) {
|
||||
const applId = getApplicationId();
|
||||
storeSet.main.setAsyncRequest();
|
||||
ApplicationService.getApplicationForm(applId, getApplFormCallback, errGetApplFormCallbacks, [
|
||||
['formId', formId],
|
||||
['action', 'NEXT']
|
||||
]);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
const getApplFormCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
setBandoTitle(data.data.callTitle);
|
||||
setFormData(data.data.applicationFormResponse.content);
|
||||
setFormId(data.data.formId);
|
||||
setTotalSteps(data.data.totalFormSteps);
|
||||
setCompletedSteps(data.data.completedSteps);
|
||||
setActiveStep(data.data.currentStep);
|
||||
|
||||
if (data.data.applicationFormResponse.formFields) {
|
||||
const submitData = data.data.applicationFormResponse.formFields.map((o) => ({
|
||||
@@ -246,11 +259,6 @@ const BandoApplication = () => {
|
||||
}));
|
||||
setFormInitialData(submitData)
|
||||
}
|
||||
|
||||
setFormId(data.data.formId);
|
||||
setTotalSteps(data.data.totalFormSteps);
|
||||
setCompletedSteps(data.data.completedSteps);
|
||||
setActiveStep(data.data.currentStep);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
@@ -285,11 +293,6 @@ const BandoApplication = () => {
|
||||
newFormData.map(o => setValue(o.fieldId, o.fieldValue));
|
||||
}, [formInitialData]);
|
||||
|
||||
useEffect(() => {
|
||||
const rangeArr = range(1, totalSteps + 1);
|
||||
setStepItems(rangeArr.map(() => ({ label: 'Passo' })));
|
||||
}, [totalSteps])
|
||||
|
||||
useEffect(() => {
|
||||
const applId = getApplicationId();
|
||||
|
||||
@@ -312,8 +315,7 @@ const BandoApplication = () => {
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
{!isAsyncRequest
|
||||
? <Steps model={stepItems} activeIndex={activeStep - 1}/> : null}
|
||||
<ApplicationSteps totalSteps={totalSteps} activeStepIndex={activeStepIndex}/>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
@@ -327,12 +329,13 @@ const BandoApplication = () => {
|
||||
const text = head(o.settings.filter(o => o.name === 'text'));
|
||||
const placeholder = head(o.settings.filter(o => o.name === 'placeholder'));
|
||||
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 mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||
let mimeValue = '';
|
||||
|
||||
if (mime) {
|
||||
mimeValue = mime.value.map(o => o.code).join(',');
|
||||
mimeValue = mime.value.map(o => o.code);
|
||||
}
|
||||
|
||||
const validations = Object.keys(o.validators).reduce((acc, cur) => {
|
||||
@@ -367,13 +370,14 @@ const BandoApplication = () => {
|
||||
register={register}
|
||||
errors={errors}
|
||||
defaultValue={values[o.id]}
|
||||
maxFractionDigits={step}
|
||||
maxFractionDigits={step ? step.value : 0}
|
||||
accept={mimeValue}
|
||||
config={validations}
|
||||
options={options ? options.value : []}
|
||||
setDataFn={setValue}
|
||||
sourceId={getApplicationId()}
|
||||
useGrouping={false}
|
||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||
/>
|
||||
})}
|
||||
|
||||
|
||||
@@ -162,7 +162,6 @@ const BandoEditFormStep1 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
}
|
||||
|
||||
const errLookupdataCallback = (data) => {
|
||||
console.log('errLookupdataCallback', data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors, st
|
||||
errors={errors}
|
||||
defaultValue={values['docs']}
|
||||
config={{ required: __('È obbligatorio', 'gepafin') }}
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
accept={["application/pdf", "application/vnd.ms-excel"]}
|
||||
chooseLabel={__('Aggiungi documento', 'gepafin')}
|
||||
multiple={true}
|
||||
doctype='document'
|
||||
|
||||
@@ -22,6 +22,7 @@ import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
||||
import { Messages } from 'primereact/messages';
|
||||
import FormsService from '../../service/forms-service';
|
||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const BandoEdit = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
@@ -32,6 +33,7 @@ const BandoEdit = () => {
|
||||
const [forms, setForms] = useState([]);
|
||||
const formRef = useRef(null);
|
||||
const bandoMsgs = useRef(null);
|
||||
const toast = useRef(null);
|
||||
|
||||
const stepItems = [
|
||||
{
|
||||
@@ -81,11 +83,18 @@ const BandoEdit = () => {
|
||||
bandoMsgs.current.show([
|
||||
{
|
||||
id: '99',
|
||||
sticky: true, severity: 'success', summary: '',
|
||||
sticky: true, severity: 'info', summary: '',
|
||||
detail: __('Potrai pubblicare il tuo Bando.', 'gepafin'),
|
||||
closable: false
|
||||
}
|
||||
]);
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'info',
|
||||
summary: '',
|
||||
detail: __('Potrai pubblicare il tuo Bando.', 'gepafin')
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
@@ -125,6 +134,13 @@ const BandoEdit = () => {
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: '',
|
||||
detail: __('Pubblicato!', 'gepafin')
|
||||
});
|
||||
}
|
||||
setData(data.data);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
@@ -247,6 +263,7 @@ const BandoEdit = () => {
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<Messages ref={bandoMsgs}/>
|
||||
<Toast ref={toast} />
|
||||
|
||||
{!isEmpty(data)
|
||||
? <>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { head } from 'ramda';
|
||||
import { head, pathOr } from 'ramda';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
@@ -7,10 +7,11 @@ import renderHtmlContent from '../../../../helpers/renderHtmlContent';
|
||||
|
||||
const BuilderElementProperLabel = ({ id, defaultLabel }) => {
|
||||
const elements = useStore().main.formElements();
|
||||
const element = head(elements.filter(o => o.id === id));
|
||||
const [label, setLabel] = useState('');
|
||||
const isRequired = pathOr(false, ['validators', 'isRequired'], element)
|
||||
|
||||
useEffect(() => {
|
||||
const element = head(elements.filter(o => o.id === id));
|
||||
const label = head(element.settings.filter(o => o.name === 'label'));
|
||||
const text = head(element.settings.filter(o => o.name === 'text'));
|
||||
|
||||
@@ -23,7 +24,10 @@ const BuilderElementProperLabel = ({ id, defaultLabel }) => {
|
||||
}
|
||||
}, [elements]);
|
||||
|
||||
return <div className="label">{renderHtmlContent(label)}</div>
|
||||
return <div className="label">
|
||||
{renderHtmlContent(label)}
|
||||
{isRequired ? <span className="appForm__field--required">*</span> : null}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default BuilderElementProperLabel;
|
||||
@@ -23,7 +23,7 @@ import FormsService from '../../service/forms-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
|
||||
// TODO temp data
|
||||
import { elementItems } from '../../tempData';
|
||||
//import { elementItems } from '../../tempData';
|
||||
|
||||
const BandoFormsEdit = () => {
|
||||
const { id, formId } = useParams();
|
||||
@@ -168,7 +168,14 @@ const BandoFormsEdit = () => {
|
||||
}
|
||||
|
||||
const openPreview = () => {
|
||||
doSave(true);
|
||||
if ('PUBLISH' !== bandoStatus) {
|
||||
doSave(true);
|
||||
} else {
|
||||
const bandoId = getBandoId();
|
||||
const parsedFormId = parseInt(formId)
|
||||
const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
|
||||
navigate(`/bandi/${bandoId}/forms/${bandoFormId}/preview`);
|
||||
}
|
||||
}
|
||||
|
||||
const confirmDelete = (event) => {
|
||||
@@ -208,8 +215,8 @@ const BandoFormsEdit = () => {
|
||||
|
||||
const getElementItemsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
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(elementItems.sort((a, b) => a.sortOrder - b.sortOrder));
|
||||
storeSet.main.elementItems(data.data.sort((a, b) => a.sortOrder - b.sortOrder));
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ const BandoFormsPreview = () => {
|
||||
}, {});
|
||||
|
||||
return ['paragraph'].includes(o.name) && text
|
||||
? <div className="appForm__content">{renderHtmlContent(text.value)}</div>
|
||||
? <div className="appForm__content" key={o.id}>{renderHtmlContent(text.value)}</div>
|
||||
: <FormField
|
||||
key={o.id}
|
||||
type={o.name}
|
||||
@@ -167,6 +167,7 @@ const BandoFormsPreview = () => {
|
||||
options={options ? options.value : []}
|
||||
setDataFn={setValue}
|
||||
sourceId={0}
|
||||
useGrouping={false}
|
||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||
/>
|
||||
})}
|
||||
|
||||
@@ -95,10 +95,11 @@ const BandoView = () => {
|
||||
icon="pi pi-arrow-left" iconPos="left"/>
|
||||
</div>
|
||||
|
||||
<picture className="appPageSection__hero">
|
||||
<source srcSet={data.images[0] ? data.images[0].filePath : ''}/>
|
||||
<img src={data.images[0] ? data.images[0].filePath : ''} alt={data.name}/>
|
||||
</picture>
|
||||
{!isEmpty(data.images)
|
||||
? <picture className="appPageSection__hero">
|
||||
<source srcSet={data.images[0] ? data.images[0].filePath : ''}/>
|
||||
<img src={data.images[0] ? data.images[0].filePath : ''} alt={data.name}/>
|
||||
</picture> : null}
|
||||
|
||||
<div className="appPageSection__withBorder">
|
||||
<h2>{__('Descrizione breve', 'gepafin')}</h2>
|
||||
@@ -187,9 +188,9 @@ const BandoView = () => {
|
||||
<Accordion>
|
||||
{data.faq
|
||||
.filter(o => o.isVisible)
|
||||
.map((o, i) => <AccordionTab key={i} header={o.value}>
|
||||
.map((o, i) => <AccordionTab key={i} header={renderHtmlContent(o.value)}>
|
||||
<p>
|
||||
{o.response}
|
||||
{renderHtmlContent(o.response)}
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
</Accordion>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { is, isEmpty, pathOr, isNil } from 'ramda';
|
||||
import { is, isEmpty, isNil } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
@@ -16,7 +16,6 @@ import renderHtmlContent from '../../helpers/renderHtmlContent';
|
||||
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 { Messages } from 'primereact/messages';
|
||||
import { Message } from 'primereact/message';
|
||||
@@ -29,14 +28,13 @@ import { Editor } from 'primereact/editor';
|
||||
|
||||
const BandoViewBeneficiario = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
const companies = useStore().main.companies();
|
||||
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState({});
|
||||
const [newQuestion, setNewQuestion] = useState('');
|
||||
const [applicationObj, setApplicationObj] = useState(true);
|
||||
const bandoMsgs = useRef(null);
|
||||
const chosenCompanyId = pathOr(0, [0, 'id'], companies);
|
||||
|
||||
const scaricaBando = () => {
|
||||
|
||||
@@ -90,12 +88,12 @@ const BandoViewBeneficiario = () => {
|
||||
bandoMsgs.current.clear();
|
||||
}
|
||||
const obj = {
|
||||
"id": null,
|
||||
"lookUpDataId": null,
|
||||
"title": newQuestion,
|
||||
"value": newQuestion,
|
||||
"response": "",
|
||||
"isVisible": false
|
||||
'id': null,
|
||||
'lookUpDataId': null,
|
||||
'title': newQuestion,
|
||||
'value': newQuestion,
|
||||
'response': '',
|
||||
'isVisible': false
|
||||
}
|
||||
storeSet.main.setAsyncRequest();
|
||||
FaqItemService.addQuestion(id, obj, createCallBack, errCreateCallback, [['companyId', chosenCompanyId]])
|
||||
@@ -161,7 +159,7 @@ const BandoViewBeneficiario = () => {
|
||||
|
||||
const getApplCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
if(data.data.length) {
|
||||
if (data.data.length) {
|
||||
setApplicationObj(data.data[0]);
|
||||
}
|
||||
}
|
||||
@@ -220,10 +218,11 @@ const BandoViewBeneficiario = () => {
|
||||
|
||||
{!isAsyncRequest && !isEmpty(data)
|
||||
? <div className="appPage__content">
|
||||
<picture className="appPageSection__hero">
|
||||
<source srcSet={data.images[0] ? data.images[0].filePath : ''}/>
|
||||
<img src={data.images[0] ? data.images[0].filePath : ''} alt={data.name}/>
|
||||
</picture>
|
||||
{!isEmpty(data.images)
|
||||
? <picture className="appPageSection__hero">
|
||||
<source srcSet={data.images[0] ? data.images[0].filePath : ''}/>
|
||||
<img src={data.images[0] ? data.images[0].filePath : ''} alt={data.name}/>
|
||||
</picture> : null}
|
||||
|
||||
<div className="appPageSection__withBorder">
|
||||
<h2>{__('Descrizione breve', 'gepafin')}</h2>
|
||||
@@ -312,11 +311,11 @@ const BandoViewBeneficiario = () => {
|
||||
<Accordion>
|
||||
{data.faq
|
||||
.filter(o => o.isVisible)
|
||||
.map((o, i) => <AccordionTab key={i} header={o.value}>
|
||||
<p>
|
||||
{o.response}
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
.map((o, i) => <AccordionTab key={i} header={renderHtmlContent(o.value)}>
|
||||
<p>
|
||||
{renderHtmlContent(o.response)}
|
||||
</p>
|
||||
</AccordionTab>)}
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
@@ -345,7 +344,8 @@ const BandoViewBeneficiario = () => {
|
||||
|
||||
{chosenCompanyId === 0
|
||||
? <>
|
||||
<Message severity="error" text={__("Devi creare un'azienda prima di partecipare nei bandi. Vai nel profilo aziendale.", 'gepafin')} />
|
||||
<Message severity="error"
|
||||
text={__('Devi creare un\'azienda prima di partecipare nei bandi. Vai nel profilo aziendale.', 'gepafin')}/>
|
||||
</>
|
||||
: null}
|
||||
|
||||
@@ -387,7 +387,8 @@ const BandoViewBeneficiario = () => {
|
||||
<h2>{__('Contatti per Assistenza', 'gepafin')}</h2>
|
||||
<div className="row rowContent">
|
||||
<p>Email: {data.email}</p>
|
||||
{!isNil(data.phoneNumber) ? <p>{__('Telefono', 'gepafin')}: +39 {data.phoneNumber}</p> : null}
|
||||
{!isNil(data.phoneNumber) ?
|
||||
<p>{__('Telefono', 'gepafin')}: +39 {data.phoneNumber}</p> : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { isEmpty, isNil, pathOr } from 'ramda';
|
||||
import { isEmpty, isNil, pathOr, head } from 'ramda';
|
||||
import { klona } from 'klona';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
import { storeSet, useStore, storeGet } from '../../store';
|
||||
|
||||
// components
|
||||
import { Messages } from 'primereact/messages';
|
||||
@@ -18,7 +19,6 @@ import CompanyService from '../../service/company-service';
|
||||
// tools
|
||||
import { isPIVA } from '../../helpers/validators';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import { klona } from 'klona';
|
||||
|
||||
const ProfileCompany = () => {
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
@@ -67,7 +67,19 @@ const ProfileCompany = () => {
|
||||
|
||||
const updateCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
//setData(getFormattedBandiData(data.data));
|
||||
const company = klona(data.data);
|
||||
const companies = storeGet.main.companies();
|
||||
const existingCompany = head(companies.filter(o => o.id === company.id));
|
||||
let newCompanies = [];
|
||||
|
||||
if (existingCompany) {
|
||||
newCompanies = companies.map(o => o.id === company.id ? company : o)
|
||||
} else {
|
||||
newCompanies = [...companies, company];
|
||||
storeSet.main.chosenCompanyId(company.id);
|
||||
}
|
||||
|
||||
storeSet.main.companies(newCompanies);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
@@ -129,7 +141,6 @@ const ProfileCompany = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const chosenCompany = pathOr({}, [0], companies);
|
||||
console.log('chosenCompany', chosenCompany, companies)
|
||||
setFormInitialData(chosenCompany);
|
||||
}, [companies]);
|
||||
|
||||
|
||||
@@ -161,10 +161,7 @@ const Registration = () => {
|
||||
control={control}
|
||||
errors={errors}
|
||||
config={{
|
||||
required: __('È obbligatorio', 'gepafin'),
|
||||
validate: {
|
||||
isCodiceFiscale
|
||||
}
|
||||
required: __('È obbligatorio', 'gepafin')
|
||||
}}
|
||||
placeholder="ABC1234"
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,7 @@ const initialStore = {
|
||||
userData: {},
|
||||
token: '',
|
||||
companies: [],
|
||||
chosenCompanyId: 0,
|
||||
// bando form
|
||||
formInitialData: {},
|
||||
// form builder
|
||||
|
||||
@@ -6,7 +6,8 @@ const zustandXOpts = {
|
||||
enabled: true,
|
||||
partialize: (state) => ({
|
||||
//userData: state.userData,
|
||||
token: state.token
|
||||
token: state.token,
|
||||
chosenCompanyId: state.chosenCompanyId,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
334
src/tempData.js
334
src/tempData.js
@@ -1,337 +1,3 @@
|
||||
export const bandoTest = {
|
||||
"name": "Innovazione digitale 2024",
|
||||
"confidi": false,
|
||||
"descriptionShort": "Supporto alle PMI per progetti di digitalizzazione e innovazione tecnologica.",
|
||||
"descriptionLong": "Il bando \"Innovazione Digitale 2024\" mira a sostenere le PMI nell'adozione di tecnologie digitali innovative. I progetti finanziabili includono l'implementazione di soluzioni di intelligenza artificiale, blockchain, IoT, e altre tecnologie avanzate che possono migliorare la competitività delle imprese.",
|
||||
"documentationRequested": "Documentazione richiesta*",
|
||||
"dates": [
|
||||
"2024-08-27T22:00:00.000Z",
|
||||
"2024-10-29T23:00:00.000Z"
|
||||
],
|
||||
"amount": 10000,
|
||||
"amountMax": 2500,
|
||||
"aimedTo": [
|
||||
{
|
||||
"id": 3,
|
||||
"value": "PMI con sede in Umbria",
|
||||
"status": "existing"
|
||||
}
|
||||
],
|
||||
"faq": [
|
||||
{
|
||||
"id": 2,
|
||||
"question": "Question 1?",
|
||||
"answer": "Lorem ipsum dolor",
|
||||
"visible": true,
|
||||
"status": "existing"
|
||||
}
|
||||
],
|
||||
status: 'draft',
|
||||
id: 11,
|
||||
createdDate: "2024-08-07T08:14:07.849Z",
|
||||
updatedDate: "2024-08-07T08:14:07.849Z",
|
||||
"documentation":[
|
||||
{
|
||||
"id":18,
|
||||
"name":"SCR-20240820-kiwn.pdf",
|
||||
"filePath":"https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/SCR-20240820-kiwn.pdf",
|
||||
"description":null,
|
||||
"createdDate":"2024-08-26T06:51:11.800799252",
|
||||
"updatedDate":"2024-08-26T06:51:11.800826092"
|
||||
}
|
||||
],
|
||||
"criteria":[
|
||||
{
|
||||
"id":null,
|
||||
"value":"Innovatività del progetto",
|
||||
"status":"new",
|
||||
"score":9
|
||||
},
|
||||
{
|
||||
"id":null,
|
||||
"value":"Impatto sulla competitività dell'azienda",
|
||||
"status":"new",
|
||||
"score":3
|
||||
},
|
||||
{
|
||||
"id":null,
|
||||
"value":"Sostenibilità economico-finanziaria",
|
||||
"status":"new",
|
||||
"score":5
|
||||
}
|
||||
],
|
||||
"threshold":11,
|
||||
"images":[
|
||||
{
|
||||
"id":19,
|
||||
"name":"photo-1618245318763-a15156d6b23c.avif",
|
||||
"filePath":"https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/photo-1618245318763-a15156d6b23c.avif",
|
||||
"description":null,
|
||||
"createdDate":"2024-08-26T07:28:16.954763338",
|
||||
"updatedDate":"2024-08-26T07:28:16.954843237"
|
||||
}
|
||||
],
|
||||
"checklist":[
|
||||
{
|
||||
"id":null,
|
||||
"value":"Innovatività del progetto",
|
||||
"status":"new"
|
||||
},
|
||||
{
|
||||
"id":null,
|
||||
"value":"Some new check",
|
||||
"status":"new"
|
||||
},
|
||||
{
|
||||
"id":null,
|
||||
"value":"Check #2",
|
||||
"status":"new"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const formData = {
|
||||
id: 15,
|
||||
label: 'La forma per Innovazione digitale 2024',
|
||||
content: [
|
||||
{
|
||||
"id": "a9a8aeb479",
|
||||
"name": "textinput",
|
||||
"label": "Testo Breve",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Testo Breve"
|
||||
},
|
||||
{
|
||||
"name": "placeholder",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": true,
|
||||
"minLength": "3",
|
||||
"maxLength": null,
|
||||
"pattern": null,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 1
|
||||
},
|
||||
{
|
||||
"id": "a20469fc97",
|
||||
"name": "textarea",
|
||||
"label": "Testo Lungo",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Testo Lungo"
|
||||
},
|
||||
{
|
||||
"name": "placeholder",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"pattern": null,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 2
|
||||
},
|
||||
{
|
||||
"id": "a21dc560f6",
|
||||
"name": "wysiwyg",
|
||||
"label": "Campo di Testo Formattato",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Testo Formattato"
|
||||
},
|
||||
{
|
||||
"name": "placeholder",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"pattern": null,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 3
|
||||
},
|
||||
{
|
||||
"id": "a5c3860c1a",
|
||||
"name": "numberinput",
|
||||
"label": "Campo Numerico",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Numero"
|
||||
},
|
||||
{
|
||||
"name": "placeholder",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "step",
|
||||
"value": 0
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": false,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": null,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 4
|
||||
},
|
||||
{
|
||||
"id": "a7252ecc8d",
|
||||
"name": "radio",
|
||||
"label": "Scelta Singola",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Scelta Singola"
|
||||
},
|
||||
{
|
||||
"name": "options",
|
||||
"value": [
|
||||
{
|
||||
"name": "o8df4ffa62",
|
||||
"label": "Radio opzione A"
|
||||
},
|
||||
{
|
||||
"name": "o3ed6fb4d8",
|
||||
"label": "Radio opzione B"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": true,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 5
|
||||
},
|
||||
{
|
||||
"id": "a778783c9d",
|
||||
"name": "select",
|
||||
"label": "Menu a Tendina",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Menu a Tendina"
|
||||
},
|
||||
{
|
||||
"name": "options",
|
||||
"value": [
|
||||
{
|
||||
"name": "od9f50d8a8",
|
||||
"label": "Opzione A"
|
||||
},
|
||||
{
|
||||
"name": "o8cb208732",
|
||||
"label": "Opzione B"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": false,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 6
|
||||
},
|
||||
{
|
||||
"id": "afee29df1a",
|
||||
"name": "switch",
|
||||
"label": "Casella di Spunta",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Casella di Spunta"
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": false
|
||||
},
|
||||
"dbId": 8
|
||||
},
|
||||
{
|
||||
"id": "a5fdbd77df",
|
||||
"name": "checkboxes",
|
||||
"label": "Scelta Multipla",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Scelta Multipla"
|
||||
},
|
||||
{
|
||||
"name": "options",
|
||||
"value": [
|
||||
{
|
||||
"name": "o55ea20665",
|
||||
"label": "Opz checkbox A"
|
||||
},
|
||||
{
|
||||
"name": "oc10db3d79",
|
||||
"label": "Opz checkbox B"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": true,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 7
|
||||
},
|
||||
{
|
||||
"id": "a2810fd8a1",
|
||||
"name": "fileupload",
|
||||
"label": "Caricamento File",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Caricamento File"
|
||||
},
|
||||
{
|
||||
"name": "mime",
|
||||
"value": ['image/jpeg', 'image/png']
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": true,
|
||||
"maxSize": 100000,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 10
|
||||
},
|
||||
{
|
||||
"id": "ae14c94da7",
|
||||
"name": "datepicker",
|
||||
"label": "Data",
|
||||
"settings": [
|
||||
{
|
||||
"name": "label",
|
||||
"value": "Data"
|
||||
}
|
||||
],
|
||||
"validators": {
|
||||
"isRequired": true,
|
||||
"custom": null
|
||||
},
|
||||
"dbId": 9
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const elementItems = [
|
||||
{
|
||||
id: 1,
|
||||
|
||||
Reference in New Issue
Block a user