Merge branch 'develop'

This commit is contained in:
Vitalii Kiiko
2026-03-27 14:28:15 +01:00
11 changed files with 316 additions and 105 deletions

View File

@@ -3,10 +3,12 @@ version: 0.2
phases: phases:
install: install:
runtime-versions: runtime-versions:
nodejs: 20 nodejs: 20
commands:
- npm install
build: build:
commands: commands:
- npm install && npm run build:dev - npm run build:dev
artifacts: artifacts:
files: files:
- '**/*' - '**/*'

View File

@@ -4,10 +4,12 @@ phases:
install: install:
runtime-versions: runtime-versions:
nodejs: 20 nodejs: 20
commands:
- npm install
build: build:
commands: commands:
- npm install && npm run build:prod - npm run build:prod
artifacts: artifacts:
files: files:
- '**/*' - '**/*'
base-directory: 'build' base-directory: 'build'

View File

@@ -65,8 +65,8 @@
"start:dev": "cp environments/dev/* public/loaded-files && rm public/loaded-files/dev.env && cp environments/dev/dev.env .env && PORT=8000 react-scripts start --mode development", "start:dev": "cp environments/dev/* public/loaded-files && rm public/loaded-files/dev.env && cp environments/dev/dev.env .env && PORT=8000 react-scripts start --mode development",
"start:prod": "cp environments/prod/* public/loaded-files && rm public/loaded-files/prod.env && cp environments/prod/prod.env .env && react-scripts start --mode production", "start:prod": "cp environments/prod/* public/loaded-files && rm public/loaded-files/prod.env && cp environments/prod/prod.env .env && react-scripts start --mode production",
"build": "react-scripts build", "build": "react-scripts build",
"build:dev": "cp environments/dev/* public/loaded-files && rm public/loaded-files/dev.env && cp environments/dev/dev.env .env && react-scripts build --mode development", "build:dev": "cp environments/dev/* public/loaded-files && rm public/loaded-files/dev.env && cp environments/dev/dev.env .env && GENERATE_SOURCEMAP=false NODE_OPTIONS=--max-old-space-size=1536 react-scripts build --mode development",
"build:prod": "cp environments/prod/* public/loaded-files && rm public/loaded-files/prod.env && cp environments/prod/prod.env .env && react-scripts build --mode production", "build:prod": "cp environments/prod/* public/loaded-files && rm public/loaded-files/prod.env && cp environments/prod/prod.env .env && GENERATE_SOURCEMAP=false NODE_OPTIONS=--max-old-space-size=1536 react-scripts build --mode production",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"make-pot": "wpi18n makepot --domain-path=languages --domain=gepafin" "make-pot": "wpi18n makepot --domain-path=languages --domain=gepafin"

View File

