- saving progress - amendment page works for both instructor and beneficiary;

This commit is contained in:
Vitalii Kiiko
2024-12-18 15:00:17 +01:00
parent 6724b9a5ba
commit 23525141b1
8 changed files with 170 additions and 134 deletions

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

@@ -78,7 +78,7 @@ const DomandaBeneficiario = () => {
}, {}); }, {});
formDataInitial = { formDataInitial = {
...formDataInitial, ...formDataInitial,
amendmentDocuments: data.amendmentDocuments amendmentDocuments: amendmentObj.amendmentDocuments
} }
setFormInitialData(formDataInitial); setFormInitialData(formDataInitial);
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
@@ -108,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;
@@ -156,13 +156,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();
} }
@@ -350,39 +354,42 @@ const DomandaBeneficiario = () => {
</ol> </ol>
</div> : null} </div> : null}
<div className="appPageSection"> {data.id
<h2>{__('Documenti aggiuntivi', 'gepafin')}</h2> ? <div className="appPageSection">
<div className="appPageSection"> <h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<h3>{__('Notes', 'gepafin')}</h3> <div className="appPageSection">
<div style={{ marginBottom: '30px', width: '100%' }}> <h3>{__('Notes', 'gepafin')}</h3>
<Editor <div style={{ marginBottom: '30px', width: '100%' }}>
value={data.amendmentNotes} <Editor
placeholder={__('Digita qui il messagio', 'gepafin')} value={data.amendmentNotes}
headerTemplate={header} readOnly={data.status === 'CLOSE'}
onTextChange={(e) => updateNewAmendmentData( placeholder={__('Digita qui il messagio', 'gepafin')}
e.htmlValue, headerTemplate={header}
'amendmentNotes' onTextChange={(e) => updateNewAmendmentData(
)} e.htmlValue,
style={{ height: 80 * 3, width: '100%' }} '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>
<FormField </div> : null}
type="fileupload"
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>
{data.id {data.id
? <div className="appPageSection__message warning"> ? <div className="appPageSection__message warning">
@@ -400,12 +407,13 @@ const DomandaBeneficiario = () => {
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}
<Button {data.id
type="button" ? <Button
disabled={isAsyncRequest} type="button"
onClick={doUpdateAmendment} disabled={isAsyncRequest}
label={__('Salva', 'gepafin')} onClick={doUpdateAmendment}
icon="pi pi-save" iconPos="right"/> label={__('Salva', 'gepafin')}
icon="pi pi-save" iconPos="right"/> : null}
<Button <Button
type="button" type="button"
outlined outlined

View File

@@ -3,6 +3,7 @@ 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';
const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applicationId }) => { const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applicationId }) => {
@@ -10,32 +11,32 @@ const ListOfFiles = ({ files, updateFn, shouldDisableFieldFn, name, ndg, applica
<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} className="appPageSection__listItem">
<div className="appPageSection__listItemRow"> <div className="appPageSection__listItemRow">
<span>{o.label}</span> <div>{renderHtmlContent(o.label)}</div>
{o.fileDetail && o.fileDetail.length === 1 <div className="appPageSection__iconActions">
? <div className="appPageSection__iconActions"> {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')}/> aria-label={__('Mostra', 'gepafin')}/> : 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'}
onClick={() => updateFn( onClick={() => updateFn(
true, true,
[name, i, 'valid'] [name, i, 'valid']
)} )}
aria-label={__('Su', 'gepafin')}/> aria-label={__('Su', 'gepafin')}/>
<Button icon="pi pi-thumbs-down" rounded outlined <Button icon="pi pi-thumbs-down" rounded outlined
disabled={shouldDisableFieldFn(name)} disabled={shouldDisableFieldFn(name)}
severity={!isNil(o.valid) && !o.valid ? 'danger' : 'secondary'} severity={!isNil(o.valid) && !o.valid ? 'danger' : 'secondary'}
onClick={() => updateFn( onClick={() => updateFn(
false, false,
[name, i, 'valid'] [name, i, 'valid']
)} )}
aria-label={__('Giu', 'gepafin')}/> aria-label={__('Giu', 'gepafin')}/>
</div> : null} </div>
</div> </div>
{o.fileDetail && o.fileDetail.length > 1 {o.fileDetail && o.fileDetail.length > 1
? <ul style={{ ? <ul style={{

View File

@@ -605,34 +605,34 @@ const DomandaEditPreInstructor = () => {
</div> </div>
</div> </div>
{/*<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Documenti di soccorso', 'gepafin')}</h2> <h2>{__('Documenti di soccorso', 'gepafin')}</h2>
{data.amendmentDetails {data.amendmentDetails
.filter(o => o.amendmentDocuments && !isEmpty(o.amendmentDocuments)
|| o.formFieldDocuments && !isEmpty(o.formFieldDocuments))
.map(o => { .map(o => {
const aDocs = pathOr([],['amendmentDocuments'], o) const aDocs = pathOr([],['amendmentDocuments'], o);
.map(o => ({ const aNotes = pathOr('',['amendmentNotes'], o);
id: o.fieldId, const aValid = pathOr(null,['valid'], o);
label: o.nameValue, const aDocsObj = {
fileDetail: o.fileValue, id: o.amendmentId,
valid: o.valid label: aNotes,
})); fileDetail: aDocs,
valid: aValid
}
const fDocs = pathOr([],['formFieldDocuments'], o); const fDocs = pathOr([],['formFieldDocuments'], o);
return { return {
id: o.id, files: [aDocsObj, ...fDocs]
files: [...aDocs, ...fDocs]
} }
}) })
.map(o => <ListOfFiles .map((o, i) => <ListOfFiles
key={`list_${i}`}
files={o.files} files={o.files}
updateFn={updateEvaluationValue} updateFn={updateEvaluationValue}
shouldDisableFieldFn={shouldDisableField} shouldDisableFieldFn={shouldDisableField}
name="files" name="amendmentDetails"
ndg={data.ndg} ndg={data.ndg}
applicationId={id}/>)} applicationId={id}/>)}
</div>*/} </div>
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Punteggi di valutazione', 'gepafin')}</h2> <h2>{__('Punteggi di valutazione', 'gepafin')}</h2>

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.applicationStatus === '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

@@ -72,7 +72,7 @@ const SoccorsoEditPreInstructor = () => {
}, {}); }, {});
formDataInitial = { formDataInitial = {
...formDataInitial, ...formDataInitial,
amendmentDocuments: data.amendmentDocuments amendmentDocuments: data.data.amendmentDocuments
} }
setFormInitialData(formDataInitial); setFormInitialData(formDataInitial);
} }
@@ -162,13 +162,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();
} }
@@ -225,7 +229,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();
@@ -448,7 +453,7 @@ const SoccorsoEditPreInstructor = () => {
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Documenti aggiuntivi', 'gepafin')}</h2> <h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<div className="appPageSection columns"> <div className="appPageSection">
{data.amendmentNotes {data.amendmentNotes
? <> ? <>
<h3>{__('Notes', 'gepafin')}</h3> <h3>{__('Notes', 'gepafin')}</h3>
@@ -458,6 +463,7 @@ const SoccorsoEditPreInstructor = () => {
</> : null} </> : null}
<FormField <FormField
type="fileupload" type="fileupload"
disabled={data.status === 'CLOSE'}
setDataFn={setValue} setDataFn={setValue}
saveFormCallback={doUpdateAmendment} saveFormCallback={doUpdateAmendment}
fieldName="amendmentDocuments" fieldName="amendmentDocuments"
@@ -482,12 +488,12 @@ const SoccorsoEditPreInstructor = () => {
<div className="appPageSection"> <div className="appPageSection">
<div className="appPageSection__actions"> <div className="appPageSection__actions">
<Button {/*<Button
type="button" type="button"
disabled={isAsyncRequest} disabled={isAsyncRequest}
onClick={doUpdateAmendment} onClick={doUpdateAmendment}
label={__('Salva', 'gepafin')} label={__('Salva', 'gepafin')}
icon="pi pi-save" iconPos="right"/> icon="pi pi-save" iconPos="right"/>*/}
<Button <Button
type="button" type="button"
onClick={sendReminder} onClick={sendReminder}