- implemented root manager functionality;
This commit is contained in:
@@ -74,6 +74,9 @@ const getBandoLabel = (status) => {
|
||||
case 'REJECTED':
|
||||
return __('Respinto', 'gepafin');
|
||||
|
||||
case 'DELETED':
|
||||
return __('Cancellato', 'gepafin');
|
||||
|
||||
case 'TECHNICAL_EVALUATION_REJECTED':
|
||||
return __('Respinto Tec-Fin', 'gepafin');
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ const getBandoSeverity = (status) => {
|
||||
case 'REJECTED':
|
||||
return 'danger';
|
||||
|
||||
case 'DELETED':
|
||||
return 'danger';
|
||||
|
||||
case 'TECHNICAL_EVALUATION_REJECTED':
|
||||
return 'danger';
|
||||
|
||||
|
||||
@@ -1,10 +1,370 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import translationStrings from '../../../../translationStringsForComponents';
|
||||
|
||||
// api
|
||||
import ApplicationService from '../../../../service/application-service';
|
||||
import AdminService from '../../../../service/admin-service';
|
||||
|
||||
// helpers
|
||||
import getQueryParamsForPaginatedEndpoint from '../../../../helpers/getQueryParamsForPaginatedEndpoint';
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
|
||||
// components
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const allStatuses = [
|
||||
'SUBMIT', 'EVALUATION', 'SOCCORSO', 'APPOINTMENT', 'NDG', 'ADMISSIBLE',
|
||||
'AWAITING_TECHNICAL_EVALUATION', 'TECHNICAL_EVALUATION'
|
||||
];
|
||||
|
||||
const initialDeletedLazyState = {
|
||||
first: 0,
|
||||
rows: 10,
|
||||
page: 0
|
||||
};
|
||||
|
||||
const initialPreDeleteLazyState = {
|
||||
first: 0,
|
||||
rows: 5,
|
||||
page: 0,
|
||||
sortField: null,
|
||||
sortOrder: null,
|
||||
filters: {
|
||||
id: { value: null, matchMode: 'equals' },
|
||||
callTitle: { value: null, matchMode: 'contains' },
|
||||
companyName: { value: null, matchMode: 'contains' },
|
||||
status: { value: null, matchMode: 'equals' }
|
||||
}
|
||||
};
|
||||
|
||||
const ManageApplDeleteSection = ({ canViewDeleted, canDeleteConfirm, canDelete }) => {
|
||||
return <div className="appPageSection">
|
||||
<h2>{__('Gestione domande eliminate', 'gepafin')}</h2>
|
||||
</div>
|
||||
}
|
||||
const toast = useRef(null);
|
||||
|
||||
// --- Table 1: Deleted applications ---
|
||||
const [deletedLoading, setDeletedLoading] = useState(false);
|
||||
const [deletedItems, setDeletedItems] = useState(null);
|
||||
const [deletedTotal, setDeletedTotal] = useState(0);
|
||||
const [deletedLazyState, setDeletedLazyState] = useState(initialDeletedLazyState);
|
||||
const [deletedRefreshKey, setDeletedRefreshKey] = useState(0);
|
||||
const [finalDeleteDialogVisible, setFinalDeleteDialogVisible] = useState(false);
|
||||
const [finalDeleteAppId, setFinalDeleteAppId] = useState(null);
|
||||
const [finalDeleteLoading, setFinalDeleteLoading] = useState(false);
|
||||
|
||||
// --- Table 2: Pre-delete applications ---
|
||||
const [preDeleteLoading, setPreDeleteLoading] = useState(false);
|
||||
const [preDeleteItems, setPreDeleteItems] = useState(null);
|
||||
const [preDeleteTotal, setPreDeleteTotal] = useState(0);
|
||||
const [preDeleteLazyState, setPreDeleteLazyState] = useState(initialPreDeleteLazyState);
|
||||
const [preDeleteRefreshKey, setPreDeleteRefreshKey] = useState(0);
|
||||
const [preDeleteDialogVisible, setPreDeleteDialogVisible] = useState(false);
|
||||
const [preDeleteAppId, setPreDeleteAppId] = useState(null);
|
||||
const [preDeleteActionLoading, setPreDeleteActionLoading] = useState(false);
|
||||
|
||||
// ---- Table 1 handlers ----
|
||||
|
||||
const getDeletedCallback = (resp) => {
|
||||
if (resp.status === 'success') {
|
||||
const { body, totalRecords } = resp.data;
|
||||
setDeletedTotal(totalRecords);
|
||||
setDeletedItems(body);
|
||||
}
|
||||
setDeletedLoading(false);
|
||||
};
|
||||
|
||||
const errDeletedCallback = () => {
|
||||
setDeletedLoading(false);
|
||||
};
|
||||
|
||||
const openFinalDeleteDialog = (appId) => {
|
||||
setFinalDeleteAppId(appId);
|
||||
setFinalDeleteDialogVisible(true);
|
||||
};
|
||||
|
||||
const hideFinalDeleteDialog = () => {
|
||||
setFinalDeleteDialogVisible(false);
|
||||
setFinalDeleteAppId(null);
|
||||
};
|
||||
|
||||
const handleFinalDelete = useCallback(() => {
|
||||
setFinalDeleteLoading(true);
|
||||
AdminService.doFinalDelete(
|
||||
{ application_id: finalDeleteAppId },
|
||||
() => {
|
||||
setDeletedRefreshKey(k => k + 1);
|
||||
setFinalDeleteLoading(false);
|
||||
hideFinalDeleteDialog();
|
||||
},
|
||||
(resp) => {
|
||||
if (toast.current) {
|
||||
toast.current.show({ severity: 'error', summary: '', detail: resp.detail });
|
||||
}
|
||||
setFinalDeleteLoading(false);
|
||||
hideFinalDeleteDialog();
|
||||
}
|
||||
);
|
||||
}, [finalDeleteAppId]);
|
||||
|
||||
const deletedActionsBodyTemplate = (rowData) => (
|
||||
<div className="appPageSection__tableActions lessGap">
|
||||
<Button
|
||||
severity="danger"
|
||||
onClick={() => openFinalDeleteDialog(rowData.id)}
|
||||
label={__('Conferma eliminazione', 'gepafin')}
|
||||
icon="pi pi-trash"
|
||||
size="small"
|
||||
iconPos="right"/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const finalDeleteDialogFooter = (
|
||||
<div>
|
||||
<Button label={__('Annulla', 'gepafin')} icon="pi pi-times" outlined onClick={hideFinalDeleteDialog}
|
||||
disabled={finalDeleteLoading}/>
|
||||
<Button label={__('Conferma', 'gepafin')} icon="pi pi-check" severity="danger"
|
||||
onClick={handleFinalDelete} disabled={finalDeleteLoading} loading={finalDeleteLoading}/>
|
||||
</div>
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!canViewDeleted) return;
|
||||
setDeletedLoading(true);
|
||||
AdminService.getDeletedAppl(getDeletedCallback, errDeletedCallback, {
|
||||
page: deletedLazyState.page + 1,
|
||||
page_size: deletedLazyState.rows
|
||||
});
|
||||
}, [deletedLazyState, deletedRefreshKey, canViewDeleted]);
|
||||
|
||||
// ---- Table 2 handlers ----
|
||||
|
||||
const getPreDeletePaginationQuery = useCallback(
|
||||
() => getQueryParamsForPaginatedEndpoint(preDeleteLazyState, allStatuses, 'id'),
|
||||
[preDeleteLazyState]
|
||||
);
|
||||
|
||||
const getPreDeleteCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
const { body, totalRecords } = resp.data;
|
||||
setPreDeleteTotal(totalRecords);
|
||||
setPreDeleteItems(body);
|
||||
}
|
||||
setPreDeleteLoading(false);
|
||||
};
|
||||
|
||||
const errPreDeleteCallback = () => {
|
||||
setPreDeleteLoading(false);
|
||||
};
|
||||
|
||||
const openPreDeleteDialog = (appId) => {
|
||||
setPreDeleteAppId(appId);
|
||||
setPreDeleteDialogVisible(true);
|
||||
};
|
||||
|
||||
const hidePreDeleteDialog = () => {
|
||||
setPreDeleteDialogVisible(false);
|
||||
setPreDeleteAppId(null);
|
||||
};
|
||||
|
||||
const handlePreDelete = useCallback(() => {
|
||||
setPreDeleteActionLoading(true);
|
||||
AdminService.doPreDelete(
|
||||
{ application_id: preDeleteAppId },
|
||||
() => {
|
||||
setPreDeleteRefreshKey(k => k + 1);
|
||||
setDeletedRefreshKey(k => k + 1);
|
||||
setPreDeleteActionLoading(false);
|
||||
hidePreDeleteDialog();
|
||||
},
|
||||
(resp) => {
|
||||
if (toast.current) {
|
||||
toast.current.show({ severity: 'error', summary: '', detail: resp.detail });
|
||||
}
|
||||
setPreDeleteActionLoading(false);
|
||||
hidePreDeleteDialog();
|
||||
}
|
||||
);
|
||||
}, [preDeleteAppId]);
|
||||
|
||||
const preDeleteActionsBodyTemplate = (rowData) => (
|
||||
<div className="appPageSection__tableActions lessGap">
|
||||
<Button
|
||||
severity="danger"
|
||||
onClick={() => openPreDeleteDialog(rowData.id)}
|
||||
label={__('Cancella', 'gepafin')}
|
||||
icon="pi pi-trash"
|
||||
size="small"
|
||||
iconPos="right"/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const statusBodyTemplate = (rowData) => <ProperBandoLabel status={rowData.status}/>;
|
||||
|
||||
const statusItemTemplate = (option) => (
|
||||
<Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>
|
||||
);
|
||||
|
||||
const statusFilterTemplate = (options) => (
|
||||
<Dropdown
|
||||
value={options.value}
|
||||
options={allStatuses}
|
||||
valueTemplate={getBandoLabel(options.value)}
|
||||
onChange={(e) => {
|
||||
options.filterCallback(e.value, options.index);
|
||||
const filters = { ...preDeleteLazyState.filters };
|
||||
if (e.value) {
|
||||
filters['status'] = { value: e.value, matchMode: 'equals' };
|
||||
} else {
|
||||
delete filters['status'];
|
||||
}
|
||||
setPreDeleteLazyState({ ...preDeleteLazyState, filters, first: 0 });
|
||||
}}
|
||||
itemTemplate={statusItemTemplate}
|
||||
placeholder={translationStrings.selectOneLabel}
|
||||
className="p-column-filter"/>
|
||||
);
|
||||
|
||||
const preDeleteDialogFooter = (
|
||||
<div>
|
||||
<Button label={__('Annulla', 'gepafin')} icon="pi pi-times" outlined onClick={hidePreDeleteDialog}
|
||||
disabled={preDeleteActionLoading}/>
|
||||
<Button label={__('Conferma', 'gepafin')} icon="pi pi-check" severity="danger"
|
||||
onClick={handlePreDelete} disabled={preDeleteActionLoading} loading={preDeleteActionLoading}/>
|
||||
</div>
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!canDelete) return;
|
||||
setPreDeleteLoading(true);
|
||||
const paginationQuery = getPreDeletePaginationQuery();
|
||||
ApplicationService.getApplicationsPaginated(paginationQuery, getPreDeleteCallback, errPreDeleteCallback);
|
||||
}, [preDeleteLazyState, preDeleteRefreshKey, canDelete]);
|
||||
|
||||
return (
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Gestione domande eliminate', 'gepafin')}</h2>
|
||||
<Toast ref={toast}/>
|
||||
|
||||
{canViewDeleted && (
|
||||
<>
|
||||
<h3>{__('Domande eliminate', 'gepafin')}</h3>
|
||||
<div className="appPageSection__table">
|
||||
<DataTable
|
||||
value={deletedItems} stripedRows showGridlines
|
||||
lazy dataKey="id" paginator
|
||||
first={deletedLazyState.first}
|
||||
rows={deletedLazyState.rows}
|
||||
totalRecords={deletedTotal}
|
||||
onPage={(e) => setDeletedLazyState(e)}
|
||||
loading={deletedLoading}
|
||||
header={
|
||||
<div className="flex justify-content-between">
|
||||
<Button type="button" icon="pi pi-refresh" label={__('Aggiorna', 'gepafin')}
|
||||
outlined onClick={() => setDeletedLazyState({ ...deletedLazyState })}/>
|
||||
</div>
|
||||
}
|
||||
emptyMessage={translationStrings.emptyMessage}>
|
||||
<Column field="id" header={__('ID domanda', 'gepafin')}
|
||||
body={(rowData) => rowData.id}
|
||||
style={{ minWidth: '6rem' }}/>
|
||||
<Column field="call_name" header={__('Bando', 'gepafin')}
|
||||
style={{ minWidth: '10rem' }}/>
|
||||
<Column field="company_name" header={__('Azienda Beneficiaria', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={statusBodyTemplate}/>
|
||||
{canDeleteConfirm && (
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={deletedActionsBodyTemplate}/>
|
||||
)}
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={finalDeleteDialogVisible}
|
||||
modal
|
||||
header={__('Conferma eliminazione definitiva', 'gepafin')}
|
||||
footer={finalDeleteDialogFooter}
|
||||
style={{ maxWidth: '500px', width: '100%' }}
|
||||
onHide={hideFinalDeleteDialog}>
|
||||
<p>{__('Sei sicuro di voler eliminare definitivamente questa domanda? L\'operazione non è reversibile.', 'gepafin')}</p>
|
||||
</Dialog>
|
||||
</>
|
||||
)}
|
||||
|
||||
{canDelete && (
|
||||
<>
|
||||
<div className="appPage__spacer"></div>
|
||||
<h3>{__('Cancella domanda', 'gepafin')}</h3>
|
||||
<div className="appPageSection__table">
|
||||
<DataTable
|
||||
value={preDeleteItems} stripedRows showGridlines
|
||||
lazy filterDisplay="menu" dataKey="id" paginator
|
||||
first={preDeleteLazyState.first}
|
||||
rows={preDeleteLazyState.rows}
|
||||
totalRecords={preDeleteTotal}
|
||||
onPage={(e) => setPreDeleteLazyState(e)}
|
||||
onSort={(e) => { e['first'] = 0; e['page'] = 0; setPreDeleteLazyState(e); }}
|
||||
sortField={preDeleteLazyState.sortField}
|
||||
sortOrder={preDeleteLazyState.sortOrder}
|
||||
onFilter={(e) => { e['first'] = 0; e['page'] = 0; setPreDeleteLazyState(e); }}
|
||||
filters={preDeleteLazyState.filters}
|
||||
loading={preDeleteLoading}
|
||||
header={
|
||||
<div className="flex justify-content-between">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')}
|
||||
outlined onClick={() => setPreDeleteLazyState(initialPreDeleteLazyState)}/>
|
||||
</div>
|
||||
}
|
||||
emptyMessage={translationStrings.emptyMessage}>
|
||||
<Column field="id" header={__('ID domanda', 'gepafin')}
|
||||
sortable
|
||||
filterField="id" filter
|
||||
filterMatchModeOptions={translationStrings.numberFilterOptions}
|
||||
filterPlaceholder={__('Cerca', 'gepafin')}
|
||||
style={{ minWidth: '6rem' }}/>
|
||||
<Column field="callTitle" header={__('Bando', 'gepafin')}
|
||||
filterField="callTitle" filter
|
||||
filterMatchModeOptions={translationStrings.textFilterOptions}
|
||||
filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '10rem' }}/>
|
||||
<Column field="companyName" header={__('Azienda Beneficiaria', 'gepafin')}
|
||||
filterField="companyName" filter
|
||||
filterMatchModeOptions={translationStrings.textFilterOptions}
|
||||
filterPlaceholder={__('Cerca il nome', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
filterElement={statusFilterTemplate} filter
|
||||
filterMatchModeOptions={translationStrings.statusFilterOptions}
|
||||
style={{ minWidth: '8rem' }}
|
||||
body={statusBodyTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={preDeleteActionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={preDeleteDialogVisible}
|
||||
modal
|
||||
header={__('Conferma cancellazione', 'gepafin')}
|
||||
footer={preDeleteDialogFooter}
|
||||
style={{ maxWidth: '500px', width: '100%' }}
|
||||
onHide={hidePreDeleteDialog}>
|
||||
<p>{__('Sei sicuro di voler cancellare questa domanda?', 'gepafin')}</p>
|
||||
</Dialog>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ManageApplDeleteSection;
|
||||
|
||||
@@ -117,7 +117,7 @@ const ManageApplStatusSection = () => {
|
||||
hideStatusDialog();
|
||||
}
|
||||
|
||||
const errCallback = () => {
|
||||
const errCallback = (resp) => {
|
||||
if (toast.current) {
|
||||
toast.current.show({
|
||||
severity: 'error',
|
||||
|
||||
@@ -822,7 +822,7 @@ const DomandaEditInstructorManager = () => {
|
||||
storeSet('unsetAsyncRequest');
|
||||
}
|
||||
|
||||
const doCreateAppointment = () => {
|
||||
/*const doCreateAppointment = () => {
|
||||
setAppointmentData({
|
||||
title: '',
|
||||
text: '',
|
||||
@@ -830,7 +830,7 @@ const DomandaEditInstructorManager = () => {
|
||||
amount: 0
|
||||
});
|
||||
setIsVisibleAppointmentDialog(true);
|
||||
}
|
||||
}*/
|
||||
|
||||
const setAppointmentFieldValue = (name, value) => {
|
||||
const newData = wrap(appointmentData).set(name, value).value();
|
||||
|
||||
@@ -822,7 +822,7 @@ const DomandaEditPreInstructor = () => {
|
||||
storeSet('unsetAsyncRequest');
|
||||
}
|
||||
|
||||
const doCreateAppointment = () => {
|
||||
/*const doCreateAppointment = () => {
|
||||
setAppointmentData({
|
||||
title: '',
|
||||
text: '',
|
||||
@@ -830,7 +830,7 @@ const DomandaEditPreInstructor = () => {
|
||||
amount: 0
|
||||
});
|
||||
setIsVisibleAppointmentDialog(true);
|
||||
}
|
||||
}*/
|
||||
|
||||
const setAppointmentFieldValue = (name, value) => {
|
||||
const newData = wrap(appointmentData).set(name, value).value();
|
||||
|
||||
@@ -21,10 +21,22 @@ export default class AdminService {
|
||||
};
|
||||
|
||||
static doSendPec = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_ADMIN_BASE_URL}/send-pec`, body, callback, errCallback, queryParams);
|
||||
NetworkService.postMultiPart(`${API_ADMIN_BASE_URL}/send-pec`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static getAdminLog = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_ADMIN_BASE_URL}/admin-operations`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static getDeletedAppl = (callback, errCallback, queryParams) => {
|
||||
NetworkService.get(`${API_ADMIN_BASE_URL}/status-deleted`, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static doPreDelete = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.delete(`${API_ADMIN_BASE_URL}/pre-delete`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static doFinalDelete = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.delete(`${API_ADMIN_BASE_URL}/def-delete`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user