- added new root manage UIs;
This commit is contained in:
@@ -158,7 +158,8 @@ const AppSidebar = () => {
|
||||
'ROOT_MANAGE_APPL_VIEW_DELETED',
|
||||
'ROOT_MANAGE_APPL_DELETE_CONFIRM',
|
||||
'ROOT_MANAGE_APPL_DELETE',
|
||||
'ROOT_MANAGE_PEC_SEND'
|
||||
'ROOT_MANAGE_PEC_SEND',
|
||||
'ROOT_MANAGE_VIEW_LOG'
|
||||
]).length
|
||||
},
|
||||
{
|
||||
|
||||
121
src/pages/Admin/components/ManageSendPecSection/index.js
Normal file
121
src/pages/Admin/components/ManageSendPecSection/index.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
// api
|
||||
import AdminService from '../../../../service/admin-service';
|
||||
|
||||
// components
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const ManageSendPecSection = () => {
|
||||
const [subject, setSubject] = useState('');
|
||||
const [body, setBody] = useState('');
|
||||
const [csvFile, setCsvFile] = useState(null);
|
||||
const [attachment, setAttachment] = useState(null);
|
||||
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
|
||||
const toast = useRef(null);
|
||||
const csvInputRef = useRef(null);
|
||||
const attachmentInputRef = useRef(null);
|
||||
|
||||
const isSubmitDisabled = localAsyncRequest || !subject.trim() || !body.trim() || !csvFile;
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
const formData = new FormData();
|
||||
formData.append('subject', subject);
|
||||
formData.append('body', body);
|
||||
formData.append('csv_file', csvFile);
|
||||
if (attachment) {
|
||||
formData.append('attachment', attachment);
|
||||
}
|
||||
|
||||
setLocalAsyncRequest(true);
|
||||
AdminService.doSendPec(
|
||||
formData,
|
||||
(resp) => {
|
||||
setLocalAsyncRequest(false);
|
||||
if (resp && resp.status === 'ok') {
|
||||
const detail = resp.data
|
||||
? __(`Invio completato: ${resp.data.total_sent} inviati, ${resp.data.total_errors} errori`, 'gepafin')
|
||||
: __('Invio completato con successo', 'gepafin');
|
||||
if (toast.current) {
|
||||
toast.current.show({ severity: 'success', summary: '', detail });
|
||||
}
|
||||
setSubject('');
|
||||
setBody('');
|
||||
setCsvFile(null);
|
||||
setAttachment(null);
|
||||
if (csvInputRef.current) csvInputRef.current.value = '';
|
||||
if (attachmentInputRef.current) attachmentInputRef.current.value = '';
|
||||
} else {
|
||||
if (toast.current) {
|
||||
toast.current.show({ severity: 'error', summary: '', detail: resp && resp.detail ? resp.detail : __('Errore durante l\'invio', 'gepafin') });
|
||||
}
|
||||
}
|
||||
},
|
||||
(resp) => {
|
||||
setLocalAsyncRequest(false);
|
||||
if (toast.current) {
|
||||
toast.current.show({ severity: 'error', summary: '', detail: resp && resp.detail ? resp.detail : __('Errore durante l\'invio', 'gepafin') });
|
||||
}
|
||||
}
|
||||
);
|
||||
}, [subject, body, csvFile, attachment]);
|
||||
|
||||
return (
|
||||
<div className="appPageSection">
|
||||
<h2>{__('Invio PEC Massivo', 'gepafin')}</h2>
|
||||
<Toast ref={toast}/>
|
||||
<div className="appForm">
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="pecSubject">{__('Oggetto', 'gepafin')} *</label>
|
||||
<InputText
|
||||
id="pecSubject"
|
||||
value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)}
|
||||
style={{ width: '100%' }}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="pecBody">{__('Corpo della PEC', 'gepafin')} *</label>
|
||||
<InputTextarea
|
||||
id="pecBody"
|
||||
value={body}
|
||||
onChange={(e) => setBody(e.target.value)}
|
||||
rows={8}
|
||||
style={{ width: '100%' }}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="pecCsv">{__('File CSV destinatari', 'gepafin')} *</label>
|
||||
<input
|
||||
ref={csvInputRef}
|
||||
id="pecCsv"
|
||||
type="file"
|
||||
accept=".csv"
|
||||
onChange={(e) => setCsvFile(e.target.files[0] || null)}/>
|
||||
<small>{__('Il file CSV deve contenere gli indirizzi PEC nella prima colonna', 'gepafin')}</small>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="pecAttachment">{__('Allegato (opzionale)', 'gepafin')}</label>
|
||||
<input
|
||||
ref={attachmentInputRef}
|
||||
id="pecAttachment"
|
||||
type="file"
|
||||
onChange={(e) => setAttachment(e.target.files[0] || null)}/>
|
||||
</div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
type="button"
|
||||
label={__('Invia PEC', 'gepafin')}
|
||||
icon="pi pi-send"
|
||||
loading={localAsyncRequest}
|
||||
disabled={isSubmitDisabled}
|
||||
onClick={handleSubmit}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ManageSendPecSection;
|
||||
@@ -1,46 +1,88 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import ManageNdgSection from './components/ManageNdgSection';
|
||||
import ManageApplStatusSection from './components/ManageApplStatusSection';
|
||||
import ManageAmendmentReopenSection from './components/ManageAmendmentReopenSection';
|
||||
import ManageAmendmentExtendSection from './components/ManageAmendmentExtendSection';
|
||||
import ManageApplDeleteSection from './components/ManageApplDeleteSection';
|
||||
import { Card } from 'primereact/card';
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
permission: ['ROOT_MANAGE_NDG'],
|
||||
route: '/admin/set-ndg',
|
||||
label: __('Gestione NDG', 'gepafin'),
|
||||
subtitle: __('Imposta il codice NDG per le domande', 'gepafin'),
|
||||
icon: 'pi pi-id-card'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_APPL_STATUS'],
|
||||
route: '/admin/set-status',
|
||||
label: __('Gestione Stato Domanda', 'gepafin'),
|
||||
subtitle: __('Modifica lo stato delle domande', 'gepafin'),
|
||||
icon: 'pi pi-list'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_AMENDMENT_REOPEN'],
|
||||
route: '/admin/amendment-reopen',
|
||||
label: __('Riapri Integrazione', 'gepafin'),
|
||||
subtitle: __('Riapri un\'integrazione chiusa', 'gepafin'),
|
||||
icon: 'pi pi-refresh'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_AMENDMENT_EXTEND'],
|
||||
route: '/admin/amendment-extend',
|
||||
label: __('Estendi Integrazione', 'gepafin'),
|
||||
subtitle: __('Estendi la scadenza di un\'integrazione', 'gepafin'),
|
||||
icon: 'pi pi-calendar-plus'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_APPL_VIEW_DELETED', 'ROOT_MANAGE_APPL_DELETE_CONFIRM', 'ROOT_MANAGE_APPL_DELETE'],
|
||||
route: '/admin/elimina-domande',
|
||||
label: __('Elimina Domande', 'gepafin'),
|
||||
subtitle: __('Gestione eliminazione domande', 'gepafin'),
|
||||
icon: 'pi pi-trash'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_VIEW_LOG'],
|
||||
route: '/admin/log',
|
||||
label: __('Log Operazioni', 'gepafin'),
|
||||
subtitle: __('Storico delle operazioni amministrative', 'gepafin'),
|
||||
icon: 'pi pi-history'
|
||||
},
|
||||
{
|
||||
permission: ['ROOT_MANAGE_PEC_SEND'],
|
||||
route: '/admin/send-pec',
|
||||
label: __('Invio PEC Massivo', 'gepafin'),
|
||||
subtitle: __('Invia PEC a più destinatari tramite file CSV', 'gepafin'),
|
||||
icon: 'pi pi-envelope'
|
||||
}
|
||||
];
|
||||
|
||||
const Admin = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
|
||||
const hasNdg = intersection(permissions, ['ROOT_MANAGE_NDG']).length > 0;
|
||||
const hasApplStatus = intersection(permissions, ['ROOT_MANAGE_APPL_STATUS']).length > 0;
|
||||
const hasAmendmentReopen = intersection(permissions, ['ROOT_MANAGE_AMENDMENT_REOPEN']).length > 0;
|
||||
const hasAmendmentExtend = intersection(permissions, ['ROOT_MANAGE_AMENDMENT_EXTEND']).length > 0;
|
||||
const hasApplDelete = intersection(permissions, [
|
||||
'ROOT_MANAGE_APPL_VIEW_DELETED',
|
||||
'ROOT_MANAGE_APPL_DELETE_CONFIRM',
|
||||
'ROOT_MANAGE_APPL_DELETE'
|
||||
]).length > 0;
|
||||
|
||||
const canViewDeleted = intersection(permissions, ['ROOT_MANAGE_APPL_VIEW_DELETED']).length > 0;
|
||||
const canDeleteConfirm = intersection(permissions, ['ROOT_MANAGE_APPL_DELETE_CONFIRM']).length > 0;
|
||||
const canDelete = intersection(permissions, ['ROOT_MANAGE_APPL_DELETE']).length > 0;
|
||||
const visibleItems = navItems.filter(
|
||||
(item) => intersection(permissions, item.permission).length > 0
|
||||
);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader"><h1>{__('Admin', 'gepafin')}</h1></div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasNdg && <><ManageNdgSection/><div className="appPage__spacer"></div></>}
|
||||
{hasApplStatus && <><ManageApplStatusSection/><div className="appPage__spacer"></div></>}
|
||||
{hasAmendmentReopen && <><ManageAmendmentReopenSection/><div className="appPage__spacer"></div></>}
|
||||
{hasAmendmentExtend && <><ManageAmendmentExtendSection/><div className="appPage__spacer"></div></>}
|
||||
{hasApplDelete && <><ManageApplDeleteSection
|
||||
canViewDeleted={canViewDeleted}
|
||||
canDeleteConfirm={canDeleteConfirm}
|
||||
canDelete={canDelete}
|
||||
/><div className="appPage__spacer"></div></>}
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
|
||||
{visibleItems.map((item) => (
|
||||
<Card
|
||||
key={item.route}
|
||||
title={<span><i className={item.icon} style={{ marginRight: '0.5rem' }}/>{item.label}</span>}
|
||||
subTitle={item.subtitle}
|
||||
style={{ width: '280px', cursor: 'pointer', padding: '0.5rem' }}
|
||||
onClick={() => navigate(item.route)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
35
src/pages/AdminAmendmentExtend/index.js
Normal file
35
src/pages/AdminAmendmentExtend/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageAmendmentExtendSection from '../Admin/components/ManageAmendmentExtendSection';
|
||||
|
||||
const AdminAmendmentExtend = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_AMENDMENT_EXTEND']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Estendi Integrazione', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageAmendmentExtendSection/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminAmendmentExtend;
|
||||
35
src/pages/AdminAmendmentReopen/index.js
Normal file
35
src/pages/AdminAmendmentReopen/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageAmendmentReopenSection from '../Admin/components/ManageAmendmentReopenSection';
|
||||
|
||||
const AdminAmendmentReopen = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_AMENDMENT_REOPEN']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Riapri Integrazione', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageAmendmentReopenSection/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminAmendmentReopen;
|
||||
48
src/pages/AdminEliminaDomande/index.js
Normal file
48
src/pages/AdminEliminaDomande/index.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageApplDeleteSection from '../Admin/components/ManageApplDeleteSection';
|
||||
|
||||
const DELETE_PERMISSIONS = [
|
||||
'ROOT_MANAGE_APPL_VIEW_DELETED',
|
||||
'ROOT_MANAGE_APPL_DELETE_CONFIRM',
|
||||
'ROOT_MANAGE_APPL_DELETE'
|
||||
];
|
||||
|
||||
const AdminEliminaDomande = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, DELETE_PERMISSIONS).length > 0;
|
||||
const canViewDeleted = intersection(permissions, ['ROOT_MANAGE_APPL_VIEW_DELETED']).length > 0;
|
||||
const canDeleteConfirm = intersection(permissions, ['ROOT_MANAGE_APPL_DELETE_CONFIRM']).length > 0;
|
||||
const canDelete = intersection(permissions, ['ROOT_MANAGE_APPL_DELETE']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Elimina Domande', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageApplDeleteSection
|
||||
canViewDeleted={canViewDeleted}
|
||||
canDeleteConfirm={canDeleteConfirm}
|
||||
canDelete={canDelete}
|
||||
/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminEliminaDomande;
|
||||
244
src/pages/AdminLog/index.js
Normal file
244
src/pages/AdminLog/index.js
Normal file
@@ -0,0 +1,244 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// api
|
||||
import AdminService from '../../service/admin-service';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Toast } from 'primereact/toast';
|
||||
|
||||
const buildDiffRows = (oldData, newData) => {
|
||||
const keys = Array.from(new Set([
|
||||
...Object.keys(oldData || {}),
|
||||
...Object.keys(newData || {})
|
||||
]));
|
||||
return keys.map((key) => ({
|
||||
key,
|
||||
old: oldData ? String(oldData[key] ?? '') : '',
|
||||
new: newData ? String(newData[key] ?? '') : ''
|
||||
}));
|
||||
};
|
||||
|
||||
const AdminLog = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const toast = useRef(null);
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_VIEW_LOG']).length > 0;
|
||||
|
||||
const [callId, setCallId] = useState('');
|
||||
const [userId, setUserId] = useState('');
|
||||
const [dateFrom, setDateFrom] = useState(null);
|
||||
const [dateTo, setDateTo] = useState(null);
|
||||
const [items, setItems] = useState(null);
|
||||
const [totalRecordsNum, setTotalRecordsNum] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [lazyState, setLazyState] = useState({ first: 0, rows: 10, page: 0 });
|
||||
|
||||
const [detailRow, setDetailRow] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
const formatDate = (date) => {
|
||||
if (!date) return undefined;
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
const validate = () => {
|
||||
if ((dateFrom && !dateTo) || (!dateFrom && dateTo)) {
|
||||
toast.current.show({
|
||||
severity: 'warn',
|
||||
summary: __('Attenzione', 'gepafin'),
|
||||
detail: __('Inserire sia la data di inizio che la data di fine.', 'gepafin')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (dateFrom && dateTo && dateFrom > dateTo) {
|
||||
toast.current.show({
|
||||
severity: 'warn',
|
||||
summary: __('Attenzione', 'gepafin'),
|
||||
detail: __('La data di inizio non può essere superiore alla data di fine.', 'gepafin')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const fetchData = (page = 0, rows = lazyState.rows) => {
|
||||
if (!validate()) return;
|
||||
setLoading(true);
|
||||
|
||||
const queryParams = [
|
||||
['page', page + 1],
|
||||
['limit', rows]
|
||||
];
|
||||
if (callId) queryParams.push(['call_id', callId]);
|
||||
if (userId) queryParams.push(['user_id', userId]);
|
||||
if (dateFrom) queryParams.push(['date_from', formatDate(dateFrom)]);
|
||||
if (dateTo) queryParams.push(['date_to', formatDate(dateTo)]);
|
||||
|
||||
AdminService.getAdminLog(
|
||||
(resp) => {
|
||||
if (resp && resp.status === 'ok') {
|
||||
setItems(resp.records || []);
|
||||
setTotalRecordsNum(resp.totalRecords || 0);
|
||||
}
|
||||
setLoading(false);
|
||||
},
|
||||
() => { setLoading(false); },
|
||||
queryParams
|
||||
);
|
||||
};
|
||||
|
||||
const onPage = (event) => {
|
||||
setLazyState(event);
|
||||
fetchData(event.page, event.rows);
|
||||
};
|
||||
|
||||
const azioniTemplate = (row) => (
|
||||
<Button
|
||||
size="small"
|
||||
label={__('Mostra dettagli', 'gepafin')}
|
||||
icon="pi pi-eye"
|
||||
onClick={() => setDetailRow(row)}
|
||||
/>
|
||||
);
|
||||
|
||||
const userTemplate = (row) => {
|
||||
return `${row.utente.email}`;
|
||||
}
|
||||
|
||||
return <div className="appPage">
|
||||
<Toast ref={toast}/>
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Log Operazioni', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '1rem', marginBottom: '1rem' }}>
|
||||
<div className="formLayout__col">
|
||||
<label htmlFor="callId">{__('ID Bando', 'gepafin')}</label>
|
||||
<InputText
|
||||
id="callId"
|
||||
value={callId}
|
||||
onChange={(e) => setCallId(e.target.value)}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="formLayout__col">
|
||||
<label htmlFor="userId">{__('ID Utente', 'gepafin')}</label>
|
||||
<InputText
|
||||
id="userId"
|
||||
value={userId}
|
||||
onChange={(e) => setUserId(e.target.value)}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="formLayout__col">
|
||||
<label htmlFor="dateFrom">{__('Data da', 'gepafin')}</label>
|
||||
<Calendar
|
||||
id="dateFrom"
|
||||
value={dateFrom}
|
||||
onChange={(e) => setDateFrom(e.value)}
|
||||
dateFormat="dd/mm/yy"
|
||||
showIcon
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="formLayout__col">
|
||||
<label htmlFor="dateTo">{__('Data a', 'gepafin')}</label>
|
||||
<Calendar
|
||||
id="dateTo"
|
||||
value={dateTo}
|
||||
onChange={(e) => setDateTo(e.value)}
|
||||
dateFormat="dd/mm/yy"
|
||||
showIcon
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
label={__('Cerca', 'gepafin')}
|
||||
icon="pi pi-search"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setLazyState((s) => ({ ...s, first: 0, page: 0 }));
|
||||
fetchData(0);
|
||||
}}
|
||||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection__table">
|
||||
<DataTable
|
||||
value={items}
|
||||
lazy
|
||||
paginator
|
||||
first={lazyState.first}
|
||||
rows={lazyState.rows}
|
||||
totalRecords={totalRecordsNum}
|
||||
onPage={onPage}
|
||||
loading={loading}
|
||||
emptyMessage={__('Nessun risultato trovato.', 'gepafin')}
|
||||
>
|
||||
<Column field="user_action_id" header={__('ID', 'gepafin')}/>
|
||||
<Column field="call_id" header={__('ID Bando', 'gepafin')}/>
|
||||
<Column field="periodo" header={__('Periodo', 'gepafin')}/>
|
||||
<Column header={__('Utente', 'gepafin')} body={userTemplate}/>
|
||||
<Column field="action_context" header={__('Azione', 'gepafin')}/>
|
||||
<Column header={__('Azioni', 'gepafin')} body={azioniTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
header={__('Dettagli operazione', 'gepafin')}
|
||||
visible={!!detailRow}
|
||||
style={{ width: '80vw' }}
|
||||
onHide={() => setDetailRow(null)}
|
||||
>
|
||||
{detailRow && (detailRow.version_history || []).map((vh, idx) => (
|
||||
<div key={vh.version_history_id ?? idx} style={{ marginBottom: '1.5rem' }}>
|
||||
<h3 style={{ marginBottom: '0.5rem' }}>
|
||||
{vh.table_name} — {vh.version_history_action_type}
|
||||
</h3>
|
||||
<DataTable
|
||||
value={buildDiffRows(vh.old_data, vh.new_data)}
|
||||
size="small"
|
||||
scrollable
|
||||
scrollHeight="300px"
|
||||
emptyMessage={__('Nessun dato.', 'gepafin')}
|
||||
>
|
||||
<Column field="key" header={__('Campo', 'gepafin')} style={{ width: '30%' }}/>
|
||||
<Column field="old" header={__('Vecchio valore', 'gepafin')} style={{ width: '35%' }}/>
|
||||
<Column field="new" header={__('Nuovo valore', 'gepafin')} style={{ width: '35%' }}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
))}
|
||||
</Dialog>
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminLog;
|
||||
35
src/pages/AdminSendPec/index.js
Normal file
35
src/pages/AdminSendPec/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageSendPecSection from '../Admin/components/ManageSendPecSection';
|
||||
|
||||
const AdminSendPec = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_PEC_SEND']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Invio PEC Massivo', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageSendPecSection/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminSendPec;
|
||||
35
src/pages/AdminSetNdg/index.js
Normal file
35
src/pages/AdminSetNdg/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageNdgSection from '../Admin/components/ManageNdgSection';
|
||||
|
||||
const AdminSetNdg = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_NDG']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Gestione NDG', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageNdgSection/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminSetNdg;
|
||||
35
src/pages/AdminSetStatus/index.js
Normal file
35
src/pages/AdminSetStatus/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { intersection } from 'ramda';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStoreValue } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import ManageApplStatusSection from '../Admin/components/ManageApplStatusSection';
|
||||
|
||||
const AdminSetStatus = () => {
|
||||
const permissions = useStoreValue('getPermissions');
|
||||
const navigate = useNavigate();
|
||||
const hasPermission = intersection(permissions, ['ROOT_MANAGE_APPL_STATUS']).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasPermission) navigate('/admin');
|
||||
}, [hasPermission]);
|
||||
|
||||
return <div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Gestione Stato Domanda', 'gepafin')}</h1>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
<div className="appPageSection__actions">
|
||||
<Button type="button" outlined label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" onClick={() => navigate('/admin')}/>
|
||||
</div>
|
||||
<div className="appPage__spacer"></div>
|
||||
{hasPermission && <ManageApplStatusSection/>}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default AdminSetStatus;
|
||||
@@ -57,6 +57,13 @@ import ResetPasswordAdmin from './pages/ResetPasswordAdmin';
|
||||
import DashboardBeneficiarioConfidi from './pages/DashboardBeneficiarioConfidi';
|
||||
import DashboardDirector from './pages/DashboardDirector';
|
||||
import Admin from './pages/Admin';
|
||||
import AdminSetNdg from './pages/AdminSetNdg';
|
||||
import AdminSetStatus from './pages/AdminSetStatus';
|
||||
import AdminAmendmentReopen from './pages/AdminAmendmentReopen';
|
||||
import AdminAmendmentExtend from './pages/AdminAmendmentExtend';
|
||||
import AdminEliminaDomande from './pages/AdminEliminaDomande';
|
||||
import AdminLog from './pages/AdminLog';
|
||||
import AdminSendPec from './pages/AdminSendPec';
|
||||
|
||||
const routes = ({ role, chosenCompanyId }) => {
|
||||
|
||||
@@ -291,6 +298,27 @@ const routes = ({ role, chosenCompanyId }) => {
|
||||
<Route path="/admin" element={<DefaultLayout>
|
||||
<Admin/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/set-ndg" element={<DefaultLayout>
|
||||
<AdminSetNdg/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/set-status" element={<DefaultLayout>
|
||||
<AdminSetStatus/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/amendment-reopen" element={<DefaultLayout>
|
||||
<AdminAmendmentReopen/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/amendment-extend" element={<DefaultLayout>
|
||||
<AdminAmendmentExtend/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/elimina-domande" element={<DefaultLayout>
|
||||
<AdminEliminaDomande/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/log" element={<DefaultLayout>
|
||||
<AdminLog/>
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/admin/send-pec" element={<DefaultLayout>
|
||||
<AdminSendPec/>
|
||||
</DefaultLayout>}/>
|
||||
</Route>
|
||||
<Route exact path="/reset-password" element={<ResetPassword/>}/>
|
||||
<Route exact path="/reset-password-admin" element={<ResetPasswordAdmin/>}/>
|
||||
|
||||
@@ -19,4 +19,12 @@ export default class AdminService {
|
||||
static doAmendmentExtend = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${API_ADMIN_BASE_URL}/extend-days`, body, callback, errCallback, queryParams);
|
||||
};
|
||||
|
||||
static doSendPec = (body, callback, errCallback, queryParams) => {
|
||||
NetworkService.post(`${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);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user