diff --git a/package.json b/package.json
index 0783782..ccd2660 100644
--- a/package.json
+++ b/package.json
@@ -4,53 +4,54 @@
"private": true,
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
- "@babel/preset-react": "7.24.7",
- "@date-fns/tz": "1.1.2",
- "@emailjs/browser": "^4.4.1",
- "@emotion/styled": "11.13.0",
+ "@babel/preset-react": "7.25.9",
+ "@date-fns/tz": "1.2.0",
+ "@emailjs/browser": "4.4.1",
+ "@emotion/styled": "11.13.5",
"@number-flow/react": "0.4.2",
- "@sentry/browser": "^8.42.0",
- "@stomp/stompjs": "^7.0.0",
- "@tanstack/react-table": "^8.20.5",
- "@wordpress/i18n": "5.8.0",
- "@wordpress/react-i18n": "4.8.0",
- "@xyflow/react": "12.3.1",
+ "@sentry/browser": "8.42.0",
+ "@stomp/stompjs": "7.0.0",
+ "@tanstack/react-table": "8.20.5",
+ "@wordpress/i18n": "5.13.0",
+ "@wordpress/react-i18n": "4.13.0",
"codice-fiscale-js": "2.3.22",
- "copy-to-clipboard": "^3.3.3",
- "deep-object-diff": "^1.1.9",
- "dompurify": "3.1.7",
+ "copy-to-clipboard": "3.3.3",
+ "deep-object-diff": "1.1.9",
+ "dompurify": "3.2.2",
"fast-deep-equal": "3.1.3",
- "hotkeys-js": "^3.13.7",
- "html-react-parser": "5.1.16",
+ "hotkeys-js": "3.13.7",
+ "html-react-parser": "5.1.18",
"jwt-decode": "4.0.0",
"klona": "2.0.6",
+ "leader-line-new": "1.1.9",
"luxon": "3.5.0",
"object-path-immutable": "4.1.2",
"primeicons": "7.0.0",
- "primereact": "10.8.4",
- "quill": "2.0.2",
+ "primereact": "10.8.5",
+ "quill": "2.0.3",
"ramda": "0.30.1",
"react": "18.3.1",
"react-dnd": "16.0.1",
"react-dnd-html5-backend": "16.0.1",
"react-dom": "18.3.1",
- "react-hook-form": "7.53.0",
- "react-router-dom": "6.26.2",
+ "react-hook-form": "7.53.2",
+ "react-router-dom": "7.0.1",
"react-scripts": "5.0.1",
+ "recharts": "2.15.0",
"sockjs-client": "^1.6.1",
"validate.js": "0.13.1",
"zustand": "4.5.4",
"zustand-x": "3.0.4"
},
"devDependencies": {
- "@babel/cli": "7.25.6",
- "@babel/core": "7.25.2",
- "@babel/plugin-syntax-jsx": "7.24.7",
- "@wordpress/babel-plugin-makepot": "6.8.0",
+ "@babel/cli": "7.25.9",
+ "@babel/core": "7.26.0",
+ "@babel/plugin-syntax-jsx": "7.25.9",
+ "@wordpress/babel-plugin-makepot": "6.13.0",
"babel-plugin-macros": "3.1.0",
- "node-wp-i18n": "^1.2.7",
- "sass": "1.79.3",
- "sass-loader": "16.0.2"
+ "node-wp-i18n": "1.2.7",
+ "sass": "1.81.0",
+ "sass-loader": "16.0.3"
},
"scripts": {
"start": "GENERATE_SOURCEMAP=false react-scripts start",
diff --git a/src/assets/scss/components/charts.scss b/src/assets/scss/components/charts.scss
new file mode 100644
index 0000000..15cff0e
--- /dev/null
+++ b/src/assets/scss/components/charts.scss
@@ -0,0 +1,39 @@
+.chartCard {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
+ min-height: 220px;
+ padding: 20px 5px;
+ border-radius: 6px;
+ border: 1px solid #EAB308;
+ background: #FFF;
+}
+
+.chartCard__title {
+ color: var(--global-textColor);
+ font-size: 18px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+ margin: 0 0 16px;
+}
+
+.chartCard__chart {
+ width: 100%;
+ height: 24rem;
+}
+
+.chartCard__tooltip {
+ padding: 5px 10px;
+ background-color: white;
+ border: 1px solid var(--global-textColor);
+}
+
+.chartCard__tooltipTitle {
+ font-weight: bold;
+}
+
+.chartCard__tooltipText {
+
+}
\ No newline at end of file
diff --git a/src/assets/scss/components/flowBuilder.scss b/src/assets/scss/components/flowBuilder.scss
index 04e3e83..8916a7b 100644
--- a/src/assets/scss/components/flowBuilder.scss
+++ b/src/assets/scss/components/flowBuilder.scss
@@ -32,4 +32,136 @@
font-size: 13px;
text-align: center;
}
+}
+.flowContainer {
+ width: 100%;
+ overflow-x: auto;
+ margin-top: 30px;
+}
+
+.flowContainerInner {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: max-content;
+ margin: 0 auto;
+}
+
+.flowContainer__level {
+ display: flex;
+ justify-content: center;
+ gap: 20px;
+ /*min-height: 240px;*/
+ /*margin: 0 auto;*/
+
+ &.initialLevel {
+ padding: 0 0 30px;
+ }
+
+ &.intermediateLevel, &.finalLevel {
+ padding: 30px 0 30px;
+ }
+
+ &.intermediateLevel {
+ border-bottom: 1px solid var(--table-border-color);
+ border-top: 1px solid var(--table-border-color);
+ }
+}
+
+.flowContainer__flowItem {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: 280px;
+ min-width: 280px;
+ padding: 15px;
+ border: 1px solid var(--table-border-color);
+ z-index: 9;
+
+ .flowContainer__flowItemInner > label {
+ border-color: #757575;
+ background-color: #757575;
+ color: white;
+ }
+
+ &.initialForm, &.finalForm {
+ .flowContainer__flowItemInner > label {
+ border-color: var(--card-full-background-color-3);
+ background-color: var(--card-full-background-color-3);
+ color: white;
+ }
+ }
+
+ &.levelForms, &.initialForm {
+ &:after {
+ position: absolute;
+ bottom: -31px;
+ left: 50%;
+ content: '';
+ width: 1px;
+ height: 31px;
+ background-color: var(--table-border-color);
+ }
+ }
+
+ &.levelForms, &.finalForm {
+ &:before {
+ position: absolute;
+ top: -31px;
+ left: 50%;
+ content: '';
+ width: 1px;
+ height: 31px;
+ background-color: var(--table-border-color);
+ }
+ }
+}
+
+.flowContainer__levelMaskStart, .flowContainer__levelMaskEnd {
+ position: absolute;
+ width: 140px;
+ height: 100% ;
+ top: -1px;
+ background-color: white;
+}
+.flowContainer__levelMaskStart {
+ left: 0;
+}
+.flowContainer__levelMaskEnd {
+ right: 0;
+}
+
+.flowContainer__flowItemInner {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ width: 100%;
+ max-width: 250px;
+ border: 1px solid var(--panel-content-borderColor);
+ height: 100%;
+
+ > label {
+ display: flex;
+ justify-content: center;
+ padding: 10px;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px;
+ text-align: center;
+ }
+}
+
+.flowContainer__flowItemContent {
+ padding: 5px;
+ display: flex;
+ flex-direction: column;
+
+ .appForm__field {
+ margin-top: 10px;
+
+ label {
+ text-align: center;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/assets/scss/components/misc.scss b/src/assets/scss/components/misc.scss
index b809ae8..162068e 100644
--- a/src/assets/scss/components/misc.scss
+++ b/src/assets/scss/components/misc.scss
@@ -147,6 +147,14 @@
max-width: 100%;
}
+.p-password.p-inputwrapper {
+ width: 100%;
+
+ > div, input {
+ width: 100%;
+ }
+}
+
.p-inputgroup.flex-1 {
align-items: center;
}
diff --git a/src/assets/scss/components/topBar.scss b/src/assets/scss/components/topBar.scss
index fc73015..bb9c86d 100644
--- a/src/assets/scss/components/topBar.scss
+++ b/src/assets/scss/components/topBar.scss
@@ -72,4 +72,10 @@
i {
margin-right: 7px;
}
+}
+
+@media (max-width: 500px) {
+ .topBar__endContent {
+ flex-wrap: wrap;
+ }
}
\ No newline at end of file
diff --git a/src/assets/scss/theme.scss b/src/assets/scss/theme.scss
index 943b18a..53499eb 100644
--- a/src/assets/scss/theme.scss
+++ b/src/assets/scss/theme.scss
@@ -21,6 +21,7 @@
--message-warning-color: #cc8925;
--message-info-background: rgba(183, 183, 183, 0.7);
--message-info-color: #3B82F6;
+ --panel-content-borderColor: #E5E7EB;
--card-full-background-color-2: #EEC137;
--card-full-background-color-3: #FA8E42;
@@ -49,3 +50,4 @@
@import "./components/evaluation.scss";
@import "./components/fieldsRepeater.scss";
@import "./components/notificationsSidebar.scss";
+@import "./components/charts.scss";
diff --git a/src/components/ChartDomandePerBando/index.js b/src/components/ChartDomandePerBando/index.js
new file mode 100644
index 0000000..700e6a7
--- /dev/null
+++ b/src/components/ChartDomandePerBando/index.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import { __ } from '@wordpress/i18n';
+import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
+import { isEmpty } from 'ramda';
+
+// components
+
+
+const ChartDomandePerBando = ({ title, data = [] }) => {
+ const truncateText = (text) => {
+ const maxLength = 12;
+ if (typeof text === 'string' && text.length > maxLength) {
+ return `${text.slice(0, maxLength)}...`;
+ }
+ return text;
+ };
+
+ // Custom tooltip
+ const CustomTooltip = ({ active, payload, label }) => {
+ if (active && payload && payload.length) {
+ return (
+
+
{label}
+
+ {__('Domande', 'gepafin')}: {payload[0].value}
+
+
+ );
+ }
+ return null;
+ };
+
+ return (
+ {title ?
{title} : null}
+ {data && !isEmpty(data)
+ ?
+
+
+
+
+
+ }/>
+
+
+
+
+
: null}
+
)
+}
+
+export default ChartDomandePerBando;
\ No newline at end of file
diff --git a/src/components/ChartStatoDomande/index.js b/src/components/ChartStatoDomande/index.js
new file mode 100644
index 0000000..856fd6c
--- /dev/null
+++ b/src/components/ChartStatoDomande/index.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { __ } from '@wordpress/i18n';
+import { Tooltip, ResponsiveContainer, Cell, Pie, PieChart } from 'recharts';
+import { isEmpty } from 'ramda';
+import getBandoLabel from '../../helpers/getBandoLabel';
+
+// components
+
+
+const ChartStatoDomande = ({ title, data = [] }) => {
+ const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884d8', '#82ca9d'];
+
+ const CustomTooltip = ({ active, payload }) => {
+ if (active && payload && payload.length) {
+ return (
+
+
{getBandoLabel(payload[0].name)}
+
+ {__('Domande', 'gepafin')}: {payload[0].value}
+
+
+ );
+ }
+ return null;
+ };
+
+ return (
+ {title ?
{title} : null}
+ {data && !isEmpty(data)
+ ?
+
+
+ `${(percent * 100).toFixed(0)}%`}
+ outerRadius={120}
+ fill="#8884d8"
+ dataKey="numberOfApplications"
+ nameKey="status"
+ >
+ {data.map((entry, index) => (
+ |
+ ))}
+
+ } />
+
+
+
: null}
+
)
+}
+
+export default ChartStatoDomande;
\ No newline at end of file
diff --git a/src/components/FlowBuilder/components/NodeInitialForm/index.js b/src/components/FlowBuilder/components/NodeInitialForm/index.js
deleted file mode 100644
index 79fe833..0000000
--- a/src/components/FlowBuilder/components/NodeInitialForm/index.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { Handle, Position } from '@xyflow/react';
-import { isEmpty, head } from 'ramda';
-
-// store
-import { storeGet, storeSet } from '../../../../store';
-import { __ } from '@wordpress/i18n';
-
-const NodeInitialForm = ({ data: { id, label = '' } }) => {
- const flowData = storeGet.main.flowData();
- const [value, setValue] = useState('');
-
- useEffect(() => {
- const flowForms = storeGet.main.flowForms();
- const form = head(flowForms.filter(o => String(o.id) === String(id)));
- const flowDataItem = head(flowData.filter(o => String(o.formId) === String(id)));
-
- if (form && flowDataItem) {
- const field = head(form.content.filter(o => o.id === flowDataItem.chosenField));
-
- if (field) {
- const label = head(field.settings.filter(o => o.name === 'label'));
- setValue(label ? label.value : field.label);
- }
- }
- }, [flowData]);
-
- return (
-
-
- {value}
- {/*{options && !isEmpty(options)
- ? : null}*/}
-
-
- );
-}
-
-export default NodeInitialForm;
\ No newline at end of file
diff --git a/src/components/FlowBuilder/components/NodeIntermediateForm/index.js b/src/components/FlowBuilder/components/NodeIntermediateForm/index.js
deleted file mode 100644
index 8cc3a0e..0000000
--- a/src/components/FlowBuilder/components/NodeIntermediateForm/index.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { Handle, Position } from '@xyflow/react';
-import { head, isEmpty } from 'ramda';
-import { __ } from '@wordpress/i18n';
-
-import { useStore, storeSet, storeGet } from '../../../../store';
-
-const NodeIntermediateForm = ({ data: { id, label = '' } }) => {
- const flowEdges = useStore().main.flowEdges();
- const flowData = useStore().main.flowData();
- const [options, setOptions] = useState([]);
- const [value, setValue] = useState('');
-
- const onChangeFn = (e) => {
- const { value } = e.target;
- const data = {
- formId: String(id),
- chosenField: '',
- chosenValue: value
- }
- setValue(value);
- storeSet.main.addFlowData(data);
- }
-
- useEffect(() => {
- const edge = head(flowEdges.filter(o => o.target === String(id)));
- if (edge) {
- const sourceForm = edge.source;
- const sourceFormData = head(flowData.filter(o => String(o.formId) === sourceForm));
- const flowForms = storeGet.main.flowForms();
- const form = head(flowForms.filter(o => String(o.id) === String(sourceForm)));
-
- if (form && sourceFormData) {
- const { chosenField } = sourceFormData;
- const field = head(form.content.filter(o => o.id === chosenField));
- if (field) {
- const options = head(field.settings.filter(o => o.name === 'options'));
- if (options) {
- setOptions(options.value);
- }
- }
- }
- }
-
- const flowDataForm = head(flowData.filter(o => String(o.formId) === String(id)));
-
- if (flowDataForm) {
- setValue(flowDataForm.chosenValue);
- }
- }, [flowEdges, flowData]);
-
- return (
-
-
-
- {options && !isEmpty(options)
- ? : null}
-
-
- );
-}
-
-export default NodeIntermediateForm;
\ No newline at end of file
diff --git a/src/components/FlowBuilder/index.js b/src/components/FlowBuilder/index.js
deleted file mode 100644
index 3bf66de..0000000
--- a/src/components/FlowBuilder/index.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import {
- ReactFlow,
- Background
-} from '@xyflow/react';
-import { isEmpty } from 'ramda';
-
-import '@xyflow/react/dist/style.css';
-
-// store
-import { useStore, storeSet } from '../../store';
-
-// nodes
-import NodeInitialForm from './components/NodeInitialForm';
-import NodeIntermediateForm from './components/NodeIntermediateForm';
-
-const nodeTypes = {
- initialForm: NodeInitialForm,
- intermediateForm: NodeIntermediateForm
-};
-
-const FlowBuilder = ({ initialForm = 0, finalForm = 0, mainField = '' }) => {
- const flowForms = useStore().main.flowForms();
- const [nodes, setNodes] = useState([]);
- const [edges, setEdges] = useState([]);
-
- const range = (start, stop, step) => {
- return Array.from(
- { length: (stop - start) / step + 1 },
- (_, i) => start + i * step
- );
- }
-
- useEffect(() => {
- if (
- (flowForms.length === 2 && initialForm) ||
- (flowForms.length > 2 && initialForm && finalForm)
- ) {
- const total = (flowForms.length - 2) * (200 - 90);
- let coordinates = range(total * -1, total, 200);
-
- const initialNodes = flowForms.map(o => {
- const formId = String(o.id);
- let obj;
-
- if (formId === String(initialForm)) {
- obj = {
- id: formId,
- type: 'initialForm',
- data: { label: o.label, id: formId },
- position: { x: 0, y: 0 },
- }
- } else if (formId === String(finalForm)) {
- obj = {
- id: formId,
- type: 'output',
- data: { label: o.label, id: formId },
- position: { x: 0, y: flowForms.length === 2 ? 150 : 300 },
- }
- } else {
- const x = coordinates.splice(0, 1);
- obj = {
- id: formId,
- type: 'intermediateForm',
- data: { label: o.label, id: formId },
- position: { x, y: 150 },
- }
- }
- return obj
- });
-
- let edges = [];
- // eslint-disable-next-line
- flowForms.map(o => {
- const formId = String(o.id);
-
- if (formId !== String(initialForm) && formId !== String(finalForm)) {
- edges.push({
- id: `${initialForm}->${formId}`,
- source: String(initialForm),
- target: formId,
- type: 'smoothstep'
- });
- }
- if (formId !== String(initialForm) && formId !== String(finalForm) && String(finalForm) !== '0') {
- edges.push({
- id: `${formId}->${finalForm}`,
- source: formId,
- target: String(finalForm),
- type: 'smoothstep'
- });
- }
- });
-
- if (flowForms.length === 2 && initialForm && finalForm) {
- edges.push({
- id: `${initialForm}->${finalForm}`,
- source: String(initialForm),
- target: String(finalForm),
- type: 'smoothstep'
- });
- }
-
- setNodes(initialNodes);
- setEdges(edges);
- storeSet.main.flowEdges(edges);
- } else {
- setNodes([]);
- setEdges([]);
- }
- }, [initialForm, finalForm, flowForms, mainField]);
-
- return (
- !isEmpty(nodes) && !isEmpty(edges)
- ?
-
-
-
-
- : null
- );
-}
-
-export default FlowBuilder;
\ No newline at end of file
diff --git a/src/components/FormField/components/PasswordField/index.js b/src/components/FormField/components/PasswordField/index.js
new file mode 100644
index 0000000..f214f9c
--- /dev/null
+++ b/src/components/FormField/components/PasswordField/index.js
@@ -0,0 +1,54 @@
+import React from 'react';
+import { classNames } from 'primereact/utils';
+import { Controller } from 'react-hook-form';
+import { Password } from 'primereact/password';
+
+const PasswordField = ({
+ fieldName,
+ label,
+ control,
+ errors,
+ defaultValue,
+ config = {},
+ infoText = null,
+ inputgroup = false,
+ icon = null,
+ placeholder = '',
+ disabled = false,
+ onBlurFn = () => {
+ }
+ }) => {
+ const input = (
+
+ )}/>
+ return (
+ <>
+
+ {inputgroup
+ ?
+
+ {icon}
+
+ {input}
+
+ : input}
+ {infoText ? {infoText} : null}
+ >)
+}
+
+export default PasswordField;
\ No newline at end of file
diff --git a/src/components/FormField/index.js b/src/components/FormField/index.js
index bde12fb..c1559a7 100644
--- a/src/components/FormField/index.js
+++ b/src/components/FormField/index.js
@@ -16,6 +16,7 @@ import Wysiwyg from './components/Wysiwyg';
import Checkboxes from './components/Checkboxes';
import Fileupload from './components/Fileupload';
import Table from './components/Table';
+import PasswordField from './components/PasswordField';
const FormField = (props) => {
const fields = {
@@ -31,7 +32,8 @@ const FormField = (props) => {
radio: Radio,
wysiwyg: Wysiwyg,
checkboxes: Checkboxes,
- table: Table
+ table: Table,
+ password: PasswordField
}
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
diff --git a/src/configData.js b/src/configData.js
index ba5d649..5d3e7b8 100644
--- a/src/configData.js
+++ b/src/configData.js
@@ -19,6 +19,7 @@ const dynamicDataForTextinput = [
{ label: 'ragione sociale', value: 'company.companyName' },
{ label: 'partita IVA', value: 'company.vatNumber' },
{ label: 'codice fiscale azienda', value: 'company.codiceFiscale' },
+ { label: 'codice ateco', value: 'company.codiceAteco' },
{ label: 'indirizzo', value: 'company.address' },
{ label: 'numero di telefono azienda', value: 'company.phoneNumber' },
{ label: 'città', value: 'company.city' },
diff --git a/src/layouts/DefaultLayout/components/AppSidebar/index.js b/src/layouts/DefaultLayout/components/AppSidebar/index.js
index 37aa0eb..5c81b8f 100644
--- a/src/layouts/DefaultLayout/components/AppSidebar/index.js
+++ b/src/layouts/DefaultLayout/components/AppSidebar/index.js
@@ -64,11 +64,25 @@ const AppSidebar = () => {
},
{
label: __('Archivio domande', 'gepafin'),
- icon: 'pi pi-file',
+ icon: 'pi pi-briefcase',
href: '/domande',
id: 7,
enable: intersection(permissions, ['APPLY_CALLS']).length
},
+ {
+ label: __('Archivio domande', 'gepafin'),
+ icon: 'pi pi-briefcase',
+ href: '/domande-archivio',
+ id: 5,
+ enable: intersection(permissions, ['VIEW_USERS', 'MANAGE_USERS']).length
+ },
+ {
+ label: __('Archivio domande', 'gepafin'),
+ icon: 'pi pi-briefcase',
+ href: '/domande-archivio',
+ id: 6,
+ enable: intersection(permissions, ['EVALUATE_APPLICATIONS']).length
+ },
{
label: __('Soccorso istruttorio', 'gepafin'),
icon: ,
diff --git a/src/pages/BandoApplication/index.js b/src/pages/BandoApplication/index.js
index 6a33db6..d6d324b 100644
--- a/src/pages/BandoApplication/index.js
+++ b/src/pages/BandoApplication/index.js
@@ -312,7 +312,8 @@ const BandoApplication = () => {
dynamicData = Object.keys(company).reduce((acc, cur) => {
if ([
'companyName', 'vatNumber', 'codiceFiscale', 'address', 'phoneNumber',
- 'city', 'province', 'cap', 'country', 'pec', 'email', 'contactName', 'contactEmail'
+ 'city', 'province', 'cap', 'country', 'pec', 'email', 'contactName', 'contactEmail',
+ 'codiceAteco'
].includes(cur)) {
acc.company[cur] = company[cur];
}
diff --git a/src/pages/BandoFlowEdit/index.js b/src/pages/BandoFlowEdit/index.js
index e6b210d..af64d22 100644
--- a/src/pages/BandoFlowEdit/index.js
+++ b/src/pages/BandoFlowEdit/index.js
@@ -1,13 +1,14 @@
import React, { useEffect, useState, useCallback, useRef } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
-import { isEmpty, head } from 'ramda';
+import { isEmpty, head, pathOr } from 'ramda';
// store
-import { storeGet, storeSet, useStore } from '../../store';
+import { storeSet } from '../../store';
// api
import FormsService from '../../service/forms-service';
+import FlowService from '../../service/flow-service';
// tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
@@ -15,27 +16,33 @@ import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
// components
import { Button } from 'primereact/button';
import { Dropdown } from 'primereact/dropdown';
-import FlowBuilder from '../../components/FlowBuilder';
import { Messages } from 'primereact/messages';
-import FlowService from '../../service/flow-service';
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
import { Toast } from 'primereact/toast';
const BandoFlowEdit = () => {
const { id } = useParams();
const navigate = useNavigate();
- const forms = useStore().main.flowForms();
- const flowData = useStore().main.flowData();
- const flowEdges = useStore().main.flowEdges();
+
+ const [flowStructure, setFlowStructure] = useState({
+ initialForm: 0,
+ finalForm: 0,
+ flowData: [],
+ flowEdges: [],
+ chosenField: ''
+ });
+
+ const [forms, setForms] = useState([]);
const [formOptions, setFormOptions] = useState([]);
- const [initialForm, setInitialForm] = useState(0);
- const [mainFieldOptions, setMainFieldOptions] = useState([]);
- const [mainField, setMainField] = useState('');
+ const [chosenMainFieldOptions, setChosenMainFieldOptions] = useState([]);
+ //const [chosenMainField, setChosenMainField] = useState('');
+ const [mainFieldSuboptions, setMainFieldSubOptions] = useState([]);
const [bandoStatus, setBandoStatus] = useState('');
- const [isFlowAllowed, setIsFlowAllowed] = useState(false);
- const [finalForm, setFinalForm] = useState(0);
+ const [isFlowAllowed, setIsFlowAllowed] = useState(true);
const flowMsgs = useRef(null);
const toast = useRef(null);
+ const itemRefs = useRef({});
+ const itemContainerRef = useRef(null);
const getBandoId = () => {
const parsed = parseInt(id)
@@ -56,7 +63,8 @@ const BandoFlowEdit = () => {
defaultFocus: 'reject',
acceptClassName: 'p-button-danger',
accept: doDelete,
- reject: () => {}
+ reject: () => {
+ }
});
};
@@ -64,46 +72,120 @@ const BandoFlowEdit = () => {
if (flowMsgs.current) {
flowMsgs.current.clear();
}
- storeSet.main.flowData([]);
- storeSet.main.flowEdges([]);
- setInitialForm(0);
- setMainFieldOptions([]);
- setMainField('');
+
+ setFlowStructure({
+ initialForm: 0,
+ finalForm: 0,
+ flowData: [],
+ flowEdges: [],
+ chosenField: ''
+ })
+
setIsFlowAllowed(false);
- setFinalForm(0);
+ setChosenMainFieldOptions([]);
}
- const updateInitialForm = (value) => {
- setInitialForm(value);
- if (forms.length === 2) {
- const finalForm = head(forms.filter(o => o.id !== value));
- if (finalForm) {
- setFinalForm(finalForm.id);
+ const updateInitialForm = useCallback((value) => {
+ const finalFormObj = head(forms.filter(o => o.id !== value));
+
+ if (forms.length === 2 && finalFormObj) {
+ setFlowStructure({
+ ...flowStructure,
+ initialForm: value,
+ finalForm: finalFormObj.id
+ });
+ } else {
+ setFlowStructure({
+ ...flowStructure,
+ initialForm: value
+ });
+ }
+ }, [flowStructure])
+
+ const updateFinalForm = useCallback((value) => {
+ const filtered = flowStructure.flowData.filter(o => o.formId === flowStructure.initialForm);
+ const flowEdges = buildFlowEdges(flowStructure.initialForm, value);
+
+ setFlowStructure({
+ ...flowStructure,
+ flowEdges,
+ flowData: filtered,
+ finalForm: value
+ });
+ }, [flowStructure]);
+
+ const updateChosenField = useCallback((value) => {
+ setFlowStructure({
+ ...flowStructure,
+ chosenField: value
+ });
+ }, [flowStructure]);
+
+ const addFlowData = useCallback((data) => {
+ const initial = flowStructure.flowData;
+ const exists = initial ? initial.filter(o => parseInt(o.formId) === parseInt(data.formId)) : [];
+ let final = [];
+
+ if (exists.length) {
+ final = initial.map(o => parseInt(o.formId) === parseInt(data.formId) ? data : o);
+ } else {
+ final = [...initial, data];
+ }
+
+ setFlowStructure({
+ ...flowStructure,
+ flowData: final
+ });
+ }, [flowStructure]);
+
+ const updateItermediateForm = (value, formId) => {
+ const isUsed = flowStructure.flowData.map(o => o.chosenValue).filter(v => !isEmpty(v)).includes(value);
+ if (!isUsed) {
+ const data = {
+ formId: parseInt(formId),
+ chosenField: '',
+ chosenValue: value
}
+ addFlowData(data);
}
}
+ const displayChosenOptionValue = (id) => {
+ const suboptionId = pathOr('', ['chosenValue'], head(flowStructure.flowData.filter(f => parseInt(f.formId) === parseInt(id))));
+ return pathOr('', ['label'], head(mainFieldSuboptions.filter(o => o.name === suboptionId)));
+ }
+
+ const disabledOptionForIntermediateForm = (opt) => {
+ return flowStructure.flowData.map(o => o.chosenValue).filter(v => !isEmpty(v)).includes(opt.name);
+ }
+
const shoudDisableSaving = useCallback(() => {
+ const nonEmptyFlowItems = flowStructure.flowData.filter(o => isEmpty(o.chosenField)).filter(o => !isEmpty(o.chosenValue));
+
+ /*if (flowForms.length > 2) {
+ console.log('disable BTN:', nonEmptyFlowItems.length !== flowForms.length - 2, isEmpty(flowEdges), 'PUBLISH' === bandoStatus,
+ isEmpty(initialForm), isEmpty(finalForm));
+ } else {
+ console.log('disable BTN:', nonEmptyFlowItems.length !== 1, isEmpty(flowEdges), 'PUBLISH' === bandoStatus,
+ isEmpty(initialForm), isEmpty(finalForm));
+ }*/
+
return forms.length > 2
- ? isEmpty(flowData) || isEmpty(flowEdges) || isEmpty(initialForm) || isEmpty(finalForm)
- || flowData.length < forms.length - 1 || 'PUBLISH' === bandoStatus
- : isEmpty(flowEdges) || isEmpty(initialForm) || 'PUBLISH' === bandoStatus;
- }, [flowData, flowEdges]);
+ ? nonEmptyFlowItems.length !== forms.length - 2 || isEmpty(flowStructure.flowEdges) || 'PUBLISH' === bandoStatus
+ || isEmpty(flowStructure.initialForm) || isEmpty(flowStructure.finalForm)
+ : nonEmptyFlowItems.length !== 1 || isEmpty(flowStructure.flowEdges) || 'PUBLISH' === bandoStatus
+ || isEmpty(flowStructure.initialForm) || isEmpty(flowStructure.finalForm);
+ }, [flowStructure, forms]);
const doSave = () => {
storeSet.main.setAsyncRequest();
const bandoId = getBandoId();
- const body = {
- initialForm,
- finalForm,
- flowData,
- flowEdges
- };
+
if (flowMsgs.current) {
flowMsgs.current.clear();
}
- FlowService.createFlow(bandoId, body, getFlowCreateCallback, errGetFlowCreateCallback);
+ FlowService.createFlow(bandoId, flowStructure, getFlowCreateCallback, errGetFlowCreateCallback);
}
const getFlowCreateCallback = (data) => {
@@ -126,12 +208,13 @@ const BandoFlowEdit = () => {
const getFormsCallback = (data) => {
if (data.status === 'SUCCESS') {
+ setForms(data.data);
const formOptions = data.data.map(o => ({ label: o.label, value: o.id }))
- storeSet.main.flowForms(data.data);
- setFormOptions([{label: '', value: ''}, ...formOptions]);
+ setFormOptions([{ label: '', value: '' }, ...formOptions]);
const bandoId = getBandoId();
+
storeSet.main.setAsyncRequest();
- FlowService.getFlow(bandoId, getFlowCallback, errGetFlowCallback);
+ FlowService.getFlow(bandoId, (resp) => getFlowCallback(resp, data.data), errGetFlowCallback);
}
storeSet.main.unsetAsyncRequest();
}
@@ -141,21 +224,42 @@ const BandoFlowEdit = () => {
storeSet.main.unsetAsyncRequest();
}
- const getFlowCallback = (data) => {
+ const getFlowCallback = (data, forms) => {
if (data.status === 'SUCCESS' && data.data) {
- storeSet.main.flowData(data.data.flowData);
- storeSet.main.flowEdges(data.data.flowEdges);
- setInitialForm(data.data.initialForm);
- setFinalForm(data.data.finalForm);
- setBandoStatus(data.data.callStatus);
const chosenFieldItem = head(data.data.flowData.filter(o => !isEmpty(o.chosenField)));
- if (chosenFieldItem) {
- setMainField(chosenFieldItem.chosenField);
- }
- const flowDataItem = head(data.data.flowData.filter(o => !isEmpty(o.chosenField)));
+ setBandoStatus(data.data.callStatus);
- if (flowDataItem) {
- setMainField(flowDataItem.chosenField);
+ if (chosenFieldItem) {
+ setFlowStructure({
+ initialForm: data.data.initialForm,
+ finalForm: data.data.finalForm,
+ flowData: data.data.flowData,
+ flowEdges: data.data.flowEdges,
+ chosenField: chosenFieldItem.chosenField
+ });
+ const form = head(forms.filter(o => o.id === data.data.initialForm));
+ const relevantFields = form
+ ? form.content
+ .filter(o => ['radio', 'select'].includes(o.name))
+ .map(o => {
+ const label = head(o.settings.filter(o => o.name === 'label'));
+ return { value: o.id, label: label ? label.value : o.label };
+ })
+ : [];
+ setChosenMainFieldOptions(relevantFields);
+ const field = form ? head(form.content.filter(o => o.id === chosenFieldItem.chosenField)) : null;
+ if (field) {
+ const options = head(field.settings.filter(o => o.name === 'options'));
+ setMainFieldSubOptions(options.value);
+ }
+ } else {
+ setFlowStructure({
+ initialForm: data.data.initialForm,
+ finalForm: data.data.finalForm,
+ flowData: data.data.flowData,
+ flowEdges: data.data.flowEdges,
+ chosenField: ''
+ });
}
}
storeSet.main.unsetAsyncRequest();
@@ -166,71 +270,48 @@ const BandoFlowEdit = () => {
storeSet.main.unsetAsyncRequest();
}
- useEffect(() => {
- const flowForms = storeGet.main.flowForms();
- const form = head(flowForms.filter(o => String(o.id) === String(initialForm)))
- const field = form ? head(form.content.filter(o => o.id === mainField)) : null;
- let options = [];
+ const setItemRef = (id, element) => {
+ itemRefs.current[id] = element;
+ };
- if (field) {
- options = head(field.settings.filter(o => o.name === 'options'));
- }
+ const buildFlowEdges = (initialForm, finalForm) => {
+ let edges = [];
- if (field && options.value && options.value.length === flowForms.length - 2) {
- setIsFlowAllowed(true);
- const data = {
- formId: String(initialForm),
- chosenField: mainField,
- chosenValue: ''
- }
- storeSet.main.addFlowData(data);
- } else {
- setIsFlowAllowed(false);
- let msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzioni.';
+ if (!isEmpty(initialForm) && !isEmpty(finalForm)) {
+ // eslint-disable-next-line
+ forms.map(o => {
+ const formId = String(o.id);
- if (flowForms.length - 2 === 1) {
- msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzione.';
- }
+ if (formId !== String(initialForm) && formId !== String(finalForm)) {
+ edges.push({
+ id: `${initialForm}->${formId}`,
+ source: String(initialForm),
+ target: formId,
+ type: 'smoothstep'
+ });
+ }
+ if (formId !== String(initialForm) && formId !== String(finalForm) && String(finalForm) !== '0') {
+ edges.push({
+ id: `${formId}->${finalForm}`,
+ source: formId,
+ target: String(finalForm),
+ type: 'smoothstep'
+ });
+ }
+ });
- if (flowMsgs.current && !isEmpty(mainField)) {
- flowMsgs.current.clear();
- flowMsgs.current.show([
- {
- id: '1',
- sticky: true, severity: 'error', summary: '',
- detail: sprintf(
- __(msg, 'gepafin'),
- flowForms.length - 2
- ),
- closable: false
- }
- ]);
+ if (forms.length === 2 && initialForm && finalForm) {
+ edges.push({
+ id: `${initialForm}->${finalForm}`,
+ source: String(initialForm),
+ target: String(finalForm),
+ type: 'smoothstep'
+ });
}
}
- }, [mainField]);
- useEffect(() => {
- setMainField('');
- setMainFieldOptions([]);
- const flowForms = storeGet.main.flowForms();
- const form = head(flowForms.filter(o => String(o.id) === String(initialForm)))
- const relevantFields = form
- ? form.content
- .filter(o => ['radio', 'select'].includes(o.name))
- .map(o => {
- const label = head(o.settings.filter(o => o.name === 'label'));
- return { value: o.id, label: label ? label.value : o.label };
- })
- : [];
- setMainFieldOptions([
- {label: isEmpty(relevantFields) ? __('Nessun scelta', 'gepafin') : '', value: ''},
- ...relevantFields]
- );
-
- if (flowForms.length === 2) {
- setIsFlowAllowed(true)
- }
- }, [initialForm]);
+ return edges;
+ };
useEffect(() => {
const bandoId = getBandoId();
@@ -251,23 +332,98 @@ const BandoFlowEdit = () => {
]);
} else {
flowMsgs.current.clear();
+ if (itemContainerRef.current) {
+ itemContainerRef.current.dispatchEvent(new Event('scroll'));
+ }
}
}, [forms]);
useEffect(() => {
- const chosenFieldItem = head(flowData.filter(o => !isEmpty(o.chosenField)));
- if (chosenFieldItem) {
- setMainField(chosenFieldItem.chosenField);
- }
- }, [flowData])
+ const initialForm = flowStructure.initialForm;
+ const finalForm = flowStructure.finalForm;
+ const chosenField = flowStructure.chosenField;
- useEffect(() => {
- return () => {
- storeSet.main.flowForms([]);
- storeSet.main.flowData([]);
- storeSet.main.flowEdges([]);
+ if (!isEmpty(initialForm) && !isEmpty(finalForm)) {
+ const form = head(forms.filter(o => String(o.id) === String(initialForm)))
+ const relevantFields = form
+ ? form.content
+ .filter(o => ['radio', 'select'].includes(o.name))
+ .map(o => {
+ const label = head(o.settings.filter(o => o.name === 'label'));
+ return { value: o.id, label: label ? label.value : o.label };
+ })
+ : [];
+ setChosenMainFieldOptions([
+ { label: isEmpty(relevantFields) ? __('Nessun scelta', 'gepafin') : '', value: '' },
+ ...relevantFields]
+ );
+
+ if (forms.length === 2) {
+ setIsFlowAllowed(true);
+ }
+
+ //const flowEdges = buildFlowEdges(initialForm, finalForm);
+
+ if (!isEmpty(chosenField)) {
+ const field = form ? head(form.content.filter(o => o.id === chosenField)) : null;
+ let options = [];
+
+ if (field) {
+ options = head(field.settings.filter(o => o.name === 'options'));
+ }
+
+ if (field && options.value && options.value.length === forms.length - 2) {
+ setIsFlowAllowed(true);
+ const suboptions = [
+ { label: __('Nessun scelta', 'gepafin'), name: '' },
+ ...options.value
+ ]
+
+ setMainFieldSubOptions(suboptions);
+
+ const data = {
+ formId: parseInt(initialForm),
+ chosenField: chosenField,
+ chosenValue: ''
+ }
+
+ addFlowData(data);
+
+ if (flowMsgs.current && !isEmpty(chosenField)) {
+ flowMsgs.current.clear();
+ }
+ } else {
+ setIsFlowAllowed(false);
+
+ let msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzioni.';
+
+ if (forms.length - 2 === 1) {
+ msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzioni.';
+ }
+
+ if (flowMsgs.current && !isEmpty(chosenField)) {
+ flowMsgs.current.clear();
+ flowMsgs.current.show([
+ {
+ id: '1',
+ sticky: true, severity: 'error', summary: '',
+ detail: sprintf(
+ __(msg, 'gepafin'),
+ forms.length - 2
+ ),
+ closable: false
+ }
+ ]);
+ }
+ }
+ }
}
- }, []);
+ }, [flowStructure.initialForm, flowStructure.finalForm, flowStructure.chosenField]);
+
+ const { initialForm = 0, finalForm = 0, flowData = [], chosenField = '' } = flowStructure;
+ const initialFormData = head(forms.filter(o => o.id === initialForm));
+ const finalFormData = head(forms.filter(o => o.id === finalForm));
+ const levelForms = forms.filter(o => o.id !== initialForm && o.id !== finalForm);
return (
@@ -296,29 +452,29 @@ const BandoFlowEdit = () => {
placeholder={__('Scegli il form', 'gepafin')}/>
- {forms.length > 2 && initialForm && mainFieldOptions
+ {forms.length > 2 && initialForm && chosenMainFieldOptions
?
-
+
setMainField(e.value)}
+ value={chosenField}
+ onChange={(e) => updateChosenField(e.value)}
optionDisabled={(opt) => isEmpty(opt.value)}
- options={mainFieldOptions}
+ options={chosenMainFieldOptions}
optionLabel="label"
optionValue="value"
placeholder={__('Scegli il campo', 'gepafin')}/>
: null}
- {(forms.length > 2 && mainField && isFlowAllowed) || (forms.length === 2 && isFlowAllowed)
+ {(forms.length > 2 && chosenField && isFlowAllowed) || (forms.length === 2 && isFlowAllowed)
?
setFinalForm(e.value)}
+ onChange={(e) => updateFinalForm(e.value)}
optionDisabled={(opt) => initialForm === opt.value || isEmpty(opt.value)}
options={formOptions}
optionLabel="label"
@@ -343,11 +499,67 @@ const BandoFlowEdit = () => {
- {forms.length >= 2 && isFlowAllowed
- ? : null}
+
+ {forms.length >= 2 && initialForm && finalForm && isFlowAllowed
+ ?
+
+
+
initialForm ? setItemRef(initialForm, el) : null}>
+
+
+
+
+
+
+ {levelForms.length && initialForm && finalForm
+ ?
+ {levelForms.map((o, i) =>
setItemRef(o.id, el)}
+ className="flowContainer__flowItem levelForms">
+
+
+
+ {mainFieldSuboptions && !isEmpty(mainFieldSuboptions)
+ ? 'PUBLISH' !== bandoStatus
+ ? f.formId === parseInt(o.id))))}
+ onChange={(e) => updateItermediateForm(e.value, o.id)}
+ options={mainFieldSuboptions}
+ optionDisabled={disabledOptionForIntermediateForm}
+ optionLabel="label"
+ optionValue="name"
+ placeholder={__('Scegli il valore', 'gepafin')}/>
+ :
+
+ : null}
+
+
+
)}
+ {levelForms.length > 1
+ ? <>
+
+
+ > : null}
+
: null}
+
+ {forms.length >= 2 && initialForm && finalForm
+ ?
+
finalForm ? setItemRef(finalForm, el) : null}>
+
+
+
+
+
+ : null}
+
+
: null}
diff --git a/src/pages/Dashboard/index.js b/src/pages/Dashboard/index.js
index 71334b0..4bb003e 100644
--- a/src/pages/Dashboard/index.js
+++ b/src/pages/Dashboard/index.js
@@ -4,33 +4,31 @@ import { useNavigate } from 'react-router-dom';
import { pathOr } from 'ramda';
import NumberFlow from '@number-flow/react';
-// store
-//import { storeSet } from '../../store';
-
// api
import DashboardService from '../../service/dashboard-service';
// components
import LatestBandiTable from './components/LatestBandiTable';
-//import LatestUsersActivityTable from './components/LatestUsersActivityTable';
import { Button } from 'primereact/button';
-//import MyEvaluationsTable from '../DashboardPreInstructor/components/PreInstructorDomandeTable';
import AllDomandeTable from '../Domande/components/AllDomandeTable';
import DraftApplicationsTable from './components/DraftApplicationsTable';
+import ChartDomandePerBando from '../../components/ChartDomandePerBando';
+import ChartStatoDomande from '../../components/ChartStatoDomande';
const Dashboard = () => {
const navigate = useNavigate();
const [mainStats, setMainStats] = useState({});
+ const [chartStats, setChartStats] = useState({});
const onGoToCreateNewBando = () => {
navigate('/bandi/new');
}
- /*const onGoToUsers = () => {
- console.log('onGoToUsers')
+ const onGoToUsers = () => {
+ navigate('/utenti');
}
- const onGoToStats = () => {
+ /*const onGoToStats = () => {
console.log('onGoToStats')
}
@@ -45,16 +43,18 @@ const Dashboard = () => {
const getStats = (data) => {
if (data.status === 'SUCCESS') {
setMainStats(data.data.widget1);
+ setChartStats(data.data.widgetBars);
}
}
- const errGetStats = () => {}
+ const errGetStats = () => {
+ }
useEffect(() => {
DashboardService.getAdminStats(getStats, errGetStats);
}, []);
- return(
+ return (
{__('Dashboard', 'gepafin')}
@@ -147,20 +147,36 @@ const Dashboard = () => {
+ {chartStats.applicationPerCall
+ ?
+
{__('Statistiche di sistema', 'gepafin')}
+
+
+
+
+
: null}
+
+
+
{__('Azioni rapide', 'gepafin')}
+
+
- {/*
-
diff --git a/src/pages/DomandaEditPreInstructor/components/ArchiveDocument/index.js b/src/pages/DomandaEditPreInstructor/components/ArchiveDocument/index.js
index 5a1bb66..0660dba 100644
--- a/src/pages/DomandaEditPreInstructor/components/ArchiveDocument/index.js
+++ b/src/pages/DomandaEditPreInstructor/components/ArchiveDocument/index.js
@@ -83,7 +83,7 @@ const ArchiveDocument = ({ applicationId, ndg = '', fileId = 0, docAttachmentId
}
}
}
-
+
AppointmentService.archiveDocument(applicationId, fileId, submitData, submitCallback, errSubmitCallback)
}
}
diff --git a/src/pages/DomandeArchive/components/AllDomandeArchiveTable/index.js b/src/pages/DomandeArchive/components/AllDomandeArchiveTable/index.js
new file mode 100644
index 0000000..3b0e13a
--- /dev/null
+++ b/src/pages/DomandeArchive/components/AllDomandeArchiveTable/index.js
@@ -0,0 +1,182 @@
+import React, { useState, useEffect } from 'react';
+import { __ } from '@wordpress/i18n';
+import { is, uniq } from 'ramda';
+import { Link, useLocation } from 'react-router-dom';
+
+// api
+import ApplicationService from '../../../../service/application-service';
+
+// tools
+import getBandoLabel from '../../../../helpers/getBandoLabel';
+import getBandoSeverity from '../../../../helpers/getBandoSeverity';
+
+// translation
+import translationStrings from '../../../../translationStringsForComponents';
+
+// components
+import { FilterMatchMode, FilterOperator } from 'primereact/api';
+import { DataTable } from 'primereact/datatable';
+import { Column } from 'primereact/column';
+import { Button } from 'primereact/button';
+import { Calendar } from 'primereact/calendar';
+import ProperBandoLabel from '../../../../components/ProperBandoLabel';
+import { Dropdown } from 'primereact/dropdown';
+import { Tag } from 'primereact/tag';
+
+
+const AllDomandeArchiveTable = ({ updaterString = '' }) => {
+ const [items, setItems] = useState(null);
+ const [filters, setFilters] = useState(null);
+ const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
+ const [statuses, setStatuses] = useState([]);
+ const location = useLocation();
+
+ useEffect(() => {
+ setLocalAsyncRequest(true);
+ ApplicationService.getApplications(getCallback, errGetCallbacks, [
+ ['statuses', ['APPROVED', 'REJECTED']]
+ ]);
+ }, [updaterString]);
+
+ const getCallback = (data) => {
+ if (data.status === 'SUCCESS') {
+ setItems(getFormattedData(data.data));
+ setStatuses(uniq(data.data.map(o => o.status)))
+ initFilters();
+ }
+ setLocalAsyncRequest(false);
+ }
+
+ const errGetCallbacks = (data) => {
+ setLocalAsyncRequest(false);
+ }
+
+ const getFormattedData = (data) => {
+ return data.map((d) => {
+ d.callEndDate = is(String, d.callEndDate) ? new Date(d.callEndDate) : (d.callEndDate ? d.callEndDate : '');
+ d.modifiedDate = is(String, d.modifiedDate) ? new Date(d.modifiedDate) : (d.modifiedDate ? d.modifiedDate : '');
+ d.submissionDate = is(String, d.submissionDate) ? new Date(d.submissionDate) : (d.submissionDate ? d.submissionDate : '');
+ return d;
+ });
+ };
+
+ const formatDate = (value) => {
+ return value.toLocaleDateString('it-IT', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric'
+ });
+ };
+
+ const clearFilter = () => {
+ initFilters();
+ };
+
+ const initFilters = () => {
+ setFilters({
+ global: { value: null, matchMode: FilterMatchMode.CONTAINS },
+ callTitle: {
+ operator: FilterOperator.AND,
+ constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
+ },
+ companyName: {
+ operator: FilterOperator.AND,
+ constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
+ },
+ submissionDate: {
+ operator: FilterOperator.AND,
+ constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
+ },
+ callEndDate: {
+ operator: FilterOperator.AND,
+ constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
+ },
+ status: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
+ });
+ };
+
+ const renderHeader = () => {
+ return (
+
+
+ );
+ };
+
+ const dateAppliedBodyTemplate = (rowData) => {
+ return formatDate(rowData.submissionDate);
+ };
+
+ const statusFilterTemplate = (options) => {
+ return
options.filterCallback(e.value, options.index)}
+ itemTemplate={statusItemTemplate} placeholder={translationStrings.selectOneLabel} className="p-column-filter"
+ showClear/>;
+ };
+
+ const dateFilterTemplate = (options) => {
+ return options.filterCallback(e.value, options.index)}
+ dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
+ };
+
+ const statusBodyTemplate = (rowData) => {
+ return ;
+ };
+
+ const statusItemTemplate = (option) => {
+ return ;
+ };
+
+ const actionsBodyTemplate = (rowData) => {
+ return
+
+
+
+
+ }
+
+ const header = renderHeader();
+
+ return (
+
+ setFilters(e.filters)}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default AllDomandeArchiveTable;
diff --git a/src/pages/DomandeArchive/index.js b/src/pages/DomandeArchive/index.js
new file mode 100644
index 0000000..c6e7885
--- /dev/null
+++ b/src/pages/DomandeArchive/index.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { __ } from '@wordpress/i18n';
+
+// components
+import AllDomandeArchiveTable from './components/AllDomandeArchiveTable';
+
+const Domande = () => {
+
+ return (
+
+
+
{__('Archivio domande', 'gepafin')}
+
+
+
+
+
+
{__('Domande pubblicate', 'gepafin')}
+
+
+
+ )
+}
+
+export default Domande;
\ No newline at end of file
diff --git a/src/pages/ResetPassword/index.js b/src/pages/ResetPassword/index.js
index 05a1438..a43724f 100644
--- a/src/pages/ResetPassword/index.js
+++ b/src/pages/ResetPassword/index.js
@@ -1,9 +1,9 @@
-import React, { useRef, useState, useEffect } from 'react';
+import React, { useRef, useState, useEffect, useMemo } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { useForm } from 'react-hook-form';
import { classNames } from 'primereact/utils';
-import { isEmpty } from 'ramda';
-import { useNavigate } from 'react-router-dom';
+import { isEmpty, isNil } from 'ramda';
+import { useNavigate, useSearchParams } from 'react-router-dom';
// tools
import AuthenticationService from '../../service/authentication-service';
@@ -24,7 +24,9 @@ const ResetPassword = () => {
const token = useStore().main.token();
const [loading, setLoading] = useState(false);
const [resetPassToken, setResetPassToken] = useState('');
+ const [resetPassEmail, setResetPassEmail] = useState('');
const errorMsgs = useRef(null);
+ let [searchParams] = useSearchParams();
const {
control,
handleSubmit,
@@ -47,12 +49,33 @@ const ResetPassword = () => {
}
if (request.token && !isEmpty(request.token)) {
- AuthenticationService.resetPassword(request, getCallback, errCallback);
+ AuthenticationService.resetPassword(request, getCallbackReset, errCallback);
} else {
AuthenticationService.forgotPassword(request, getCallback, errCallback);
}
};
+ const getCallbackReset = (data) => {
+ if (data.status === 'SUCCESS') {
+ errorMsgs.current.show([
+ {
+ sticky: true, severity: 'success', summary: '',
+ detail: data.message,
+ closable: true
+ }
+ ]);
+ } else {
+ errorMsgs.current.show([
+ {
+ sticky: true, severity: 'error', summary: '',
+ detail: data.message,
+ closable: true
+ }
+ ]);
+ }
+ setLoading(false);
+ }
+
const getCallback = (data) => {
if (data.status === 'SUCCESS') {
setResetPassToken(data.data)
@@ -87,9 +110,18 @@ const ResetPassword = () => {
}, [token]);
useEffect(() => {
- setValue('token', resetPassToken);
+ console.log(resetPassToken, resetPassEmail);
reset();
- }, [resetPassToken])
+ setValue('token', resetPassToken);
+ setValue('email', resetPassEmail);
+ }, [resetPassToken, resetPassEmail]);
+
+ useEffect(() => {
+ const token = searchParams.get('token');
+ const email = searchParams.get('email');
+ setResetPassToken(token);
+ setResetPassEmail(email);
+ }, [searchParams]);
return (
@@ -113,7 +145,7 @@ const ResetPassword = () => {
placeholder="sample@example.com"
/>
- {!isEmpty(resetPassToken)
+ {resetPassToken && !isEmpty(resetPassToken)
?
{
})}
/> : null}
- {!isEmpty(resetPassToken)
+ {resetPassToken && !isEmpty(resetPassToken)
?
{
}}
/> : null}
- {!isEmpty(resetPassToken)
+ {resetPassToken && !isEmpty(resetPassToken)
? {
@@ -124,6 +125,18 @@ const routes = ({ role, chosenCompanyId }) => {
{'ROLE_PRE_INSTRUCTOR' === role ? : null}
{'ROLE_INSTRUCTOR_MANAGER' === role ? : null}
}/>
+
+ {'ROLE_SUPER_ADMIN' === role ? : null}
+ {'ROLE_BENEFICIARY' === role ? : null}
+ {'ROLE_PRE_INSTRUCTOR' === role ? : null}
+ {'ROLE_INSTRUCTOR_MANAGER' === role ? : null}
+ }/>
+
+ {'ROLE_SUPER_ADMIN' === role ? : null}
+ {'ROLE_BENEFICIARY' === role ? : null}
+ {'ROLE_PRE_INSTRUCTOR' === role ? : null}
+ {'ROLE_INSTRUCTOR_MANAGER' === role ? : null}
+ }/>
{'ROLE_SUPER_ADMIN' === role ? : null}
{'ROLE_BENEFICIARY' === role ? : null}
diff --git a/src/store/actions.js b/src/store/actions.js
index baeb35e..448daa6 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -43,16 +43,5 @@ export const actionsBeta = (set, get, api) => ({
const newElements = newFields.toSpliced(hoverIndex, 0, prevFields[dragIndex]);
set.formElements(newElements);
}
- },
- addFlowData: (data) => {
- const initial = get.flowData();
- const exists = initial ? initial.filter(o => parseInt(o.formId) === parseInt(data.formId)) : [];
-
- if (exists.length) {
- const newData = initial.map(o => parseInt(o.formId) === parseInt(data.formId) ? data : o);
- set.flowData(newData);
- } else {
- set.flowData([...initial, data]);
- }
}
});