Merge pull request #23 from Kitzanos/master-sync/20-12-2024

Master sync/20 12 2024 TAsks Amendments and Evaluation
This commit is contained in:
Rinaldo
2024-12-20 07:46:43 +01:00
committed by GitHub
28 changed files with 754 additions and 204 deletions

View File

@@ -5,3 +5,4 @@ REACT_APP_LOGO_FILENAME=gepafin-logo.svg
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
REACT_APP_EVALUATION_FLOW_ID=1 REACT_APP_EVALUATION_FLOW_ID=1
REACT_APP_LOCAL_DEVELOPMENT=0

View File

@@ -5,3 +5,4 @@ REACT_APP_LOGO_FILENAME=gepafin-logo.svg
REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico REACT_APP_FAVICON_FILENAME=gepafin-favicon.ico
REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs REACT_APP_HUB_ID=p4lk3bcx1RStqTaIVVbXs
REACT_APP_EVALUATION_FLOW_ID=1 REACT_APP_EVALUATION_FLOW_ID=1
REACT_APP_LOCAL_DEVELOPMENT=0

View File

@@ -43,6 +43,10 @@
margin-left: 10px; margin-left: 10px;
text-transform: uppercase; text-transform: uppercase;
} }
span.companyName {
margin: 0;
}
} }
.appPage__spacer { .appPage__spacer {
@@ -258,7 +262,7 @@
.appPageSection__checklist { .appPageSection__checklist {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1.2rem;
div { div {
display: flex; display: flex;

View File

@@ -0,0 +1,45 @@
.fieldsRepeater {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10px;
width: 100%;
}
.fieldsRepeater form {
display: contents;
}
.fieldsRepeater__panel {
width: 100%;
}
.fieldsRepeater__heading {
align-items: center;
display: flex;
justify-content: space-between;
> span {
width: 100%;
height: 100%;
&:hover {
cursor: pointer;
color: var(--menuitem-active-background);
}
}
&[data-hide="true"] {
display: none;
}
}
.fieldsRepeater__fields {
&[data-hide="true"] {
display: none;
}
}
.fieldsRepeater__addNew {
}

View File

@@ -44,3 +44,4 @@
@import "./components/error404.scss"; @import "./components/error404.scss";
@import "./components/myTable.scss"; @import "./components/myTable.scss";
@import "./components/evaluation.scss"; @import "./components/evaluation.scss";
@import "./components/fieldsRepeater.scss";

View File

@@ -1,7 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import * as Sentry from '@sentry/browser'; import logMsgWithSentry from '../../helpers/logMsgWithSentry';
const LOCAL_DEVELOPMENT = process.env.REACT_APP_LOCAL_DEVELOPMENT;
class ErrorBoundary extends Component { class ErrorBoundary extends Component {
constructor(props) { constructor(props) {
@@ -14,16 +12,8 @@ class ErrorBoundary extends Component {
static getDerivedStateFromError(error) { static getDerivedStateFromError(error) {
try { try {
if (LOCAL_DEVELOPMENT !== '1') { logMsgWithSentry('', 0, {}, error);
Sentry.init({
dsn: "https://e7b2134f7d816f663bb83e51b106a694@o4508381921738752.ingest.de.sentry.io/4508381935501392",
environment: process.env.NODE_ENV || "development"
});
Sentry.captureException(error);
}
} catch (err) { } catch (err) {
console.log('err')
console.log(err); console.log(err);
} }
return { builderError: true }; return { builderError: true };

View File

@@ -38,7 +38,8 @@ const Fileupload = ({
source = 'application', source = 'application',
disabled = false, disabled = false,
saveFormCallback = () => { saveFormCallback = () => {
} },
deleteOnBackend = true
}) => { }) => {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const [stateFieldData, setStateFieldData] = useState([]); const [stateFieldData, setStateFieldData] = useState([]);
@@ -97,7 +98,7 @@ const Fileupload = ({
}; };
const onTemplateRemove = (file) => { const onTemplateRemove = (file) => {
if (file.id) { if (file.id && deleteOnBackend) {
FileUploadService.deleteFile( FileUploadService.deleteFile(
{}, {},
(data) => deleteCallback(data, file.id), (data) => deleteCallback(data, file.id),
@@ -108,6 +109,11 @@ const Fileupload = ({
const files = inputRef.current.getFiles() const files = inputRef.current.getFiles()
const newFiles = files.filter(o => o.lastModified !== file.lastModified && o.name !== file.name); const newFiles = files.filter(o => o.lastModified !== file.lastModified && o.name !== file.name);
inputRef.current.setFiles(newFiles); inputRef.current.setFiles(newFiles);
if (file.id) {
const uploadedFiles = inputRef.current.getUploadedFiles();
const newUploadedFiles = uploadedFiles.filter(o => o.id !== file.id);
inputRef.current.setUploadedFiles(newUploadedFiles);
}
} }
} }

View File

@@ -67,87 +67,87 @@ export const protocolType = [
export const classificationType = [ export const classificationType = [
{ {
'idClassificazione': 101, 'idClassificazione': 1,
'name': 'BILANCIO', 'name': 'BILANCIO',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 102, 'idClassificazione': 2,
'name': 'DICHHIARAZIONE DEI REDDITI', 'name': 'DICHHIARAZIONE DEI REDDITI',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 103, 'idClassificazione': 3,
'name': 'SITUAZIONE CONTABILE', 'name': 'SITUAZIONE CONTABILE',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 104, 'idClassificazione': 4,
'name': 'PROSPETTO CONTO ECONOMICO', 'name': 'PROSPETTO CONTO ECONOMICO',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 105, 'idClassificazione': 5,
'name': 'CENTRALE DEI RISCHI', 'name': 'CENTRALE DEI RISCHI',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 106, 'idClassificazione': 6,
'name': 'RELAZIONE AZIENDALE ILLUSTRATIVA (MOD R1C, R1I, R1R, R1R A SECONDO DEI ', 'name': 'RELAZIONE AZIENDALE ILLUSTRATIVA (MOD R1C, R1I, R1R, R1R A SECONDO DEI ',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 107, 'idClassificazione': 7,
'name': 'DOCUMENTO IDENTITA\'', 'name': 'DOCUMENTO IDENTITA\'',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 108, 'idClassificazione': 8,
'name': 'MODELLO SP1', 'name': 'MODELLO SP1',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 109, 'idClassificazione': 9,
'name': 'PRIVACY', 'name': 'PRIVACY',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 110, 'idClassificazione': 10,
'name': 'DOCUMENTAZIONE CHE ATTESTA POSSIBILITA\' DI RILASCIARE GAA FAVORE', 'name': 'DOCUMENTAZIONE CHE ATTESTA POSSIBILITA\' DI RILASCIARE GAA FAVORE',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 111, 'idClassificazione': 11,
'name': 'MODELLO AR1 D.LG 231/2007', 'name': 'MODELLO AR1 D.LG 231/2007',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 112, 'idClassificazione': 12,
'name': 'DOCUMENTO IDENTITA\' FIRMATORIO DICHHIARAZIONE SOSTITUTIVA', 'name': 'DOCUMENTO IDENTITA\' FIRMATORIO DICHHIARAZIONE SOSTITUTIVA',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 113, 'idClassificazione': 13,
'name': 'PRIVACY FIRMATARIO DICHHIARAZIONE SOSTITUTIVA', 'name': 'PRIVACY FIRMATARIO DICHHIARAZIONE SOSTITUTIVA',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 114, 'idClassificazione': 14,
'name': 'NULLAOSTA ANTIMAFIA', 'name': 'NULLAOSTA ANTIMAFIA',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 201, 'idClassificazione': 1,
'name': 'LETTERA ESITO DELIBERA', 'name': 'LETTERA ESITO DELIBERA',
'idTipoprotocollo': 2 'idTipoprotocollo': 2
}, },
{ {
'idClassificazione': 202, 'idClassificazione': 2,
'name': 'LETTERA DI GARANZIA', 'name': 'LETTERA DI GARANZIA',
'idTipoprotocollo': 1 'idTipoprotocollo': 1
}, },
{ {
'idClassificazione': 203, 'idClassificazione': 3,
'name': 'GENERICO', 'name': 'GENERICO',
'idTipoprotocollo': 3 'idTipoprotocollo': 3
} }

View File

@@ -0,0 +1,31 @@
import * as Sentry from '@sentry/browser';
const LOCAL_DEVELOPMENT = process.env.REACT_APP_LOCAL_DEVELOPMENT;
const logMsgWithSentry = (endpoint = '', status = 0, resp = {}, error = null) => {
try {
if (LOCAL_DEVELOPMENT !== '1') {
Sentry.init({
dsn: 'https://e7b2134f7d816f663bb83e51b106a694@o4508381921738752.ingest.de.sentry.io/4508381935501392',
environment: process.env.NODE_ENV || 'development'
});
if (!error) {
const newError = new Error(`Status ${status}`);
Sentry.captureException(`Error in endpoint: ${endpoint}`, {
level: 'error',
extra: {
originalError: newError,
details: resp
}
});
} else {
Sentry.captureException(error);
}
}
} catch (err) {
console.log(err);
}
}
export default logMsgWithSentry;

View File

@@ -1,6 +1,10 @@
import React from 'react'; import React from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { head } from 'ramda';
// store
import { storeGet, useStore } from '../../store';
// components // components
import MyLatestSubmissionsTable from '../DashboardBeneficiario/components/MyLatestSubmissionsTable'; import MyLatestSubmissionsTable from '../DashboardBeneficiario/components/MyLatestSubmissionsTable';
@@ -9,6 +13,9 @@ import ErrorBoundary from '../../components/ErrorBoundary';
const Applications = () => { const Applications = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const chosenCompanyId = useStore().main.chosenCompanyId();
const companies = useStore().main.companies();
const company = head(companies.filter(o => o.id === chosenCompanyId));
const gotToBandiDisponibili = () => { const gotToBandiDisponibili = () => {
navigate('/bandi') navigate('/bandi')
@@ -18,6 +25,7 @@ const Applications = () => {
<div className="appPage"> <div className="appPage">
<div className="appPage__pageHeader"> <div className="appPage__pageHeader">
<h1>{__('Domande in Lavorazione', 'gepafin')}</h1> <h1>{__('Domande in Lavorazione', 'gepafin')}</h1>
{company ? <span className="companyName">{company.companyName}</span> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { isEmpty } from 'ramda'; import { head, isEmpty } from 'ramda';
// store // store
import { useStore } from '../../store'; import { useStore } from '../../store';
@@ -12,11 +12,14 @@ import ErrorBoundary from '../../components/ErrorBoundary';
const BandiBeneficiario = () => { const BandiBeneficiario = () => {
const chosenCompanyId = useStore().main.chosenCompanyId(); const chosenCompanyId = useStore().main.chosenCompanyId();
const companies = useStore().main.companies();
const company = head(companies.filter(o => o.id === chosenCompanyId));
return ( return (
<div className="appPage"> <div className="appPage">
<div className="appPage__pageHeader"> <div className="appPage__pageHeader">
<h1>{__('Bandi disponibili', 'gepafin')}</h1> <h1>{__('Bandi disponibili', 'gepafin')}</h1>
{company ? <span className="companyName">{company.companyName}</span> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { isEmpty } from 'ramda'; import { head, isEmpty } from 'ramda';
// store // store
import { useStore } from '../../store'; import { useStore } from '../../store';
@@ -11,11 +11,14 @@ import AllBandiAccordion from '../BandiBeneficiario/components/AllBandiAccordion
const BandiPreferredBeneficiario = () => { const BandiPreferredBeneficiario = () => {
const chosenCompanyId = useStore().main.chosenCompanyId(); const chosenCompanyId = useStore().main.chosenCompanyId();
const companies = useStore().main.companies();
const company = head(companies.filter(o => o.id === chosenCompanyId));
return ( return (
<div className="appPage"> <div className="appPage">
<div className="appPage__pageHeader"> <div className="appPage__pageHeader">
<h1>{__('Bandi osservati', 'gepafin')}</h1> <h1>{__('Bandi osservati', 'gepafin')}</h1>
{company ? <span className="companyName">{company.companyName}</span> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>

View File

@@ -266,7 +266,6 @@ const BandoApplicationPreview = () => {
{activeStep < totalSteps {activeStep < totalSteps
? <Button ? <Button
type="button" type="button"
disabled={'SUBMIT' === applicationStatus}
onClick={goForward} onClick={goForward}
label={__('Vai avanti', 'gepafin')} label={__('Vai avanti', 'gepafin')}
icon="pi pi-arrow-right" icon="pi pi-arrow-right"

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { wrap } from 'object-path-immutable'; import { wrap } from 'object-path-immutable';
import { findIndex, propEq } from 'ramda'; import { pathOr } from 'ramda';
// components // components
import { InputText } from 'primereact/inputtext'; import { InputText } from 'primereact/inputtext';
@@ -14,7 +14,8 @@ import uniqid from '../../../../../../helpers/uniqid';
const ElementSettingTableColumns = ({ const ElementSettingTableColumns = ({
value, value,
name, name,
setDataFn setDataFn,
bandoStatus
}) => { }) => {
const [stateFieldData, setStateFieldData] = useState([]); const [stateFieldData, setStateFieldData] = useState([]);
const [rowsData, setRowsData] = useState([]); const [rowsData, setRowsData] = useState([]);
@@ -28,18 +29,19 @@ const ElementSettingTableColumns = ({
setStateFieldData([...stateFieldData, { name: uniqid('o'), label: '', predefined: false }]); setStateFieldData([...stateFieldData, { name: uniqid('o'), label: '', predefined: false }]);
} }
const addNewRow = (index) => { const addNewRow = () => {
const newStateFieldData = wrap(stateFieldData) const obj = stateFieldData
.insert([index, 'rows'], { label: '' }, stateFieldData[index].rows.length) .filter(o => o.predefined)
.value(); .reduce((acc, cur) => {
setStateFieldData(newStateFieldData); acc[cur.name] = ''
return acc;
}, {});
setRowsData([...rowsData, obj]);
} }
const removeRow = (index, indexK) => { const removeRow = (index) => {
const newStateFieldData = wrap(stateFieldData) const newRowsData = wrap(rowsData).del([index]).value();
.del([index, 'rows', indexK]) setRowsData(newRowsData);
.value();
setStateFieldData(newStateFieldData);
} }
const onInputChange = (e, index) => { const onInputChange = (e, index) => {
@@ -53,24 +55,31 @@ const ElementSettingTableColumns = ({
setStateFieldData(newData); setStateFieldData(newData);
} }
const onSubInputChange = (e, index, indexK) => { const onSubInputChange = (e, name, index) => {
const { value } = e.target; const { value } = e.target;
const newStateFieldData = wrap(stateFieldData) const newRowsData = wrap(rowsData).set([index, name], value).value();
.set([index, 'rows', indexK, 'label'], value) setRowsData(newRowsData);
.value();
setStateFieldData(newStateFieldData);
} }
const setChecked = (value, index) => { const setChecked = (value, index) => {
let name = '';
const newData = stateFieldData.map((o, i) => { const newData = stateFieldData.map((o, i) => {
if (i === index) { if (i === index) {
o.predefined = value; o.predefined = value;
if (value === false) { name = o.name;
o.rows = [];
}
} }
return o; return o;
}) });
let newRowsData = [];
if (value === false) {
newRowsData = rowsData.map(o => wrap(o).set([name], '').value());
} else {
newRowsData = rowsData.map(o => wrap(o).set([name], '').value());
}
setRowsData(newRowsData);
setStateFieldData(newData); setStateFieldData(newData);
} }
@@ -79,23 +88,31 @@ const ElementSettingTableColumns = ({
<InputText value={item.label} onInput={(e) => onInputChange(e, i)}/> <InputText value={item.label} onInput={(e) => onInputChange(e, i)}/>
<div className="flex-1"> <div className="flex-1">
<span>{__('Predefinito?', 'gepafin')}</span> <span>{__('Predefinito?', 'gepafin')}</span>
<InputSwitch checked={item.predefined} onChange={(e) => setChecked(e.value, i)}/> <InputSwitch
checked={item.predefined}
disabled={bandoStatus === 'PUBLISH'}
onChange={(e) => setChecked(e.value, i)}/>
</div> </div>
</> </>
} }
const properSubField = (item, i, k) => { const properSubField = (item, i, name) => {
return <InputText value={item.label} onInput={(e) => onSubInputChange(e, i, k)}/> return <InputText value={item[name]} onInput={(e) => onSubInputChange(e, name, i)}/>
} }
useEffect(() => { useEffect(() => {
const storeFieldData = value ?? []; const stateFieldData = pathOr([], ['stateFieldData'], value);
setStateFieldData(storeFieldData); setStateFieldData(stateFieldData);
const rowsData = pathOr([], ['rowsData'], value);
setRowsData(rowsData);
}, []); }, []);
useEffect(() => { useEffect(() => {
setDataFn(name, [...stateFieldData]); setDataFn(name, {
}, [stateFieldData]); stateFieldData,
rowsData
});
}, [stateFieldData, rowsData]);
stateFieldData.filter(o => o.predefined) stateFieldData.filter(o => o.predefined)
@@ -105,10 +122,10 @@ const ElementSettingTableColumns = ({
{stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem"> {stateFieldData.map((o, i) => <div key={i} className="formElementSettings__repeaterItem">
<div className="p-inputgroup flex-1"> <div className="p-inputgroup flex-1">
{properField(o, i)} {properField(o, i)}
<Button icon="pi pi-times" className="p-button-danger" onClick={() => removeItem(i)}/> <Button icon="pi pi-times" disabled={bandoStatus === 'PUBLISH'} className="p-button-danger" onClick={() => removeItem(i)}/>
</div> </div>
</div>)} </div>)}
<Button type="button" outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/> <Button type="button" disabled={bandoStatus === 'PUBLISH'} outlined label={__('Aggiungi', 'gepafin')} onClick={addNewItem}/>
</div> </div>
{stateFieldData {stateFieldData
.filter(o => o.predefined) .filter(o => o.predefined)
@@ -116,19 +133,22 @@ const ElementSettingTableColumns = ({
<div className="formElementSettings__repeater formElementSettings__subRepeater"> <div className="formElementSettings__repeater formElementSettings__subRepeater">
<label>{__('Righe per colonna:', 'gepafin')} <strong>{o.label}</strong></label> <label>{__('Righe per colonna:', 'gepafin')} <strong>{o.label}</strong></label>
<div className="formElementSettings__repeater"> <div className="formElementSettings__repeater">
{o.rows.map((c, k) => { {rowsData.map((c, k) => {
const properIndex = findIndex(propEq(o.name, 'name'))(stateFieldData);
return <div key={k} className="formElementSettings__repeaterItem"> return <div key={k} className="formElementSettings__repeaterItem">
<div className="p-inputgroup flex-1"> <div className="p-inputgroup flex-1">
{properSubField(c, properIndex, k)} {properSubField(c, k, o.name)}
<Button icon="pi pi-times" className="p-button-danger" <Button icon="pi pi-times"
onClick={() => removeRow(properIndex, k)}/> disabled={bandoStatus === 'PUBLISH'}
className="p-button-danger"
onClick={() => removeRow(k)}/>
</div> </div>
</div> </div>
})} })}
<Button type="button" outlined <Button type="button"
outlined
disabled={bandoStatus === 'PUBLISH'}
label={__('Aggiungi una riga', 'gepafin')} label={__('Aggiungi una riga', 'gepafin')}
onClick={() => addNewRow(findIndex(propEq(o.name, 'name'))(stateFieldData))}/> onClick={addNewRow}/>
</div> </div>
</div> </div>
</div>)} </div>)}

View File

@@ -21,6 +21,7 @@ const DashboardBeneficiario = () => {
const [mainStats, setMainStats] = useState({}); const [mainStats, setMainStats] = useState({});
const companies = useStore().main.companies(); const companies = useStore().main.companies();
const chosenCompanyId = useStore().main.chosenCompanyId(); const chosenCompanyId = useStore().main.chosenCompanyId();
const company = head(companies.filter(o => o.id === chosenCompanyId));
const goToAllSubmissions = () => { const goToAllSubmissions = () => {
navigate('/bandi'); navigate('/bandi');
@@ -51,6 +52,7 @@ const DashboardBeneficiario = () => {
<div className="appPage"> <div className="appPage">
<div className="appPage__pageHeader"> <div className="appPage__pageHeader">
<h1>{__('Dashboard', 'gepafin')}</h1> <h1>{__('Dashboard', 'gepafin')}</h1>
{company ? <span className="companyName">{company.companyName}</span> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>

View File

@@ -25,6 +25,9 @@ import { Toast } from 'primereact/toast';
import { Dialog } from 'primereact/dialog'; import { Dialog } from 'primereact/dialog';
import FormField from '../../components/FormField'; import FormField from '../../components/FormField';
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications'; import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
import RepeaterFields from '../DomandaEditPreInstructor/components/RepeaterFields';
import { wrap } from 'object-path-immutable';
import { Editor } from 'primereact/editor';
const DomandaBeneficiario = () => { const DomandaBeneficiario = () => {
const isAsyncRequest = useStore().main.isAsyncRequest(); const isAsyncRequest = useStore().main.isAsyncRequest();
@@ -67,12 +70,16 @@ const DomandaBeneficiario = () => {
if (data.data.length) { if (data.data.length) {
const amendmentObj = data.data[0]; const amendmentObj = data.data[0];
setData(getFormattedData(amendmentObj)); setData(getFormattedData(amendmentObj));
const formDataInitial = amendmentObj.applicationFormFields.reduce((acc, cur) => { let formDataInitial = amendmentObj.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) { if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue; acc[cur.fieldId] = cur.fieldValue;
} }
return acc; return acc;
}, {}); }, {});
formDataInitial = {
...formDataInitial,
amendmentDocuments: amendmentObj.amendmentDocuments
}
setFormInitialData(formDataInitial); setFormInitialData(formDataInitial);
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} else { } else {
@@ -101,7 +108,7 @@ const DomandaBeneficiario = () => {
} }
const getFormattedData = (data) => { const getFormattedData = (data) => {
data.submissionDate = is(String, data.submissionDate) ? new Date(data.submissionDate) : (data.submissionDate ? data.submissionDate : ''); data.evaluationEndDate = is(String, data.evaluationEndDate) ? new Date(data.evaluationEndDate) : (data.evaluationEndDate ? data.evaluationEndDate : '');
data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : ''); data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : '');
data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : ''); data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : '');
return data; return data;
@@ -114,6 +121,7 @@ const DomandaBeneficiario = () => {
trigger(); trigger();
let formValues = klona(getValues()); let formValues = klona(getValues());
const newFormValues = Object.keys(formValues) const newFormValues = Object.keys(formValues)
.filter(v => v !== 'amendmentDocuments')
.reduce((acc, cur) => { .reduce((acc, cur) => {
let fieldVal = formValues[cur]; let fieldVal = formValues[cur];
@@ -126,9 +134,14 @@ const DomandaBeneficiario = () => {
}); });
return acc; return acc;
}, []); }, []);
const newAmendDocs = formValues.amendmentDocuments
? formValues.amendmentDocuments.map(o => o.id).join(',')
: '';
const submitData = { const submitData = {
applicationFormFields: newFormValues, applicationFormFields: newFormValues,
amendmentDocuments: newAmendDocs,
amendmentNotes: data.amendmentNotes
} }
const amendmentId = data.id; const amendmentId = data.id;
@@ -145,13 +158,17 @@ const DomandaBeneficiario = () => {
detail: data.message detail: data.message
}); });
} }
const newFormDataInitial = data.data.applicationFormFields.reduce((acc, cur) => { let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) { if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue; acc[cur.fieldId] = cur.fieldValue;
} }
return acc; return acc;
}, formInitialData); }, {});
setFormInitialData(newFormDataInitial); formDataInitial = {
...formDataInitial,
amendmentDocuments: data.data.amendmentDocuments
}
setFormInitialData(formDataInitial);
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
@@ -168,6 +185,31 @@ const DomandaBeneficiario = () => {
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const updateNewAmendmentData = (value, path) => {
const newData = wrap(data).set(path, value).value();
setData(newData);
}
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(() => { useEffect(() => {
if (formInitialData) { if (formInitialData) {
//reset(); //reset();
@@ -182,7 +224,7 @@ const DomandaBeneficiario = () => {
{data.id {data.id
? <h1> ? <h1>
{sprintf(__('Soccorso Istruttorio: richiesta integrazione documenti per domanda #%s', 'gepafin'), id)} {sprintf(__('Soccorso Istruttorio: richiesta integrazione documenti per domanda #%s', 'gepafin'), id)}
</h1> : null} </h1> : null}
{dataAppl.id {dataAppl.id
? <h1> ? <h1>
{sprintf(__('Dettagli: domanda #%s', 'gepafin'), dataAppl.id)} {sprintf(__('Dettagli: domanda #%s', 'gepafin'), dataAppl.id)}
@@ -239,7 +281,7 @@ const DomandaBeneficiario = () => {
{dataAppl.id {dataAppl.id
? <div className="appPageSection__withBorder columns"> ? <div className="appPageSection__withBorder columns">
<p className="appPageSection__pMeta"> <p className="appPageSection__pMeta">
<span>{__('ID domanda', 'gepafin')}</span> <span>{__('ID domanda', 'gepafin')}</span>
<span>{dataAppl.id}</span> <span>{dataAppl.id}</span>
</p> </p>
<p className="appPageSection__pMeta"> <p className="appPageSection__pMeta">
@@ -274,6 +316,12 @@ const DomandaBeneficiario = () => {
</div> </div>
</div> : null} </div> : null}
{data.id
? <div className="appPageSection">
<h2>{__('Comunicazioni', 'gepafin')}</h2>
<SoccorsoComunications amendmentId={data.id} soccorsoStatus={data.status}/>
</div> : null}
{data.id {data.id
? <div className="appPageSection"> ? <div className="appPageSection">
<h3>{__('Documenti Richiesti', 'gepafin')}</h3> <h3>{__('Documenti Richiesti', 'gepafin')}</h3>
@@ -294,42 +342,80 @@ const DomandaBeneficiario = () => {
defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []} defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []}
accept={[]} accept={[]}
source="AMENDMENT" source="AMENDMENT"
sourceId={data.applicationId} sourceId={data.id}
multiple={true} multiple={true}
/> />
}) : null} }) : null}
</form> </form>
{/*<ol className="appPageSection__list"> <ol className="appPageSection__list">
{data.formFields {data.formFields
? data.formFields.map((o, i) => <li key={o.fieldId} ? data.formFields.map((o, i) => <li key={o.fieldId}
style={{ flexDirection: 'row' }}> style={{ flexDirection: 'row' }}>
<span>{o.label}</span> <span>{o.label}</span>
</li>) : null} </li>) : null}
</ol>*/} </ol>
</div> : null} </div> : null}
{data.id {data.id
? <div className="appPageSection"> ? <div className="appPageSection">
<h2>{__('Comunicazioni', 'gepafin')}</h2> <h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<SoccorsoComunications amendmentId={data.id} soccorsoStatus={data.status}/> <div className="appPageSection">
</div> : null} <h3>{__('Notes', 'gepafin')}</h3>
<div style={{ marginBottom: '30px', width: '100%' }}>
<Editor
value={data.amendmentNotes}
readOnly={data.status === 'CLOSE'}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateNewAmendmentData(
e.htmlValue,
'amendmentNotes'
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
<FormField
type="fileupload"
disabled={data.status === 'CLOSE'}
setDataFn={setValue}
saveFormCallback={doUpdateAmendment}
fieldName="amendmentDocuments"
label={__('I file', 'gepafin')}
control={control}
register={register}
errors={errors}
defaultValue={formInitialData.amendmentDocuments ? formInitialData.amendmentDocuments : []}
accept={[]}
source="amendment"
sourceId={data.id}
multiple={true}
/>
</div>
</div> : null}
{data.id {data.id
? <div className="appPageSection__message warning"> ? <div className="appPageSection__message warning">
<i className="pi pi-exclamation-triangle"></i> <i className="pi pi-exclamation-triangle"></i>
<span className="summary">{__('Attenzione', 'gepafin')}</span> <span className="summary">{__('Attenzione', 'gepafin')}</span>
<span>{__('Inviare la documentazione richiesta completa delle integrazioni esclusivamente via PEC. In caso contarrio lintegrazione non può essere ritenuta valida.', 'gepafin')}</span> <span>{__('Inviare la documentazione richiesta completa delle integrazioni esclusivamente via PEC. In caso contarrio lintegrazione non può essere ritenuta valida.', 'gepafin')}</span>
</div> : null} </div> : null}
<div className="appPageSection"> <div className="appPageSection">
<div className="appPageSection__actions"> <div className="appPageSection__actions">
{data.id {data.id
? <Button ? <Button
type="button" type="button"
disabled={isAsyncRequest} disabled={isAsyncRequest}
onClick={() => setIsVisibleEmailDialog(true)} onClick={() => setIsVisibleEmailDialog(true)}
label={__('Invia documenti via PEC', 'gepafin')} label={__('Invia documenti via PEC', 'gepafin')}
icon="pi pi-envelope" iconPos="right"/> : null} icon="pi pi-envelope" iconPos="right"/> : null}
{data.id
? <Button
type="button"
disabled={isAsyncRequest}
onClick={doUpdateAmendment}
label={__('Salva', 'gepafin')}
icon="pi pi-save" iconPos="right"/> : null}
<Button <Button
type="button" type="button"
outlined outlined
@@ -345,7 +431,10 @@ const DomandaBeneficiario = () => {
header={__('Invia documenti via PEC', 'gepafin')} header={__('Invia documenti via PEC', 'gepafin')}
visible={isVisibleEmailDialog} visible={isVisibleEmailDialog}
style={{ width: '50vw' }} style={{ width: '50vw' }}
onHide={() => {if (!isVisibleEmailDialog) return; setIsVisibleEmailDialog(false); }}> onHide={() => {
if (!isVisibleEmailDialog) return;
setIsVisibleEmailDialog(false);
}}>
<p className="m-0"> <p className="m-0">
{data.callEmail} {data.callEmail}
</p> </p>

View File

@@ -1,8 +1,14 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { isEmpty } from 'ramda'; import { isEmpty, pathOr, isNil } from 'ramda';
import { wrap } from 'object-path-immutable'; import { wrap } from 'object-path-immutable';
// store
import AppointmentService from '../../../../service/appointment-service';
// tools
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
// components // components
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import { Dialog } from 'primereact/dialog'; import { Dialog } from 'primereact/dialog';
@@ -11,14 +17,11 @@ import { Dropdown } from 'primereact/dropdown';
import { classNames } from 'primereact/utils'; import { classNames } from 'primereact/utils';
import { InputSwitch } from 'primereact/inputswitch'; import { InputSwitch } from 'primereact/inputswitch';
import { InputText } from 'primereact/inputtext'; import { InputText } from 'primereact/inputtext';
import { classificationType, protocolType } from '../../../../configData';
import AppointmentService from '../../../../service/appointment-service';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import { storeSet } from '../../../../store';
import { Toast } from 'primereact/toast'; import { Toast } from 'primereact/toast';
const ArchiveDocument = ({ applicationId, ndg = '', fileId = 0 }) => { import { classificationType, protocolType } from '../../../../configData';
const ArchiveDocument = ({ applicationId, ndg = '', fileId = 0, docAttachmentId = null, updateFn = () => {} }) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [isVisibleDialog, setIsVisibleDialog] = useState(false); const [isVisibleDialog, setIsVisibleDialog] = useState(false);
const [modalData, setModalData] = useState({}); const [modalData, setModalData] = useState({});
@@ -87,19 +90,29 @@ const ArchiveDocument = ({ applicationId, ndg = '', fileId = 0 }) => {
const submitCallback = (data) => { const submitCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
console.log(data.data); if (toast.current && data.message) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
const documentAttachmentId = pathOr('fake_id', ['documentAttachmentId'], data.data);
updateFn(documentAttachmentId);
} }
setIsVisibleDialog(false);
setLoading(false); setLoading(false);
} }
const errSubmitCallback = (data) => { const errSubmitCallback = (data) => {
if (toast.current && data.message) { if (toast.current && data.message) {
toast.current.show({ toast.current.show({
severity: 'error', severity: data.status === 'SUCCESS' ? 'info' : 'error',
summary: '', summary: '',
detail: data.message detail: data.message
}); });
} }
setIsVisibleDialog(false);
set404FromErrorResponse(data); set404FromErrorResponse(data);
setLoading(false); setLoading(false);
} }
@@ -119,7 +132,7 @@ const ArchiveDocument = ({ applicationId, ndg = '', fileId = 0 }) => {
setTypes(protocolType.map(o => ({ value: o.id, label: o.name }))); setTypes(protocolType.map(o => ({ value: o.id, label: o.name })));
}, []); }, []);
return (!isEmpty(ndg) return (!isEmpty(ndg) && !isNil(ndg) && !docAttachmentId
? <> ? <>
<Toast ref={toast}/> <Toast ref={toast}/>
<Button icon="pi pi-file-export" <Button icon="pi pi-file-export"

View File

@@ -3,22 +3,35 @@ import { Button } from 'primereact/button';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { isNil } from 'ramda'; import { isNil } from 'ramda';
import ArchiveDocument from '../ArchiveDocument'; import ArchiveDocument from '../ArchiveDocument';
import renderHtmlContent from '../../../../helpers/renderHtmlContent';
import uniqid from '../../../../helpers/uniqid';
const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applicationId }) => { const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applicationId }) => {
return ( return (
<ol className="appPageSection__list"> <ol className="appPageSection__list">
{files.map((o, i) => <li key={o.id} className="appPageSection__listItem"> {files.map((o, i) => <li key={`${o.id}_${uniqid('f')}`} className="appPageSection__listItem">
<div className="appPageSection__listItemRow"> <div className="appPageSection__listItemRow">
<span>{o.label}</span> <div>{renderHtmlContent(o.label)}</div>
<div className="appPageSection__iconActions"> <div className="appPageSection__iconActions">
{o.fileDetail && o.fileDetail.length === 1 {o.fileDetail && o.fileDetail.length === 1
? <Button icon="pi pi-eye" rounded ? <>
<Button icon="pi pi-eye" rounded
onClick={() => { onClick={() => {
window.open(o.fileDetail[0].filePath, '_blank').focus() window.open(o.fileDetail[0].filePath, '_blank').focus()
}} }}
outlined severity="info" outlined severity="info"
aria-label={__('Mostra', 'gepafin')}/> : null} aria-label={__('Mostra', 'gepafin')}/>
<ArchiveDocument
ndg={ndg}
applicationId={applicationId}
fileId={o.fileDetail[0].id}
updateFn={(val) => updateFn(
val,
[name, i, 'fileDetail', 0, 'documentAttachmentId']
)}
docAttachmentId={o.fileDetail[0].documentAttachmentId}/>
</> : null}
<Button icon="pi pi-thumbs-up" rounded outlined <Button icon="pi pi-thumbs-up" rounded outlined
disabled={shouldDisableFieldFn(name)} disabled={shouldDisableFieldFn(name)}
severity={!isNil(o.valid) && o.valid ? 'success' : 'secondary'} severity={!isNil(o.valid) && o.valid ? 'success' : 'secondary'}
@@ -45,7 +58,7 @@ const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applica
flexDirection: 'column', flexDirection: 'column',
gap: '10px' gap: '10px'
}}> }}>
{o.fileDetail.map((k) => <li key={k.id} style={{ {o.fileDetail.map((k, ind) => <li key={k.id} style={{
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
@@ -53,7 +66,15 @@ const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applica
}}> }}>
<span>{k.name}</span> <span>{k.name}</span>
<div className="appPageSection__iconActions"> <div className="appPageSection__iconActions">
<ArchiveDocument ndg={ndg} applicationId={applicationId} fileId={k.id}/> <ArchiveDocument
ndg={ndg}
applicationId={applicationId}
fileId={k.id}
updateFn={(val) => updateFn(
val,
[name, i, 'fileDetail', ind, 'documentAttachmentId']
)}
docAttachmentId={k.documentAttachmentId}/>
<Button icon="pi pi-eye" rounded <Button icon="pi pi-eye" rounded
onClick={() => { onClick={() => {
window.open(k.filePath, '_blank').focus() window.open(k.filePath, '_blank').focus()

View File

@@ -0,0 +1,146 @@
import React, { useMemo, useState, useCallback } from 'react';
import { useForm, useFieldArray } from 'react-hook-form';
import { isEmpty, head } from 'ramda';
import { __ } from '@wordpress/i18n';
import { klona } from 'klona';
// tools
import uniqid from '../../../../helpers/uniqid';
// components
import FormField from '../../../../components/FormField';
import { Button } from 'primereact/button';
const RepeaterFields = ({
sourceId,
sourceName,
updateFn = () => {
},
updateCallbackFn = () => {
},
defaultValue = [],
}) => {
const [chosen, setChosen] = useState('');
const {
control,
handleSubmit,
formState: { errors },
setValue,
register,
trigger,
getValues,
watch
} = useForm({
defaultValues: useMemo(() => {
return {
items: defaultValue || []
};
}, [defaultValue]), mode: 'onChange'
});
const { fields, append, remove } = useFieldArray({
control,
name: 'items'
});
const watchFields = watch('items');
const onSubmit = () => {
}
const doUpdateAfterFileUploaded = () => {
const formData = getValues();
updateFn(formData.items);
updateCallbackFn(formData.items);
}
const addNew = () => {
const uid = uniqid('f');
const newItem = {
fieldId: uid,
nameValue: '',
fileValue: []
}
append(newItem);
setChosen(newItem.fieldId);
trigger();
};
const setNewChosen = useCallback((id) => {
const chosenObj = head(fields.filter(o => id === o.fieldId));
if (chosenObj) {
setChosen(chosen === id ? '' : id);
}
}, [fields, chosen]);
const removeItem = useCallback((index) => {
const chosenObj = klona(fields[index]);
remove(index);
if (chosen === chosenObj.fieldId) {
setChosen('');
}
const formData = getValues();
updateFn(formData.items);
updateCallbackFn(formData.items);
}, [fields, chosen]);
return (
<div className="fieldsRepeater">
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
{watchFields
? watchFields.map((o, index) => <div key={o.fieldId}
className="fieldsRepeater__panel p-panel p-component">
<div className="fieldsRepeater__heading p-panel p-panel-header">
<span onClick={() => setNewChosen(o.fieldId)}>{o.nameValue}</span>
<Button icon="pi pi-times"
outlined
severity="danger"
className="actionBtn"
type="button"
aria-label={__('Cancella', 'gepafin')}
onClick={() => removeItem(index)}/>
</div>
<div className="fieldsRepeater__fields p-panel-content" data-hide={chosen !== o.fieldId}>
<FormField
type="textinput"
fieldName={`items.${index}.nameValue`}
label={__('Titolo del file', 'gepafin')}
control={control}
errors={errors}
defaultValue={o.nameValue}
config={{ required: __('È obbligatorio', 'gepafin') }}
/>
<FormField
type="fileupload"
disabled={isEmpty(o.nameValue)}
setDataFn={setValue}
saveFormCallback={doUpdateAfterFileUploaded}
fieldName={`items.${index}.fileValue`}
label={__('File', 'gepafin')}
control={control}
register={register}
errors={errors}
defaultValue={o.fileValue ? o.fileValue : []}
accept={[]}
source={sourceName}
sourceId={sourceId}
multiple={false}
deleteOnBackend={false}
config={{ required: __('È obbligatorio', 'gepafin') }}
/>
</div>
</div>
) : null}
</form>
<Button
className="fieldsRepeater__addNew"
outlined
type="button"
disabled={watchFields && watchFields.filter(o => isEmpty(o.nameValue) || isEmpty(o.fileValue)).length > 0}
onClick={addNew}
label={__('Aggiungi nuovo file', 'gepafin')}
/>
</div>
)
}
export default RepeaterFields;

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef, useCallback } from 'react';
import { __, sprintf } from '@wordpress/i18n'; import { __, sprintf } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { is, isEmpty, isNil, sum, pathOr, head } from 'ramda'; import { is, isEmpty, isNil, sum, pathOr, head } from 'ramda';
@@ -11,6 +11,7 @@ import { storeSet, useStore } from '../../store';
// api // api
import ApplicationEvaluationService from '../../service/application-evaluation-service'; import ApplicationEvaluationService from '../../service/application-evaluation-service';
import AmendmentsService from '../../service/amendments-service'; import AmendmentsService from '../../service/amendments-service';
import AppointmentService from '../../service/appointment-service';
// tools // tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse'; import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
@@ -24,19 +25,18 @@ import { Tag } from 'primereact/tag';
import { Checkbox } from 'primereact/checkbox'; import { Checkbox } from 'primereact/checkbox';
import { Editor } from 'primereact/editor'; import { Editor } from 'primereact/editor';
import { InputNumber } from 'primereact/inputnumber'; import { InputNumber } from 'primereact/inputnumber';
import BlockingOverlay from '../../components/BlockingOverlay';
import { Toast } from 'primereact/toast'; import { Toast } from 'primereact/toast';
import HelpIcon from '../../icons/HelpIcon';
import { Dialog } from 'primereact/dialog'; import { Dialog } from 'primereact/dialog';
import ArchiveDocument from './components/ArchiveDocument'; import HelpIcon from '../../icons/HelpIcon';
import BlockingOverlay from '../../components/BlockingOverlay';
import { classNames } from 'primereact/utils'; import { classNames } from 'primereact/utils';
import { InputTextarea } from 'primereact/inputtextarea'; import { InputTextarea } from 'primereact/inputtextarea';
import { InputText } from 'primereact/inputtext'; import { InputText } from 'primereact/inputtext';
import DownloadApplicationArchive from './components/DownloadApplicationArchive'; import DownloadApplicationArchive from './components/DownloadApplicationArchive';
import DownloadCompanyDelegation from './components/DownloadCompanyDelegation'; import DownloadCompanyDelegation from './components/DownloadCompanyDelegation';
import DownloadSignedApplication from './components/DownloadSignedApplication'; import DownloadSignedApplication from './components/DownloadSignedApplication';
import AppointmentService from '../../service/appointment-service';
import ListOfFiles from './components/ListOfFiles'; import ListOfFiles from './components/ListOfFiles';
import RepeaterFields from './components/RepeaterFields';
const APP_EVALUATION_FLOW_ID = process.env.REACT_APP_EVALUATION_FLOW_ID; const APP_EVALUATION_FLOW_ID = process.env.REACT_APP_EVALUATION_FLOW_ID;
@@ -71,12 +71,24 @@ const DomandaEditPreInstructor = () => {
} }
const updateFlagsForSoccorso = (data) => { const updateFlagsForSoccorso = (data) => {
let nonRatedFilesLength = 0;
if (data.files) { if (data.files) {
const nonRatedFiles = data.files const nonRatedFiles = data.files
.map(el => el.valid) .map(el => el.valid)
.filter(v => isNil(v)); .filter(v => isNil(v));
setAllFilesRated(nonRatedFiles.length === 0); nonRatedFilesLength = nonRatedFiles.length;
} }
if (data.amendmentDetails) {
const nonRatedFiles = data.amendmentDetails
.map(el => el.valid)
.filter(v => isNil(v));
nonRatedFilesLength = nonRatedFiles.length;
}
setAllFilesRated(nonRatedFilesLength === 0);
if (data.checklist) { if (data.checklist) {
const checkedChecklistItems = data.checklist const checkedChecklistItems = data.checklist
.map(el => el.valid) .map(el => el.valid)
@@ -88,7 +100,7 @@ const DomandaEditPreInstructor = () => {
const doNewSoccorso = () => { const doNewSoccorso = () => {
if (connectedSoccorsoId !== 0) { if (connectedSoccorsoId !== 0) {
doSaveDraft(`/domande/${id}/soccorso/${connectedSoccorsoId}`) navigate(`/domande/${id}/soccorso/${connectedSoccorsoId}`);
} else { } else {
doSaveDraft(`/domande/${id}/aggiungi-soccorso/`) doSaveDraft(`/domande/${id}/aggiungi-soccorso/`)
} }
@@ -153,11 +165,17 @@ const DomandaEditPreInstructor = () => {
updateFlagsForSoccorso(newData); updateFlagsForSoccorso(newData);
} }
const doSaveDraft = (doRedirect = '') => { const doSaveDraft = useCallback((doRedirect = '') => {
const formData = { const formData = {
criteria: klona(data.criteria), criteria: klona(data.criteria),
checklist: klona(data.checklist), checklist: klona(data.checklist),
files: klona(data.files), files: klona(data.files),
evaluationDocument: klona(data.evaluationDocument.map(o => ({
...o,
fileValue: o.fileValue[0] ? o.fileValue[0].id : ''
})
)),
amendmentDetails: klona(data.amendmentDetails),
note: data.note note: data.note
} }
@@ -167,7 +185,7 @@ const DomandaEditPreInstructor = () => {
(data) => updateCallback(data, doRedirect), (data) => updateCallback(data, doRedirect),
errUpdateCallback errUpdateCallback
); );
} }, [data]);
const updateCallback = (data, doRedirect = '') => { const updateCallback = (data, doRedirect = '') => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
@@ -374,7 +392,13 @@ const DomandaEditPreInstructor = () => {
const getNdgCallback = (data) => { const getNdgCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
console.log('data', data.data); if (toast.current && data.message) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
@@ -382,7 +406,7 @@ const DomandaEditPreInstructor = () => {
const errGetNdgCallback = (data) => { const errGetNdgCallback = (data) => {
if (toast.current && data.message) { if (toast.current && data.message) {
toast.current.show({ toast.current.show({
severity: 'error', severity: data.status === 'SUCCESS' ? 'info' : 'error',
summary: '', summary: '',
detail: data.message detail: data.message
}); });
@@ -430,10 +454,47 @@ const DomandaEditPreInstructor = () => {
!isEmpty(appointmentData.title) && !isEmpty(appointmentData.text) && !isEmpty(appointmentData.amount) !isEmpty(appointmentData.title) && !isEmpty(appointmentData.text) && !isEmpty(appointmentData.amount)
&& !isEmpty(appointmentData.duration) && appointmentData.duration !== 0 && appointmentData.amount !== 0 && !isEmpty(appointmentData.duration) && appointmentData.duration !== 0 && appointmentData.amount !== 0
) { ) {
console.log(appointmentData); storeSet.main.setAsyncRequest();
const submitData = {
'importoBreveTermine': appointmentData.amount,
'durataMesiFinanziamento': appointmentData.duration,
'nota': {
'titolo': appointmentData.title,
'testo': appointmentData.text
}
}
AppointmentService.createAppointment(id, submitData, getAppointemntCallback, errGetAppointemntCallback);
} }
} }
const getAppointemntCallback = (data) => {
if (data.status === 'SUCCESS') {
if (toast.current && data.message) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
}
setIsVisibleAppointmentDialog(false);
storeSet.main.unsetAsyncRequest();
}
const errGetAppointemntCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: data.status === 'SUCCESS' ? 'info' : 'error',
summary: '',
detail: data.message
});
}
setIsVisibleAppointmentDialog(false);
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}
const doMakeAdmisible = () => { const doMakeAdmisible = () => {
// TODO // TODO
} }
@@ -538,11 +599,22 @@ const DomandaEditPreInstructor = () => {
</div> </div>
</div> </div>
<div className="appPageSection">
<h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<RepeaterFields
defaultValue={data.evaluationDocument ?? []}
updateFn={(data) => updateEvaluationValue(
data,
['evaluationDocument']
)}
sourceId={data.assignedApplicationId}
sourceName="evaluation"/>
</div>
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Checklist Valutazione', 'gepafin')}</h2> <h2>{__('Checklist Valutazione', 'gepafin')}</h2>
<div className="appPageSection columns"> <div className="appPageSection columns">
<div> <div>
<h3>{__('Lista', 'gepafin')}</h3> <h3>{__('Lista', 'gepafin')}</h3>
<div className="appPageSection__withBorder grey" style={{ marginBottom: '20px' }}> <div className="appPageSection__withBorder grey" style={{ marginBottom: '20px' }}>
<div className="appPageSection__checklist"> <div className="appPageSection__checklist">
@@ -588,6 +660,18 @@ const DomandaEditPreInstructor = () => {
</div> </div>
</div> </div>
{!isEmpty(data.amendmentDetails)
? <div className="appPageSection">
<h2>{__('Documenti di soccorso', 'gepafin')}</h2>
<ListOfFiles
files={data.amendmentDetails}
updateFn={updateEvaluationValue}
shouldDisableFieldFn={shouldDisableField}
name="amendmentDetails"
ndg={data.ndg}
applicationId={id}/>
</div> : null}
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Punteggi di valutazione', 'gepafin')}</h2> <h2>{__('Punteggi di valutazione', 'gepafin')}</h2>
{data.criteria {data.criteria
@@ -703,14 +787,14 @@ const DomandaEditPreInstructor = () => {
onClick={() => doSaveDraft()} onClick={() => doSaveDraft()}
label={__('Crea valutazione', 'gepafin')} label={__('Crea valutazione', 'gepafin')}
icon="pi pi-save" iconPos="right"/>} icon="pi pi-save" iconPos="right"/>}
{APP_EVALUATION_FLOW_ID === '1' && ['EVALUATION'].includes(data.applicationStatus) {/*{APP_EVALUATION_FLOW_ID === '1' && ['EVALUATION'].includes(data.applicationStatus)
? <Button ? <Button
type="button" type="button"
disabled={!data.id || !allFilesRated || !allChecksChecked} disabled={!data.id || !allFilesRated || !allChecksChecked}
onClick={doCheckNDG} onClick={doCheckNDG}
label={__('Controlla NDG', 'gepafin')} label={__('Controlla NDG', 'gepafin')}
/> : null} /> : null}*/}
{APP_EVALUATION_FLOW_ID === '1' && ['EVALUATION'].includes(data.applicationStatus) && data.ndg {APP_EVALUATION_FLOW_ID === '1' && ['NDG'].includes(data.applicationStatus) && data.ndg
? <Button ? <Button
type="button" type="button"
disabled={!data.id} disabled={!data.id}
@@ -732,12 +816,19 @@ const DomandaEditPreInstructor = () => {
onClick={initiateApproving} onClick={initiateApproving}
label={__('Approva Domanda', 'gepafin')} label={__('Approva Domanda', 'gepafin')}
icon="pi pi-check" iconPos="right"/> : null} icon="pi pi-check" iconPos="right"/> : null}
{data.id {/*{data.id
? <Button ? <Button
type="button" type="button"
disabled={APP_EVALUATION_FLOW_ID === '1' && !['ADMISSIBLE', 'APPOINTMENT'].includes(data.applicationStatus)} disabled={APP_EVALUATION_FLOW_ID === '1' && !['ADMISSIBLE', 'APPOINTMENT'].includes(data.applicationStatus)}
onClick={initiateRejecting} onClick={initiateRejecting}
label={__('Respingi Domanda', 'gepafin')} label={__('Respingi Domanda', 'gepafin')}
icon="pi pi-times" iconPos="right"/> : null}*/}
{data.id
? <Button
type="button"
disabled={APP_EVALUATION_FLOW_ID === '1' && !['EVALUATION', 'ADMISSIBLE', 'APPOINTMENT'].includes(data.applicationStatus)}
onClick={initiateRejecting}
label={__('Respingi Domanda', 'gepafin')}
icon="pi pi-times" iconPos="right"/> : null} icon="pi pi-times" iconPos="right"/> : null}
</div> </div>
</div> </div>

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { is, uniq } from 'ramda'; import { is, uniq } from 'ramda';
import { Link } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
// api // api
import ApplicationService from '../../../../service/application-service'; import ApplicationService from '../../../../service/application-service';
@@ -21,6 +21,7 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
const [filters, setFilters] = useState(null); const [filters, setFilters] = useState(null);
const [localAsyncRequest, setLocalAsyncRequest] = useState(false); const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
const [, setStatuses] = useState([]); const [, setStatuses] = useState([]);
const location = useLocation();
useEffect(() => { useEffect(() => {
setLocalAsyncRequest(true); setLocalAsyncRequest(true);
@@ -113,14 +114,15 @@ const AllDomandeTable = ({ openDialogFn, updaterString = '' }) => {
const actionsBodyTemplate = (rowData) => { const actionsBodyTemplate = (rowData) => {
return <div className="appPageSection__tableActions lessGap"> return <div className="appPageSection__tableActions lessGap">
{openDialogFn {openDialogFn && rowData.status === 'SUBMIT'
? <Button severity="info" ? <Button severity="info"
onClick={() => openDialogFn(rowData.id)} onClick={() => openDialogFn(rowData.id)}
label={__('Assegnare', 'gepafin')} label={__('Assegnare', 'gepafin')}
icon="pi pi-pencil" size="small" iconPos="right"/> icon="pi pi-pencil" size="small" iconPos="right"/>
: <Link to={'/domande'}> : location.pathname !== '/domande'
<Button severity="info" label={__('Gestire', 'gepafin')} size="small"/> ? <Link to={'/domande'}>
</Link>} <Button severity="info" label={__('Gestire', 'gepafin')} size="small"/>
</Link> : null}
<Link to={`/domande/${rowData.id}`}> <Link to={`/domande/${rowData.id}`}>
<Button severity="info" label={__('Anteprima', 'gepafin')} icon="pi pi-eye" size="small" <Button severity="info" label={__('Anteprima', 'gepafin')} icon="pi pi-eye" size="small"
iconPos="right"/> iconPos="right"/>

View File

@@ -65,7 +65,7 @@ const Domande = () => {
} }
const headerEditDialog = () => { const headerEditDialog = () => {
return <span>{__('Assign application', 'gepafin')}</span> return <span>{__('Assegni la domanda', 'gepafin')}</span>
} }
const hideEditDialog = () => { const hideEditDialog = () => {

View File

@@ -4,7 +4,7 @@ import { is, isEmpty, uniq } from 'ramda';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
// store // store
import { useStore } from '../../../../store'; import { useStore, storeGet } from '../../../../store';
// api // api
import ApplicationService from '../../../../service/application-service'; import ApplicationService from '../../../../service/application-service';
@@ -33,7 +33,7 @@ const BeneficiarioDomandeTable = () => {
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
if (!isEmpty(chosenCompanyId) && chosenCompanyId !== 0) { if (!isEmpty(chosenCompanyId) && chosenCompanyId !== 0 && !localAsyncRequest) {
setLocalAsyncRequest(true); setLocalAsyncRequest(true);
ApplicationService.getApplications(getApplCallback, errGetApplCallback, [ ApplicationService.getApplications(getApplCallback, errGetApplCallback, [
['companyId', chosenCompanyId], ['companyId', chosenCompanyId],

View File

@@ -1,14 +1,23 @@
import React from 'react'; import React from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { head } from 'ramda';
// store
import { useStore } from '../../store';
// components // components
import BeneficiarioDomandeTable from './components/BeneficiarioDomandeTable'; import BeneficiarioDomandeTable from './components/BeneficiarioDomandeTable';
const DomandePreInstructor = () => { const DomandePreInstructor = () => {
const chosenCompanyId = useStore().main.chosenCompanyId();
const companies = useStore().main.companies();
const company = head(companies.filter(o => o.id === chosenCompanyId));
return( return(
<div className="appPage"> <div className="appPage">
<div className="appPage__pageHeader"> <div className="appPage__pageHeader">
<h1>{__('Archivio domande', 'gepafin')}</h1> <h1>{__('Archivio domande', 'gepafin')}</h1>
{company ? <span className="companyName">{company.companyName}</span> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>

View File

@@ -193,7 +193,7 @@ const SoccorsoAddPreInstructor = () => {
<div className="appPageSection"> <div className="appPageSection">
<div className="appPageSection columns"> <div className="appPageSection columns">
<div> <div>
<h3>{__('Note', 'gepafin')}</h3> <h3>{__('Pec/Email', 'gepafin')}</h3>
<div style={{marginBottom: '30px'}}> <div style={{marginBottom: '30px'}}>
<Editor <Editor
value={formData.note} value={formData.note}
@@ -281,6 +281,7 @@ const SoccorsoAddPreInstructor = () => {
<Button <Button
type="button" type="button"
outlined outlined
onClick={goToEvaluationPage}
label={__('Anulla', 'gepafin')} label={__('Anulla', 'gepafin')}
icon="pi pi-times" iconPos="right"/> icon="pi pi-times" iconPos="right"/>
<Button <Button

View File

@@ -28,6 +28,7 @@ import FormField from '../../components/FormField';
import { Editor } from 'primereact/editor'; import { Editor } from 'primereact/editor';
import { InputNumber } from 'primereact/inputnumber'; import { InputNumber } from 'primereact/inputnumber';
import SoccorsoComunications from './components/SoccorsoComunications'; import SoccorsoComunications from './components/SoccorsoComunications';
import RepeaterFields from '../DomandaEditPreInstructor/components/RepeaterFields';
const SoccorsoEditPreInstructor = () => { const SoccorsoEditPreInstructor = () => {
@@ -35,6 +36,7 @@ const SoccorsoEditPreInstructor = () => {
const { id, amendmentId } = useParams(); const { id, amendmentId } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const [data, setData] = useState({}); const [data, setData] = useState({});
const [isVisibleCloseAmendDialog, setIsVisibleCloseAmendDialog] = useState(false);
const [isVisibleExtendTimeDialog, setIsVisibleExtendTimeDialog] = useState(false); const [isVisibleExtendTimeDialog, setIsVisibleExtendTimeDialog] = useState(false);
const [extendedTime, setExtendedTime] = useState(3); const [extendedTime, setExtendedTime] = useState(3);
const [isLoadingExtendingTime, setIsLoadingExtendingTime] = useState(false); const [isLoadingExtendingTime, setIsLoadingExtendingTime] = useState(false);
@@ -62,12 +64,16 @@ const SoccorsoEditPreInstructor = () => {
const getCallback = (data) => { const getCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
setData(getFormattedData(data.data)); setData(getFormattedData(data.data));
const formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => { let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) { if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue; acc[cur.fieldId] = cur.fieldValue;
} }
return acc; return acc;
}, {}); }, {});
formDataInitial = {
...formDataInitial,
amendmentDocuments: data.data.amendmentDocuments
}
setFormInitialData(formDataInitial); setFormInitialData(formDataInitial);
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
@@ -112,7 +118,7 @@ const SoccorsoEditPreInstructor = () => {
const header = renderHeader(); const header = renderHeader();
const updateNewAmendmentData = (value, path) => { const updateNewAmendmentData = (value, path) => {
const newData = wrap(data).set(path.split('.'), value).value(); const newData = wrap(data).set(path, value).value();
setData(newData); setData(newData);
} }
@@ -123,6 +129,7 @@ const SoccorsoEditPreInstructor = () => {
trigger(); trigger();
let formValues = klona(getValues()); let formValues = klona(getValues());
const newFormValues = Object.keys(formValues) const newFormValues = Object.keys(formValues)
.filter(v => v !== 'amendmentDocuments')
.reduce((acc, cur) => { .reduce((acc, cur) => {
let fieldVal = formValues[cur]; let fieldVal = formValues[cur];
@@ -135,10 +142,15 @@ const SoccorsoEditPreInstructor = () => {
}); });
return acc; return acc;
}, []); }, []);
const newAmendDocs = formValues.amendmentDocuments
? formValues.amendmentDocuments.map(o => o.id).join(',')
: '';
const submitData = { const submitData = {
applicationFormFields: newFormValues applicationFormFields: newFormValues,
amendmentDocuments: newAmendDocs
} }
storeSet.main.setAsyncRequest(); storeSet.main.setAsyncRequest();
AmendmentsService.updateSoccorso(amendmentId, submitData, updateAmendmentCallback, errUpdateAmendmentCallback); AmendmentsService.updateSoccorso(amendmentId, submitData, updateAmendmentCallback, errUpdateAmendmentCallback);
} }
@@ -152,13 +164,17 @@ const SoccorsoEditPreInstructor = () => {
detail: data.message detail: data.message
}); });
} }
const newFormDataInitial = data.data.applicationFormFields.reduce((acc, cur) => { let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) { if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue; acc[cur.fieldId] = cur.fieldValue;
} }
return acc; return acc;
}, formInitialData); }, formInitialData);
setFormInitialData(newFormDataInitial); formDataInitial = {
...formDataInitial,
amendmentDocuments: data.data.amendmentDocuments
}
setFormInitialData(formDataInitial);
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
@@ -175,6 +191,28 @@ const SoccorsoEditPreInstructor = () => {
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const openCloseAmendmentDialog = () => {
setIsVisibleCloseAmendDialog(true);
}
const headerCloseAmendDialog = () => {
return <span>{__('Chiudi Soccorso Istruttorio', 'gepafin')}</span>
}
const hideCloseAmendDialog = () => {
setIsVisibleCloseAmendDialog(false);
}
const footerCloseAmendDialog = () => {
return <div>
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideCloseAmendDialog} outlined/>
<Button
type="button"
disabled={isAsyncRequest || isEmpty(data.internalNotes)}
label={__('Invia', 'gepafin')} onClick={doCloseAmendment}/>
</div>
}
const doCloseAmendment = () => { const doCloseAmendment = () => {
const submitData = { const submitData = {
internalNote: data.internalNote internalNote: data.internalNote
@@ -193,7 +231,8 @@ const SoccorsoEditPreInstructor = () => {
}); });
} }
if (data.data.status) { if (data.data.status) {
updateNewAmendmentData(data.data.status, 'status') updateNewAmendmentData(data.data.status, ['status']);
setIsVisibleCloseAmendDialog(false);
} }
} }
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
@@ -297,7 +336,6 @@ const SoccorsoEditPreInstructor = () => {
useEffect(() => { useEffect(() => {
if (formInitialData) { if (formInitialData) {
//reset();
Object.keys(formInitialData).map(k => setValue(k, formInitialData[k])); Object.keys(formInitialData).map(k => setValue(k, formInitialData[k]));
trigger(); trigger();
} }
@@ -388,12 +426,12 @@ const SoccorsoEditPreInstructor = () => {
<SoccorsoComunications amendmentId={amendmentId} soccorsoStatus={data.status}/> <SoccorsoComunications amendmentId={amendmentId} soccorsoStatus={data.status}/>
</div> </div>
<div className="appPageSection"> {data.formFields && !isEmpty(data.formFields)
<h2>{__('Documenti Ricevuti', 'gepafin')}</h2> ? <div className="appPageSection">
<h2>{__('Documenti Ricevuti', 'gepafin')}</h2>
<form className="appForm" onSubmit={handleSubmit(onSubmit)}> <form className="appForm" onSubmit={handleSubmit(onSubmit)}>
{data.formFields {data.formFields.map((o, i) => {
? data.formFields.map((o, i) => {
return <FormField return <FormField
key={o.fieldId} key={o.fieldId}
disabled={data.status === 'CLOSE'} disabled={data.status === 'CLOSE'}
@@ -408,27 +446,38 @@ const SoccorsoEditPreInstructor = () => {
defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []} defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []}
accept={[]} accept={[]}
source="AMENDMENT" source="AMENDMENT"
sourceId={data.applicationId} sourceId={amendmentId}
multiple={true} multiple={true}
/> />
}) : null} })}
</form> </form>
</div> </div> : null}
<div className="appForm__field"> <div className="appPageSection">
<label>{__('Motivazioni / Note Interne', 'gepafin')}</label> <h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<div style={{ position: 'relative' }}> <div className="appPageSection">
<BlockingOverlay shouldDisplay={data.status === 'CLOSE'}/> {data.amendmentNotes
<Editor ? <>
value={data.internalNote} <h3>{__('Notes', 'gepafin')}</h3>
readOnly={data.status === 'CLOSE'} <div className="ql-editor" style={{ marginBottom: '30px', width: '100%' }}>
placeholder={__('Digita qui il messagio', 'gepafin')} {renderHtmlContent(data.amendmentNotes)}
headerTemplate={header} </div>
onTextChange={(e) => updateNewAmendmentData( </> : null}
e.htmlValue, <FormField
'internalNote' type="fileupload"
)} disabled={data.status === 'CLOSE'}
style={{ height: 80 * 3, width: '100%' }} setDataFn={setValue}
saveFormCallback={doUpdateAmendment}
fieldName="amendmentDocuments"
label={__('I file', 'gepafin')}
control={control}
register={register}
errors={errors}
defaultValue={formInitialData.amendmentDocuments ? formInitialData.amendmentDocuments : []}
accept={[]}
source="amendment"
sourceId={amendmentId}
multiple={true}
/> />
</div> </div>
</div> </div>
@@ -441,6 +490,12 @@ const SoccorsoEditPreInstructor = () => {
<div className="appPageSection"> <div className="appPageSection">
<div className="appPageSection__actions"> <div className="appPageSection__actions">
{/*<Button
type="button"
disabled={isAsyncRequest}
onClick={doUpdateAmendment}
label={__('Salva', 'gepafin')}
icon="pi pi-save" iconPos="right"/>*/}
<Button <Button
type="button" type="button"
onClick={sendReminder} onClick={sendReminder}
@@ -465,7 +520,7 @@ const SoccorsoEditPreInstructor = () => {
icon="pi pi-save" iconPos="right"/>*/} icon="pi pi-save" iconPos="right"/>*/}
<Button <Button
type="button" type="button"
onClick={doCloseAmendment} onClick={openCloseAmendmentDialog}
disabled={isAsyncRequest || data.status === 'CLOSE'} disabled={isAsyncRequest || data.status === 'CLOSE'}
label={__('Chiudi Soccorso Istruttorio', 'gepafin')} label={__('Chiudi Soccorso Istruttorio', 'gepafin')}
icon="pi pi-times" iconPos="right"/> icon="pi pi-times" iconPos="right"/>
@@ -494,6 +549,32 @@ const SoccorsoEditPreInstructor = () => {
onChange={(e) => setExtendedTime(e.value)}/> onChange={(e) => setExtendedTime(e.value)}/>
</div> </div>
</Dialog> </Dialog>
<Dialog
visible={isVisibleCloseAmendDialog}
modal
header={headerCloseAmendDialog}
footer={footerCloseAmendDialog}
style={{ maxWidth: '600px', width: '100%' }}
onHide={hideCloseAmendDialog}>
<div className="appForm__field">
<label>{__('Motivazioni', 'gepafin')}</label>
<div style={{ position: 'relative' }}>
<BlockingOverlay shouldDisplay={data.status === 'CLOSE'}/>
<Editor
value={data.internalNote}
readOnly={data.status === 'CLOSE'}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateNewAmendmentData(
e.htmlValue,
['internalNote']
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
</div>
</Dialog>
</div> </div>
) )

View File

@@ -4,11 +4,15 @@ const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
export default class AppointmentService { export default class AppointmentService {
static getNdg = (id, callback, errCallback, queryParams) => { static getNdg = (applicationId, callback, errCallback, queryParams) => {
NetworkService.get(`${API_BASE_URL}/appointment/application/${id}/check-ndg`, callback, errCallback, queryParams); NetworkService.get(`${API_BASE_URL}/appointment/application/${applicationId}/check-ndg`, callback, errCallback, queryParams);
}; };
static archiveDocument = (applicationId, documentId, body, callback, errCallback, queryParams) => { static archiveDocument = (applicationId, documentId, body, callback, errCallback, queryParams) => {
NetworkService.post(`${API_BASE_URL}/appointment/application/${applicationId}/document/${documentId}`, {}, callback, errCallback, queryParams); NetworkService.post(`${API_BASE_URL}/appointment/document/${documentId}`, body, callback, errCallback, queryParams);
};
static createAppointment = (applicationId, body, callback, errCallback, queryParams) => {
NetworkService.post(`${API_BASE_URL}/appointment/application/${applicationId}`, body, callback, errCallback, queryParams);
}; };
} }

View File

@@ -1,33 +1,11 @@
import { storeGet, storeSet } from '../store'; import { storeGet, storeSet } from '../store';
import * as Sentry from '@sentry/browser'; import logMsgWithSentry from '../helpers/logMsgWithSentry';
const LOCAL_DEVELOPMENT = process.env.REACT_APP_LOCAL_DEVELOPMENT;
export class NetworkService { export class NetworkService {
static TOKEN_KEY
static REFRESH_TOKEN_KEY
static logApiError = (endpoint, status = 0, resp = {}) => { static logApiError = (endpoint, status = 0, resp = {}) => {
if (status === 500) { if (status === 500) {
if (LOCAL_DEVELOPMENT !== '1') { logMsgWithSentry(endpoint, status, resp);
try {
Sentry.init({
dsn: 'https://e7b2134f7d816f663bb83e51b106a694@o4508381921738752.ingest.de.sentry.io/4508381935501392',
environment: process.env.NODE_ENV || 'development'
});
const error = new Error(`Status ${status}`);
Sentry.captureException(`Error in endpoint: ${endpoint}`, {
level: 'error',
extra: {
originalError: error,
details: resp
}
});
} catch (err) {
console.log(err);
}
}
} else if (status === 403) { } else if (status === 403) {
storeSet.main.token(''); storeSet.main.token('');
const { pathname } = window.location; const { pathname } = window.location;
@@ -52,8 +30,9 @@ export class NetworkService {
} }
} }
if (url.charAt(url.length) === '&') if (url.charAt(url.length) === '&') {
url = url.substring(0, url.length - 1); url = url.substring(0, url.length - 1);
}
} }
fetch(url, { fetch(url, {