- saving changes;
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { is, uniq } from 'ramda';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
// tools
|
||||
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
|
||||
import getBandoLabel from '../../../../helpers/getBandoLabel';
|
||||
import getDateFromISOstring from '../../../../helpers/getDateFromISOstring';
|
||||
|
||||
// api
|
||||
import CompanyDocumentsService from '../../../../service/company-documents-service';
|
||||
|
||||
// components
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
|
||||
import translationStrings from '../../../../translationStringsForComponents';
|
||||
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
|
||||
|
||||
const DocumentsTable = ({ type, reload = 0 }) => {
|
||||
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||
const [docs, setDocs] = useState([]);
|
||||
const [filters, setFilters] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [statuses, setStatuses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && chosenCompanyId && chosenCompanyId !== 0 && reload !== 0) {
|
||||
setLoading(true);
|
||||
CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [
|
||||
['documentType', type]
|
||||
]);
|
||||
}
|
||||
}, [chosenCompanyId, reload]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [
|
||||
['documentType', type]
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const getCallback = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
setDocs(getFormattedData(resp.data));
|
||||
setStatuses(uniq(resp.data.map(o => o.status)))
|
||||
initFilters();
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errGetCallbacks = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const getFormattedData = (data) => {
|
||||
return data.map((d) => {
|
||||
d.callEndDate = is(String, d.callEndDate) ? new Date(d.callEndDate) : (d.callEndDate ? d.callEndDate : '');
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
name: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
createdDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
expirationDate: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="appTableHeader">
|
||||
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined
|
||||
onClick={clearFilter}/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateCreatedBodyTemplate = (rowData) => {
|
||||
return getDateFromISOstring(rowData.createdDate);
|
||||
};
|
||||
const dateExpirationBodyTemplate = (rowData) => {
|
||||
return getDateFromISOstring(rowData.expirationDate);
|
||||
};
|
||||
|
||||
const dateFilterTemplate = (options) => {
|
||||
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
|
||||
};
|
||||
|
||||
const catBodyTemplate = (rowData) => {
|
||||
return rowData.category.categoryName;
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return <ProperBandoLabel status={rowData.status}/>;
|
||||
};
|
||||
|
||||
const statusFilterTemplate = (options) => {
|
||||
return <Dropdown value={options.value} options={statuses}
|
||||
onChange={(e) => options.filterCallback(e.value, options.index)}
|
||||
itemTemplate={statusItemTemplate} placeholder={__('Scegli uno', 'gepafin')}
|
||||
className="p-column-filter"
|
||||
showClear/>;
|
||||
};
|
||||
|
||||
const statusItemTemplate = (option) => {
|
||||
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)}/>;
|
||||
};
|
||||
|
||||
const handleDeleteFile = (id) => {
|
||||
setLoading(true);
|
||||
CompanyDocumentsService.deleteCompanyDocument(id,(resp) => deleteCallback(resp, id), errDeleteCallback)
|
||||
}
|
||||
|
||||
const deleteCallback = (resp, deletedId) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
setDocs(docs.filter(o => o.id !== deletedId));
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errDeleteCallback = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const actionsBodyTemplate = (rowData) => {
|
||||
return <div className="appPageSection__iconActions">
|
||||
<Button icon="pi pi-eye" rounded
|
||||
onClick={() => {
|
||||
window.open(rowData.filePath, '_blank').focus()
|
||||
}}
|
||||
outlined severity="info"
|
||||
aria-label={__('Mostra', 'gepafin')}/>
|
||||
{/*<Button icon="pi pi-sync" rounded
|
||||
onClick={() => {}}
|
||||
outlined severity="success"
|
||||
aria-label={__('Aggiorna', 'gepafin')}/>*/}
|
||||
<ConfirmPopup/>
|
||||
<Button icon="pi pi-trash" rounded
|
||||
onClick={(event) => confirmDelete(event, rowData.id)}
|
||||
outlined severity="danger"
|
||||
aria-label={__('Cancella', 'gepafin')}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const confirmDelete = (event, id) => {
|
||||
confirmPopup({
|
||||
target: event.currentTarget,
|
||||
message: __('Sei sicuro di voler rimuovere il file?', 'gepafin'),
|
||||
acceptLabel: __('Si', 'gepafin'),
|
||||
icon: 'pi pi-info-circle',
|
||||
defaultFocus: 'reject',
|
||||
acceptClassName: 'p-button-danger',
|
||||
accept: () => {
|
||||
handleDeleteFile(id);
|
||||
},
|
||||
reject: () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return (
|
||||
<div className="appPageSection__table">
|
||||
<DataTable value={docs} paginator showGridlines rows={5} loading={loading} dataKey="id"
|
||||
filters={filters} stripedRows removableSort
|
||||
header={header}
|
||||
onFilter={(e) => setFilters(e.filters)}>
|
||||
<Column field="name"
|
||||
header={__('Nome documento', 'gepafin')}
|
||||
filter filterField="name"
|
||||
filterPlaceholder={__('Cerca per nome', 'gepafin')}
|
||||
style={{ minWidth: '12rem' }}/>
|
||||
<Column body={catBodyTemplate} header={__('Categoria', 'gepafin')}
|
||||
style={{ minWidth: '8rem' }}/>
|
||||
<Column header={__('Data caricamento', 'gepafin')}
|
||||
filterField="createdDate" dataType="date"
|
||||
style={{ minWidth: '7rem' }}
|
||||
body={dateCreatedBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column header={__('Data scadenza', 'gepafin')}
|
||||
filterField="expirationDate" dataType="date"
|
||||
style={{ minWidth: '7rem' }}
|
||||
body={dateExpirationBodyTemplate} filter filterElement={dateFilterTemplate}/>
|
||||
<Column field="status" header={__('Stato', 'gepafin')}
|
||||
filterMenuStyle={{ width: '14rem' }}
|
||||
style={{ width: '120px' }} body={statusBodyTemplate}
|
||||
filterElement={statusFilterTemplate}/>
|
||||
<Column header={__('Azioni', 'gepafin')}
|
||||
body={actionsBodyTemplate}/>
|
||||
</DataTable>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentsTable;
|
||||
@@ -1,23 +1,138 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { pathOr } from 'ramda';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import { wrap } from 'object-path-immutable';
|
||||
import { isEmpty, isNil } from 'ramda';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../store';
|
||||
// api
|
||||
import DocumentCategoryService from '../../service/document-category-service';
|
||||
|
||||
// components
|
||||
import DocumentsTable from './components/DocumentsTable';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { useStore } from '../../store';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { FileUpload } from 'primereact/fileupload';
|
||||
import formatDateString from '../../helpers/formatDateString';
|
||||
import CompanyDocumentsService from '../../service/company-documents-service';
|
||||
|
||||
|
||||
const DocumentsBeneficiary = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const chosenCompanyId = useStore().main.chosenCompanyId();
|
||||
const [isVisibleAddNewDialog, setIsVisibleAddNewDialog] = useState(false);
|
||||
const [categories, setCategories] = useState(false);
|
||||
const [newFileData, setNewFileData] = useState({});
|
||||
const [fileAttached, setFileAttached] = useState([]);
|
||||
const [reloadHash, setReloadHash] = useState(0);
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
|
||||
const getStats = (resp) => {}
|
||||
const onCreateNew = useCallback((type) => {
|
||||
const newData = wrap({})
|
||||
.set(['documentType'], type)
|
||||
.set(['documentCategoryId'], 0)
|
||||
.set(['expirationDate'], '')
|
||||
.set(['name'], '')
|
||||
.value();
|
||||
|
||||
const errGetStats = () => {}
|
||||
setNewFileData(newData);
|
||||
setFileAttached([]);
|
||||
setIsVisibleAddNewDialog(true);
|
||||
}, [newFileData, chosenCompanyId]);
|
||||
|
||||
const hideAddNewDialog = () => {
|
||||
setIsVisibleAddNewDialog(false);
|
||||
const newData = wrap({})
|
||||
.set(['documentType'], '')
|
||||
.set(['documentCategoryId'], 0)
|
||||
.set(['expirationDate'], '')
|
||||
.set(['name'], '')
|
||||
.value();
|
||||
setNewFileData(newData);
|
||||
setFileAttached([]);
|
||||
}
|
||||
|
||||
const headerAddNewDialog = () => {
|
||||
return <span>{__('Aggiungi file', 'gepafin')}</span>
|
||||
}
|
||||
|
||||
const footerAddNewDialog = () => {
|
||||
return <div>
|
||||
<Button type="button" label={__('Anulla', 'gepafin')} onClick={hideAddNewDialog} outlined/>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={loading || !isValidForm()}
|
||||
label={__('Salva', 'gepafin')} onClick={doAddNew}/>
|
||||
</div>
|
||||
}
|
||||
|
||||
const isValidForm = useCallback(() => {
|
||||
return !isEmpty(fileAttached) && !Object.keys(newFileData).filter(k => isInvalidField(newFileData, k)
|
||||
|| newFileData[k] === 0).length
|
||||
}, [fileAttached, newFileData]);
|
||||
|
||||
const doAddNew = useCallback(() => {
|
||||
const submitData = {
|
||||
...newFileData,
|
||||
expirationDate: formatDateString(newFileData.expirationDate)
|
||||
}
|
||||
const queryParams = Object.keys(submitData).map(k => [
|
||||
k, submitData[k]
|
||||
]);
|
||||
|
||||
if (!isEmpty(fileAttached)) {
|
||||
const formData = new FormData()
|
||||
for (const file of fileAttached) {
|
||||
formData.append('file', file)
|
||||
}
|
||||
setLoading(true);
|
||||
CompanyDocumentsService.uploadCompanyDocument(chosenCompanyId, formData, uploadDoc, errUploadDoc, queryParams);
|
||||
}
|
||||
}, [fileAttached, newFileData, chosenCompanyId]);
|
||||
|
||||
const uploadDoc = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
hideAddNewDialog();
|
||||
setReloadHash(new Date().getTime())
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errUploadDoc = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const isInvalidField = (data, key) => isEmpty(data[key]) || isNil(data[key]);
|
||||
|
||||
const onUpdateFieldValue = useCallback((value, name) => {
|
||||
const newData = wrap(newFileData).set([name], value).value();
|
||||
setNewFileData(newData);
|
||||
}, [newFileData]);
|
||||
|
||||
const onFileSelect = (file) => {
|
||||
setFileAttached(file.files);
|
||||
}
|
||||
|
||||
const getCategories = (resp) => {
|
||||
if (resp.status === 'SUCCESS') {
|
||||
setCategories(resp.data.map(o => ({value: o.id, label: o.description})));
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
const errGetCategories = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
}, [chosenCompanyId]);
|
||||
setLoading(true);
|
||||
DocumentCategoryService.getCategories(getCategories, errGetCategories)
|
||||
}, []);
|
||||
|
||||
return(
|
||||
<div className="appPage">
|
||||
@@ -28,17 +143,86 @@ const DocumentsBeneficiary = () => {
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection statsBigBadges">
|
||||
<h2>{__('Documenti del rappresentante legale', 'gepafin')}</h2>
|
||||
|
||||
<h2>
|
||||
{__('Documenti del rappresentante legale', 'gepafin')}
|
||||
<Button
|
||||
onClick={() => onCreateNew('PERSONAL_DOCUMENT')}
|
||||
size="small"
|
||||
label={__('Aggiungi nuovo')} icon="pi pi-plus" iconPos="right"/>
|
||||
</h2>
|
||||
<DocumentsTable type="PERSONAL_DOCUMENT" reload={reloadHash}/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection statsBigBadges">
|
||||
<h2>{__('Documenti dell\'azienda', 'gepafin')}</h2>
|
||||
|
||||
<h2>
|
||||
{__('Documenti dell\'azienda', 'gepafin')}
|
||||
<Button
|
||||
onClick={() => onCreateNew('COMPANY_DOCUMENT')}
|
||||
size="small"
|
||||
label={__('Aggiungi nuovo')} icon="pi pi-plus" iconPos="right"/>
|
||||
</h2>
|
||||
<DocumentsTable type="COMPANY_DOCUMENT" reload={reloadHash}/>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
visible={isVisibleAddNewDialog}
|
||||
modal
|
||||
header={headerAddNewDialog}
|
||||
footer={footerAddNewDialog}
|
||||
style={{ maxWidth: '600px', width: '100%' }}
|
||||
onHide={hideAddNewDialog}>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isInvalidField(newFileData, 'name') })}>
|
||||
{__('Nome', 'gepafin')}*
|
||||
</label>
|
||||
<InputText value={newFileData.name}
|
||||
invalid={isInvalidField(newFileData, 'name')}
|
||||
onChange={(e) => onUpdateFieldValue(e.target.value, 'name')}/>
|
||||
</div>
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isInvalidField(newFileData, 'documentCategoryId') || newFileData.documentCategoryId === 0 })}>
|
||||
{__('Categoria', 'gepafin')}*
|
||||
</label>
|
||||
<Dropdown
|
||||
value={newFileData.documentCategoryId}
|
||||
invalid={isEmpty(newFileData.documentCategoryId) || isNil(newFileData.documentCategoryId) || newFileData.documentCategoryId === 0}
|
||||
onChange={(e) => onUpdateFieldValue(e.value, 'documentCategoryId')}
|
||||
options={categories}
|
||||
optionLabel="label"
|
||||
optionValue="value"/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newFileData.expirationDate) || isNil(newFileData.expirationDate) })}>
|
||||
{__('Scadenza', 'gepafin')}*
|
||||
</label>
|
||||
<Calendar
|
||||
value={newFileData.expirationDate}
|
||||
minDate={tomorrow}
|
||||
invalid={isEmpty(newFileData.expirationDate) || isNil(newFileData.expirationDate) || newFileData.expirationDate === 0}
|
||||
onChange={(e) => onUpdateFieldValue(e.value, 'expirationDate')}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="appForm__cols">
|
||||
<div className="appForm__field">
|
||||
<label
|
||||
className={classNames({ 'p-error': isEmpty(newFileData.file) || isNil(newFileData.expirationDate) })}>
|
||||
{__('File', 'gepafin')}*
|
||||
</label>
|
||||
<FileUpload
|
||||
mode="basic"
|
||||
name="file"
|
||||
onSelect={onFileSelect}/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user