@@ -4,6 +4,24 @@ import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'; import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';
import '@univerjs/preset-sheets-core/lib/index.css'; import '@univerjs/preset-sheets-core/lib/index.css';
const TAG_RE = /^\{\{gepafin_field:[^|]+\|[^}]+}}$/;
const buildTagMap = (workbookData) => {
const map = {};
if (!workbookData?.sheets) return map;
const sheetId = workbookData.sheetOrder?.[0];
const sheet = sheetId ? workbookData.sheets[sheetId] : Object.values(workbookData.sheets)[0];
if (!sheet?.cellData) return map;
Object.entries(sheet.cellData).forEach(([r, row]) => {
Object.entries(row).forEach(([c, cell]) => {
if (typeof cell.f === 'string' && TAG_RE.test(cell.f)) {
map[`${r}:${c}`] = { v: cell.v, f: cell.f };
}
});
});
return map;
};
const parseWorkbook = (val) => { const parseWorkbook = (val) => {
if (!val) return null; if (!val) return null;
if (typeof val === 'object' && val.sheets) return val; if (typeof val === 'object' && val.sheets) return val;
@@ -23,6 +41,8 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => {
const univerRef = useRef(null); const univerRef = useRef(null);
const univerAPIRef = useRef(null); const univerAPIRef = useRef(null);
const saveTimerRef = useRef(null); const saveTimerRef = useRef(null);
const isRestoringRef = useRef(false);
const tagCellMapRef = useRef({});
useEffect(() => { useEffect(() => {
if (!containerRef.current) return; if (!containerRef.current) return;
@@ -43,8 +63,40 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => {
univerAPIRef.current = univerAPI; univerAPIRef.current = univerAPI;
const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' }; const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' };
tagCellMapRef.current = buildTagMap(initialData);
univerAPI.createWorkbook(initialData); univerAPI.createWorkbook(initialData);
const restoreTagCells = () => {
if (isRestoringRef.current) return;
const wb = univerAPIRef.current?.getActiveWorkbook();
if (!wb) return;
const sheet = wb.getActiveSheet();
if (!sheet) return;
const saved = wb.save();
if (!saved?.sheets) return;
const sheetId = saved.sheetOrder?.[0];
const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0];
if (!sheetData?.cellData) return;
const restorations = [];
Object.entries(sheetData.cellData).forEach(([r, row]) => {
Object.entries(row).forEach(([c, cell]) => {
if (typeof cell.v === 'string' && TAG_RE.test(cell.v)) {
const orig = tagCellMapRef.current[`${r}:${c}`];
if (orig) restorations.push({ r: +r, c: +c, v: orig.v, f: orig.f });
}
});
});
if (restorations.length === 0) return;
isRestoringRef.current = true;
restorations.forEach(({ r, c, v, f }) => {
sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]);
});
isRestoringRef.current = false;
};
let restoreTimer;
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, () => { univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, () => {
clearTimeout(saveTimerRef.current); clearTimeout(saveTimerRef.current);
saveTimerRef.current = setTimeout(() => { saveTimerRef.current = setTimeout(() => {
@@ -53,10 +105,13 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => {
setDataFn(fieldName, wb.save()); setDataFn(fieldName, wb.save());
} }
}, 300); }, 300);
clearTimeout(restoreTimer);
restoreTimer = setTimeout(restoreTagCells, 80);
}); });
return () => { return () => {
clearTimeout(saveTimerRef.current); clearTimeout(saveTimerRef.current);
clearTimeout(restoreTimer);
if (univerRef.current) { if (univerRef.current) {
univerRef.current.dispose(); univerRef.current.dispose();
univerRef.current = null; univerRef.current = null;

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { Suspense } from 'react';
import { isNil } from 'ramda'; import { isNil } from 'ramda';
import { classNames } from 'primereact/utils'; import { classNames } from 'primereact/utils';
@@ -19,7 +19,7 @@ import Table from './components/Table';
import PasswordField from './components/PasswordField'; import PasswordField from './components/PasswordField';
import CriteriaTable from './components/CriteriaTable'; import CriteriaTable from './components/CriteriaTable';
import FileSelect from './components/FileSelect'; import FileSelect from './components/FileSelect';
import Spreadsheet from './components/Spreadsheet'; const Spreadsheet = React.lazy(() => import('./components/Spreadsheet'));
const FormField = (props) => { const FormField = (props) => {
const fields = { const fields = {
@@ -45,7 +45,9 @@ const FormField = (props) => {
return (!isNil(Comp) return (!isNil(Comp)
? <div className={classNames(['appForm__field', props.type, props.additionalClass])}> ? <div className={classNames(['appForm__field', props.type, props.additionalClass])}>
<Comp {...props} /> <Suspense fallback={null}>
<Comp {...props} />
</Suspense>
</div> </div>
: null : null
) )

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { Suspense, useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { head, is, isEmpty, isNil, uniq } from 'ramda'; import { head, is, isEmpty, isNil, uniq } from 'ramda';
@@ -18,13 +18,13 @@ import { InputSwitch } from 'primereact/inputswitch';
import ElementSettingChips from '../ElementSettingChips'; import ElementSettingChips from '../ElementSettingChips';
import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns'; import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns';
import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv'; import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv';
import ElementSettingSpreadsheet from '../ElementSettingSpreadsheet';
import { mimeTypes } from '../../../../../../configData'; import { mimeTypes } from '../../../../../../configData';
import ElementSettingReportHeader from '../ElementSettingReportHeader'; import ElementSettingReportHeader from '../ElementSettingReportHeader';
import ElementSettingReportEnable from '../ElementSettingReportEnable'; import ElementSettingReportEnable from '../ElementSettingReportEnable';
import getTokens from '../../../../../../helpers/getTokens'; import getTokens from '../../../../../../helpers/getTokens';
const ElementSettingSpreadsheet = React.lazy(() => import('../ElementSettingSpreadsheet'));
const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
const [existingVars, setExistingVars] = useState([]); const [existingVars, setExistingVars] = useState([]);
@@ -159,10 +159,12 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
bandoStatus={bandoStatus} bandoStatus={bandoStatus}
setDataFn={updateDataFn}/> setDataFn={updateDataFn}/>
} else if (setting.name === 'template') { } else if (setting.name === 'template') {
return <ElementSettingSpreadsheet return <Suspense fallback={null}>
value={setting.value} <ElementSettingSpreadsheet
name={setting.name} value={setting.value}
setDataFn={updateDataFn}/>; name={setting.name}
setDataFn={updateDataFn}/>
</Suspense>;
} else if (setting.name === 'formula') { } else if (setting.name === 'formula') {
const isInvalid = invalidFormula(setting.value); const isInvalid = invalidFormula(setting.value);
return <> return <>

View File

@@ -12,6 +12,8 @@ import { useStoreValue } from '../../../../../../store';
// tools // tools
import { xlsxToWorkbookData } from '../../../../../BandoEdit/components/BandoEditFormStep3Excel/xlsxToWorkbookData'; import { xlsxToWorkbookData } from '../../../../../BandoEdit/components/BandoEditFormStep3Excel/xlsxToWorkbookData';
const TAG_RE = /^\{\{gepafin_field:([^|]+)\|([^}]+)}}$/;
const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
const callFormFields = useStoreValue('callFormFields'); const callFormFields = useStoreValue('callFormFields');
const [tagTooltip, setTagTooltip] = useState(null); const [tagTooltip, setTagTooltip] = useState(null);
@@ -19,6 +21,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
const univerRef = useRef(null); const univerRef = useRef(null);
const univerAPIRef = useRef(null); const univerAPIRef = useRef(null);
const formFieldsRef = useRef([]); const formFieldsRef = useRef([]);
const isRestoringRef = useRef(false);
const mousePos = useRef({ x: 0, y: 0 }); const mousePos = useRef({ x: 0, y: 0 });
const fileInputRef = useRef(null); const fileInputRef = useRef(null);
@@ -60,11 +63,54 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
univerRef.current = univer; univerRef.current = univer;
univerAPIRef.current = univerAPI; univerAPIRef.current = univerAPI;
// Disable adding new sheets // Restore tag cells whose display value was overwritten by raw tag on blur
const restoreTagCells = () => {
if (isRestoringRef.current) return;
const wb = univerAPIRef.current?.getActiveWorkbook();
if (!wb) return;
const sheet = wb.getActiveSheet();
if (!sheet) return;
const saved = wb.save();
if (!saved?.sheets) return;
const sheetId = saved.sheetOrder?.[0];
const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0];
if (!sheetData?.cellData) return;
const restorations = [];
Object.entries(sheetData.cellData).forEach(([r, row]) => {
Object.entries(row).forEach(([c, cell]) => {
const match = typeof cell.v === 'string' && cell.v.match(TAG_RE);
if (match) {
const tagIds = match[1].split(',');
const type = match[2];
const field = formFieldsRef.current.find(f =>
f.ids.some(id => tagIds.includes(String(id)))
);
const displayValue = type === 'value'
? (field?.placeholder || '')
: (field?.label || match[1]);
restorations.push({ r: +r, c: +c, v: displayValue, f: cell.v });
}
});
});
if (restorations.length === 0) return;
isRestoringRef.current = true;
restorations.forEach(({ r, c, v, f }) => {
sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]);
});
isRestoringRef.current = false;
};
let restoreTimer;
// Disable adding new sheets; also schedule tag-cell restoration after each command
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => { univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => {
if (event.id === 'sheet.command.insert-sheet') { if (event.id === 'sheet.command.insert-sheet') {
event.cancel = true; event.cancel = true;
} }
clearTimeout(restoreTimer);
restoreTimer = setTimeout(restoreTagCells, 80);
}); });
// Context menu: "Inserisci variabile GEPAFIN" // Context menu: "Inserisci variabile GEPAFIN"
@@ -113,6 +159,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
setTagTooltip(null); setTagTooltip(null);
} }
}); });
}, []); // refs are stable }, []); // refs are stable
// Keep formFieldsRef in sync with store value // Keep formFieldsRef in sync with store value

View File

@@ -119,7 +119,7 @@ const BuilderElementSettings = ({ closeSettingsFn, callStatus, context }) => {
const chosenElementItemCfg = head(elementItems.filter(o => o.name === chosen.name)); const chosenElementItemCfg = head(elementItems.filter(o => o.name === chosen.name));
let settings = []; let settings = [];
if (chosenElementItemCfg) { if (chosenElementItemCfg && chosenElementItemCfg.settings) {
settings = chosenElementItemCfg.settings.map((o) => { settings = chosenElementItemCfg.settings.map((o) => {
const setting = head(chosen.settings.filter(s => s.name === o.name)); const setting = head(chosen.settings.filter(s => s.name === o.name));
return setting ? klona(setting) : klona(o) return setting ? klona(setting) : klona(o)

View File

@@ -24,8 +24,9 @@ import { Tag } from 'primereact/tag';
import ProperBandoLabel from '../../../../components/ProperBandoLabel'; import ProperBandoLabel from '../../../../components/ProperBandoLabel';
import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup'; import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup';
const DocumentsTable = ({ type, reload = 0 }) => { const DocumentsTable = ({ type, reload = 0, companyId: companyIdProp }) => {
const chosenCompanyId = useStoreValue('chosenCompanyId'); const storedCompanyId = useStoreValue('chosenCompanyId');
const effectiveCompanyId = companyIdProp || storedCompanyId;
const companies = useStoreValue('companies'); const companies = useStoreValue('companies');
const [docs, setDocs] = useState([]); const [docs, setDocs] = useState([]);
const [filters, setFilters] = useState(null); const [filters, setFilters] = useState(null);
@@ -33,22 +34,26 @@ const DocumentsTable = ({ type, reload = 0 }) => {
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
const existingCompany = head(companies.filter(o => o.id === chosenCompanyId)); const shouldFetch = companyIdProp
? !!effectiveCompanyId
: !!head(companies.filter(o => o.id === effectiveCompanyId));
if (!loading && existingCompany && reload !== 0) { if (!loading && shouldFetch && reload !== 0) {
setLoading(true); setLoading(true);
CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [ CompanyDocumentsService.getCompanyDocuments(effectiveCompanyId, getCallback, errGetCallbacks, [
['documentType', type] ['documentType', type]
]); ]);
} }
}, [chosenCompanyId, reload, companies]); }, [effectiveCompanyId, reload, companies]);
useEffect(() => { useEffect(() => {
const existingCompany = head(companies.filter(o => o.id === chosenCompanyId)); const shouldFetch = companyIdProp
? !!effectiveCompanyId
: !!head(companies.filter(o => o.id === effectiveCompanyId));
if (existingCompany) { if (shouldFetch) {
setLoading(true); setLoading(true);
CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [ CompanyDocumentsService.getCompanyDocuments(effectiveCompanyId, getCallback, errGetCallbacks, [
['documentType', type] ['documentType', type]
]); ]);
} }

View File

@@ -1,22 +1,30 @@
import React, { useMemo, useState, useCallback, useEffect, useRef } from 'react'; import React, { useMemo, useState, useCallback, useEffect, useRef } from 'react';
import { useForm, useFieldArray } from 'react-hook-form'; import { useForm, useFieldArray } from 'react-hook-form';
import { isEmpty, head, pluck } from 'ramda'; import { isEmpty, head, isNil } from 'ramda';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { klona } from 'klona'; import { klona } from 'klona';
import { wrap } from 'object-path-immutable';
import { classNames } from 'primereact/utils';
// tools // tools
import uniqid from '../../../../helpers/uniqid'; import uniqid from '../../../../helpers/uniqid';
import formatDateString from '../../../../helpers/formatDateString';
// components // components
import FormField from '../../../../components/FormField'; import FormField from '../../../../components/FormField';
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import { Dialog } from 'primereact/dialog'; import { Dialog } from 'primereact/dialog';
import { Toast } from 'primereact/toast'; import { Toast } from 'primereact/toast';
import CompanyService from '../../../../service/company-service'; import { Dropdown } from 'primereact/dropdown';
import FileSelect from '../../../../components/FormField/components/FileSelect'; import { InputText } from 'primereact/inputtext';
import ApplicationService from '../../../../service/application-service'; import { Calendar } from 'primereact/calendar';
import { FileUpload } from 'primereact/fileupload';
import DocumentsTable from '../../../DocumentsBeneficiary/components/DocumentsTable';
// services
import CompanyDocumentsService from '../../../../service/company-documents-service';
import DocumentCategoryService from '../../../../service/document-category-service';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse'; import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import { storeSet } from '../../../../store';
const EvaluationExtraFiles = ({ const EvaluationExtraFiles = ({
sourceId, sourceId,
@@ -32,9 +40,16 @@ const EvaluationExtraFiles = ({
}) => { }) => {
const [chosen, setChosen] = useState(''); const [chosen, setChosen] = useState('');
const [isVisibleCompanyDocsDialog, setIsVisibleCompanyDocsDialog] = useState(false); const [isVisibleCompanyDocsDialog, setIsVisibleCompanyDocsDialog] = useState(false);
const [companyDocs, setCompanyDocs] = useState([]); const [isVisibleAddDocDialog, setIsVisibleAddDocDialog] = useState(false);
const [companyDocsSelected, setCompanyDocsSelected] = useState([]); const [newDocData, setNewDocData] = useState({});
const [docFileAttached, setDocFileAttached] = useState([]);
const [documentCategories, setDocumentCategories] = useState([]);
const [addDocLoading, setAddDocLoading] = useState(false);
const [reloadHash, setReloadHash] = useState(0);
const toast = useRef(null); const toast = useRef(null);
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
const { const {
control, control,
handleSubmit, handleSubmit,
@@ -107,74 +122,113 @@ const EvaluationExtraFiles = ({
const hideCompanyDocsDialog = () => { const hideCompanyDocsDialog = () => {
setIsVisibleCompanyDocsDialog(false); setIsVisibleCompanyDocsDialog(false);
setCompanyDocsSelected([]);
} }
const footerPreTecEvalDialog = useCallback(() => { const footerCompanyDocsDialog = () => {
return <div> return <div>
<Button type="button" label={__('Annulla', 'gepafin')} onClick={hideCompanyDocsDialog} outlined/> <Button type="button" label={__('Chiudi', 'gepafin')} onClick={hideCompanyDocsDialog} outlined/>
</div>
}
const openAddDocDialog = () => {
setNewDocData({
name: '',
documentCategoryId: 0,
expirationDate: ''
});
setDocFileAttached([]);
setIsVisibleAddDocDialog(true);
}
const hideAddDocDialog = () => {
setIsVisibleAddDocDialog(false);
setNewDocData({});
setDocFileAttached([]);
}
const headerAddDocDialog = () => {
return <span>{__('Aggiungi documento aziendale', 'gepafin')}</span>;
}
const isDocFormValid = useCallback(() => {
return !isEmpty(docFileAttached)
&& !isEmpty(newDocData.name) && !isNil(newDocData.name)
&& newDocData.documentCategoryId !== 0 && !isNil(newDocData.documentCategoryId)
&& !isEmpty(newDocData.expirationDate) && !isNil(newDocData.expirationDate);
}, [docFileAttached, newDocData]);
const footerAddDocDialog = () => {
return <div>
<Button type="button" label={__('Annulla', 'gepafin')} onClick={hideAddDocDialog} outlined/>
<Button <Button
type="button" type="button"
disabled={isEmpty(companyDocsSelected)} disabled={addDocLoading || !isDocFormValid()}
label={__('Aggiungi', 'gepafin')} onClick={doImportCompanyDocs}/> label={__('Salva', 'gepafin')}
onClick={doAddNewDoc}/>
</div> </div>
}, [companyDocsSelected]); }
const doImportCompanyDocs = useCallback(() => { const onUpdateDocFieldValue = useCallback((value, name) => {
if (!isEmpty(companyDocsSelected)) { setNewDocData(prev => wrap(prev).set([name], value).value());
const ids = pluck('id', companyDocsSelected); }, []);
ApplicationService.setApplicationDocuments(applicationId, setDocsCallback, errSetDocsCallback, [
['companyDocumentIds', ids] const onDocFileSelect = (file) => {
]) setDocFileAttached(file.files);
}
const doAddNewDoc = useCallback(() => {
const submitData = {
...newDocData,
expirationDate: formatDateString(newDocData.expirationDate),
documentType: 'COMPANY_DOCUMENT'
};
const queryParams = Object.keys(submitData).map(k => [k, submitData[k]]);
if (!isEmpty(docFileAttached)) {
const formData = new FormData();
for (const file of docFileAttached) {
formData.append('file', file);
}
setAddDocLoading(true);
CompanyDocumentsService.uploadCompanyDocumenFromEvaluation(companyId, applicationId, formData, uploadDocCallback, errUploadDocCallback, queryParams);
} }
}, [companyDocsSelected]); }, [docFileAttached, newDocData, companyId, applicationId]);
const setDocsCallback = (resp) => { const uploadDocCallback = (resp) => {
if (resp.status === 'SUCCESS') { if (resp.status === 'SUCCESS') {
hideAddDocDialog();
setReloadHash(new Date().getTime());
} else {
if (toast.current && resp.message) { if (toast.current && resp.message) {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'error',
summary: '', summary: '',
detail: resp.message detail: resp.message
}); });
} }
} }
setIsVisibleCompanyDocsDialog(false); setAddDocLoading(false);
setCompanyDocsSelected([]);
storeSet('unsetAsyncRequest');
setTimeout(() => {
window.location.reload();
}, 2500);
} }
const errSetDocsCallback = (resp) => { const errUploadDocCallback = (resp) => {
if (toast.current && resp.message) { if (toast.current && resp.message) {
toast.current.show({ toast.current.show({
severity: resp.status === 'SUCCESS' ? 'info' : 'error', severity: 'error',
summary: '', summary: '',
detail: resp.message detail: resp.message
}); });
} }
setIsVisibleCompanyDocsDialog(false);
setCompanyDocsSelected([]);
set404FromErrorResponse(resp); set404FromErrorResponse(resp);
storeSet('unsetAsyncRequest'); setAddDocLoading(false);
} }
const getDocsCallback = (resp) => {
if (resp.status === 'SUCCESS') {
setCompanyDocs(resp.data);
}
}
const errGetDocsCallback = () => {}
useEffect(() => { useEffect(() => {
CompanyService.getCompanyDocuments(companyId, getDocsCallback, errGetDocsCallback, [ DocumentCategoryService.getCategories((resp) => {
['documentType', 'COMPANY_DOCUMENT'] if (resp.status === 'SUCCESS') {
]) setDocumentCategories(resp.data.map(o => ({ value: o.id, label: o.description })));
}, [companyId]); }
}, () => {});
}, []);
return ( return (
<> <>
@@ -240,7 +294,7 @@ const EvaluationExtraFiles = ({
className="fieldsRepeater__addNew" className="fieldsRepeater__addNew"
outlined outlined
type="button" type="button"
disabled={(watchFields && watchFields.filter(o => isEmpty(o.nameValue) || isEmpty(o.fileValue)).length > 0) || shouldDisable} disabled={shouldDisable}
onClick={openCompanyArchive} onClick={openCompanyArchive}
label={__('Documenti aziendali', 'gepafin')} label={__('Documenti aziendali', 'gepafin')}
/> />
@@ -251,41 +305,79 @@ const EvaluationExtraFiles = ({
visible={isVisibleCompanyDocsDialog} visible={isVisibleCompanyDocsDialog}
modal modal
header={headerCompanyDocsDialog} header={headerCompanyDocsDialog}
footer={footerPreTecEvalDialog} footer={footerCompanyDocsDialog}
style={{ maxWidth: '600px', width: '100%' }} style={{ maxWidth: '900px', width: '100%' }}
onHide={hideCompanyDocsDialog}> onHide={hideCompanyDocsDialog}>
<div className="appForm__field"> <div style={{ marginBottom: '1rem' }}>
{/*<label <Button
className={classNames({ type="button"
'p-error': isEmpty(companyDocsSelected) label={__('Aggiungi nuovo documento', 'gepafin')}
})}> icon="pi pi-plus"
{__('Documenti', 'gepafin')} iconPos="right"
</label>*/} onClick={openAddDocDialog}/>
<FileSelect </div>
fieldName="companyDocsSelected" <DocumentsTable type="COMPANY_DOCUMENT" companyId={companyId} reload={reloadHash}/>
label={null} </Dialog>
errors={{}} <Dialog
register={() => {}} visible={isVisibleAddDocDialog}
key={companyDocsSelected} modal
defaultValue={companyDocsSelected} header={headerAddDocDialog}
options={companyDocs} footer={footerAddDocDialog}
sourceId="0" style={{ maxWidth: '600px', width: '100%' }}
source="DOCUMENT" onHide={hideAddDocDialog}>
documentCategories={[]} <div className="appForm__cols">
attachFilesCallback={(o) => { <div className="appForm__field">
setCompanyDocsSelected(prev => { <label
const newSelected = [...prev]; className={classNames({ 'p-error': isEmpty(newDocData.name) || isNil(newDocData.name) })}>
if (!newSelected.find(s => s.id === o.id)) { {__('Nome', 'gepafin')}*
newSelected.push(o); </label>
} <InputText
return newSelected; value={newDocData.name || ''}
}) invalid={isEmpty(newDocData.name || '') || isNil(newDocData.name)}
}} onChange={(e) => onUpdateDocFieldValue(e.target.value, 'name')}/>
/> </div>
<div className="appForm__field">
<label
className={classNames({ 'p-error': !newDocData.documentCategoryId || newDocData.documentCategoryId === 0 })}>
{__('Categoria', 'gepafin')}*
</label>
<Dropdown
value={newDocData.documentCategoryId}
invalid={!newDocData.documentCategoryId || newDocData.documentCategoryId === 0}
onChange={(e) => onUpdateDocFieldValue(e.value, 'documentCategoryId')}
options={documentCategories}
optionLabel="label"
optionValue="value"/>
</div>
</div>
<div className="appForm__cols">
<div className="appForm__field">
<label
className={classNames({ 'p-error': isEmpty(newDocData.expirationDate || '') || isNil(newDocData.expirationDate) })}>
{__('Scadenza', 'gepafin')}*
</label>
<Calendar
value={newDocData.expirationDate}
minDate={tomorrow}
invalid={isEmpty(newDocData.expirationDate || '') || isNil(newDocData.expirationDate)}
onChange={(e) => onUpdateDocFieldValue(e.value, 'expirationDate')}/>
</div>
</div>
<div className="appForm__cols">
<div className="appForm__field">
<label
className={classNames({ 'p-error': isEmpty(docFileAttached) })}>
{__('File', 'gepafin')}*
</label>
<FileUpload
mode="basic"
name="file"
onSelect={onDocFileSelect}/>
</div>
</div> </div>
</Dialog> </Dialog>
</> </>
) )
} }
export default EvaluationExtraFiles; export default EvaluationExtraFiles;

View File

@@ -12,6 +12,10 @@ export default class CompanyDocumentsService {
NetworkService.postMultiPart(`${API_BASE_URL}/companyDocument/company/${id}/upload`, body, callback, errCallback, queryParams); NetworkService.postMultiPart(`${API_BASE_URL}/companyDocument/company/${id}/upload`, body, callback, errCallback, queryParams);
}; };
static uploadCompanyDocumenFromEvaluation = (id, applicationId, body, callback, errCallback, queryParams) => {
NetworkService.postMultiPart(`${API_BASE_URL}/companyDocument/company/${id}/application/${applicationId}/upload`, body, callback, errCallback, queryParams);
};
static attachCompanyDocumentToAppl = (id, callback, errCallback, queryParams) => { static attachCompanyDocumentToAppl = (id, callback, errCallback, queryParams) => {
NetworkService.put(`${API_BASE_URL}/companyDocument/${id}/document/upload`, {}, callback, errCallback, queryParams); NetworkService.put(`${API_BASE_URL}/companyDocument/${id}/document/upload`, {}, callback, errCallback, queryParams);
}; };