diff --git a/buildspec.dev.yml b/buildspec.dev.yml index c44d149..6c62832 100644 --- a/buildspec.dev.yml +++ b/buildspec.dev.yml @@ -3,10 +3,12 @@ version: 0.2 phases: install: runtime-versions: - nodejs: 20 + nodejs: 20 + commands: + - npm install build: commands: - - npm install && npm run build:dev + - npm run build:dev artifacts: files: - '**/*' diff --git a/buildspec.prod.yml b/buildspec.prod.yml index ce3c7b5..2f0dfa8 100644 --- a/buildspec.prod.yml +++ b/buildspec.prod.yml @@ -4,10 +4,12 @@ phases: install: runtime-versions: nodejs: 20 + commands: + - npm install build: commands: - - npm install && npm run build:prod + - npm run build:prod artifacts: files: - '**/*' - base-directory: 'build' \ No newline at end of file + base-directory: 'build' diff --git a/package.json b/package.json index a55fc51..f98edcb 100644 --- a/package.json +++ b/package.json @@ -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: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: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: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: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 && GENERATE_SOURCEMAP=false NODE_OPTIONS=--max-old-space-size=1536 react-scripts build --mode production", "test": "react-scripts test", "eject": "react-scripts eject", "make-pot": "wpi18n makepot --domain-path=languages --domain=gepafin" diff --git a/src/components/FormField/components/Spreadsheet/index.js b/src/components/FormField/components/Spreadsheet/index.js index 7b9343f..98efc27 100644 --- a/src/components/FormField/components/Spreadsheet/index.js +++ b/src/components/FormField/components/Spreadsheet/index.js @@ -4,6 +4,24 @@ import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'; import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'; 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) => { if (!val) return null; if (typeof val === 'object' && val.sheets) return val; @@ -23,6 +41,8 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { const univerRef = useRef(null); const univerAPIRef = useRef(null); const saveTimerRef = useRef(null); + const isRestoringRef = useRef(false); + const tagCellMapRef = useRef({}); useEffect(() => { if (!containerRef.current) return; @@ -43,8 +63,40 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { univerAPIRef.current = univerAPI; const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' }; + tagCellMapRef.current = buildTagMap(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, () => { clearTimeout(saveTimerRef.current); saveTimerRef.current = setTimeout(() => { @@ -53,10 +105,13 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { setDataFn(fieldName, wb.save()); } }, 300); + clearTimeout(restoreTimer); + restoreTimer = setTimeout(restoreTagCells, 80); }); return () => { clearTimeout(saveTimerRef.current); + clearTimeout(restoreTimer); if (univerRef.current) { univerRef.current.dispose(); univerRef.current = null; diff --git a/src/components/FormField/index.js b/src/components/FormField/index.js index 5688f4f..e7cc860 100644 --- a/src/components/FormField/index.js +++ b/src/components/FormField/index.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { isNil } from 'ramda'; import { classNames } from 'primereact/utils'; @@ -19,7 +19,7 @@ import Table from './components/Table'; import PasswordField from './components/PasswordField'; import CriteriaTable from './components/CriteriaTable'; import FileSelect from './components/FileSelect'; -import Spreadsheet from './components/Spreadsheet'; +const Spreadsheet = React.lazy(() => import('./components/Spreadsheet')); const FormField = (props) => { const fields = { @@ -45,7 +45,9 @@ const FormField = (props) => { return (!isNil(Comp) ?
- + + +
: null ) diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js index d167688..02ccccf 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSetting/index.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { Suspense, useEffect, useState } from 'react'; import { __ } from '@wordpress/i18n'; import { head, is, isEmpty, isNil, uniq } from 'ramda'; @@ -18,13 +18,13 @@ import { InputSwitch } from 'primereact/inputswitch'; import ElementSettingChips from '../ElementSettingChips'; import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns'; import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv'; -import ElementSettingSpreadsheet from '../ElementSettingSpreadsheet'; - import { mimeTypes } from '../../../../../../configData'; import ElementSettingReportHeader from '../ElementSettingReportHeader'; import ElementSettingReportEnable from '../ElementSettingReportEnable'; import getTokens from '../../../../../../helpers/getTokens'; +const ElementSettingSpreadsheet = React.lazy(() => import('../ElementSettingSpreadsheet')); + const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { const [existingVars, setExistingVars] = useState([]); @@ -159,10 +159,12 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => { bandoStatus={bandoStatus} setDataFn={updateDataFn}/> } else if (setting.name === 'template') { - return ; + return + + ; } else if (setting.name === 'formula') { const isInvalid = invalidFormula(setting.value); return <> diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js index 010b3c9..b5752c5 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js @@ -12,6 +12,8 @@ import { useStoreValue } from '../../../../../../store'; // tools import { xlsxToWorkbookData } from '../../../../../BandoEdit/components/BandoEditFormStep3Excel/xlsxToWorkbookData'; +const TAG_RE = /^\{\{gepafin_field:([^|]+)\|([^}]+)}}$/; + const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { const callFormFields = useStoreValue('callFormFields'); const [tagTooltip, setTagTooltip] = useState(null); @@ -19,6 +21,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { const univerRef = useRef(null); const univerAPIRef = useRef(null); const formFieldsRef = useRef([]); + const isRestoringRef = useRef(false); const mousePos = useRef({ x: 0, y: 0 }); const fileInputRef = useRef(null); @@ -60,11 +63,54 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { univerRef.current = univer; 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) => { if (event.id === 'sheet.command.insert-sheet') { event.cancel = true; } + clearTimeout(restoreTimer); + restoreTimer = setTimeout(restoreTagCells, 80); }); // Context menu: "Inserisci variabile GEPAFIN" @@ -113,6 +159,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { setTagTooltip(null); } }); + }, []); // refs are stable // Keep formFieldsRef in sync with store value diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/index.js index 3ddf810..b7ec16e 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/index.js @@ -119,7 +119,7 @@ const BuilderElementSettings = ({ closeSettingsFn, callStatus, context }) => { const chosenElementItemCfg = head(elementItems.filter(o => o.name === chosen.name)); let settings = []; - if (chosenElementItemCfg) { + if (chosenElementItemCfg && chosenElementItemCfg.settings) { settings = chosenElementItemCfg.settings.map((o) => { const setting = head(chosen.settings.filter(s => s.name === o.name)); return setting ? klona(setting) : klona(o) diff --git a/src/pages/DocumentsBeneficiary/components/DocumentsTable/index.js b/src/pages/DocumentsBeneficiary/components/DocumentsTable/index.js index 52ed254..5c132ce 100644 --- a/src/pages/DocumentsBeneficiary/components/DocumentsTable/index.js +++ b/src/pages/DocumentsBeneficiary/components/DocumentsTable/index.js @@ -24,8 +24,9 @@ import { Tag } from 'primereact/tag'; import ProperBandoLabel from '../../../../components/ProperBandoLabel'; import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup'; -const DocumentsTable = ({ type, reload = 0 }) => { - const chosenCompanyId = useStoreValue('chosenCompanyId'); +const DocumentsTable = ({ type, reload = 0, companyId: companyIdProp }) => { + const storedCompanyId = useStoreValue('chosenCompanyId'); + const effectiveCompanyId = companyIdProp || storedCompanyId; const companies = useStoreValue('companies'); const [docs, setDocs] = useState([]); const [filters, setFilters] = useState(null); @@ -33,22 +34,26 @@ const DocumentsTable = ({ type, reload = 0 }) => { const [statuses, setStatuses] = useState([]); 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); - CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [ + CompanyDocumentsService.getCompanyDocuments(effectiveCompanyId, getCallback, errGetCallbacks, [ ['documentType', type] ]); } - }, [chosenCompanyId, reload, companies]); + }, [effectiveCompanyId, reload, companies]); 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); - CompanyDocumentsService.getCompanyDocuments(chosenCompanyId, getCallback, errGetCallbacks, [ + CompanyDocumentsService.getCompanyDocuments(effectiveCompanyId, getCallback, errGetCallbacks, [ ['documentType', type] ]); } diff --git a/src/pages/DomandaEditPreInstructor/components/EvaluationExtraFiles/index.js b/src/pages/DomandaEditPreInstructor/components/EvaluationExtraFiles/index.js index 5ce8961..61457a3 100644 --- a/src/pages/DomandaEditPreInstructor/components/EvaluationExtraFiles/index.js +++ b/src/pages/DomandaEditPreInstructor/components/EvaluationExtraFiles/index.js @@ -1,22 +1,30 @@ import React, { useMemo, useState, useCallback, useEffect, useRef } from 'react'; import { useForm, useFieldArray } from 'react-hook-form'; -import { isEmpty, head, pluck } from 'ramda'; +import { isEmpty, head, isNil } from 'ramda'; import { __ } from '@wordpress/i18n'; import { klona } from 'klona'; +import { wrap } from 'object-path-immutable'; +import { classNames } from 'primereact/utils'; // tools import uniqid from '../../../../helpers/uniqid'; +import formatDateString from '../../../../helpers/formatDateString'; // components import FormField from '../../../../components/FormField'; import { Button } from 'primereact/button'; import { Dialog } from 'primereact/dialog'; import { Toast } from 'primereact/toast'; -import CompanyService from '../../../../service/company-service'; -import FileSelect from '../../../../components/FormField/components/FileSelect'; -import ApplicationService from '../../../../service/application-service'; +import { Dropdown } from 'primereact/dropdown'; +import { InputText } from 'primereact/inputtext'; +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 { storeSet } from '../../../../store'; const EvaluationExtraFiles = ({ sourceId, @@ -32,9 +40,16 @@ const EvaluationExtraFiles = ({ }) => { const [chosen, setChosen] = useState(''); const [isVisibleCompanyDocsDialog, setIsVisibleCompanyDocsDialog] = useState(false); - const [companyDocs, setCompanyDocs] = useState([]); - const [companyDocsSelected, setCompanyDocsSelected] = useState([]); + const [isVisibleAddDocDialog, setIsVisibleAddDocDialog] = useState(false); + 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 today = new Date(); + const tomorrow = new Date(today); + tomorrow.setDate(today.getDate() + 1); const { control, handleSubmit, @@ -107,74 +122,113 @@ const EvaluationExtraFiles = ({ const hideCompanyDocsDialog = () => { setIsVisibleCompanyDocsDialog(false); - setCompanyDocsSelected([]); } - const footerPreTecEvalDialog = useCallback(() => { + const footerCompanyDocsDialog = () => { return
-
+ } + + const openAddDocDialog = () => { + setNewDocData({ + name: '', + documentCategoryId: 0, + expirationDate: '' + }); + setDocFileAttached([]); + setIsVisibleAddDocDialog(true); + } + + const hideAddDocDialog = () => { + setIsVisibleAddDocDialog(false); + setNewDocData({}); + setDocFileAttached([]); + } + + const headerAddDocDialog = () => { + return {__('Aggiungi documento aziendale', 'gepafin')}; + } + + 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
+
- }, [companyDocsSelected]); + } - const doImportCompanyDocs = useCallback(() => { - if (!isEmpty(companyDocsSelected)) { - const ids = pluck('id', companyDocsSelected); - ApplicationService.setApplicationDocuments(applicationId, setDocsCallback, errSetDocsCallback, [ - ['companyDocumentIds', ids] - ]) + const onUpdateDocFieldValue = useCallback((value, name) => { + setNewDocData(prev => wrap(prev).set([name], value).value()); + }, []); + + 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') { + hideAddDocDialog(); + setReloadHash(new Date().getTime()); + } else { if (toast.current && resp.message) { toast.current.show({ - severity: 'success', + severity: 'error', summary: '', detail: resp.message }); } } - setIsVisibleCompanyDocsDialog(false); - setCompanyDocsSelected([]); - storeSet('unsetAsyncRequest'); - - setTimeout(() => { - window.location.reload(); - }, 2500); + setAddDocLoading(false); } - const errSetDocsCallback = (resp) => { + const errUploadDocCallback = (resp) => { if (toast.current && resp.message) { toast.current.show({ - severity: resp.status === 'SUCCESS' ? 'info' : 'error', + severity: 'error', summary: '', detail: resp.message }); } - setIsVisibleCompanyDocsDialog(false); - setCompanyDocsSelected([]); set404FromErrorResponse(resp); - storeSet('unsetAsyncRequest'); + setAddDocLoading(false); } - const getDocsCallback = (resp) => { - if (resp.status === 'SUCCESS') { - setCompanyDocs(resp.data); - } - } - - const errGetDocsCallback = () => {} - useEffect(() => { - CompanyService.getCompanyDocuments(companyId, getDocsCallback, errGetDocsCallback, [ - ['documentType', 'COMPANY_DOCUMENT'] - ]) - }, [companyId]); + DocumentCategoryService.getCategories((resp) => { + if (resp.status === 'SUCCESS') { + setDocumentCategories(resp.data.map(o => ({ value: o.id, label: o.description }))); + } + }, () => {}); + }, []); return ( <> @@ -240,7 +294,7 @@ const EvaluationExtraFiles = ({ className="fieldsRepeater__addNew" outlined type="button" - disabled={(watchFields && watchFields.filter(o => isEmpty(o.nameValue) || isEmpty(o.fileValue)).length > 0) || shouldDisable} + disabled={shouldDisable} onClick={openCompanyArchive} label={__('Documenti aziendali', 'gepafin')} /> @@ -251,41 +305,79 @@ const EvaluationExtraFiles = ({ visible={isVisibleCompanyDocsDialog} modal header={headerCompanyDocsDialog} - footer={footerPreTecEvalDialog} - style={{ maxWidth: '600px', width: '100%' }} + footer={footerCompanyDocsDialog} + style={{ maxWidth: '900px', width: '100%' }} onHide={hideCompanyDocsDialog}> -
- {/**/} - {}} - key={companyDocsSelected} - defaultValue={companyDocsSelected} - options={companyDocs} - sourceId="0" - source="DOCUMENT" - documentCategories={[]} - attachFilesCallback={(o) => { - setCompanyDocsSelected(prev => { - const newSelected = [...prev]; - if (!newSelected.find(s => s.id === o.id)) { - newSelected.push(o); - } - return newSelected; - }) - }} - /> +
+
+ + + +
+
+ + onUpdateDocFieldValue(e.target.value, 'name')}/> +
+
+ + onUpdateDocFieldValue(e.value, 'documentCategoryId')} + options={documentCategories} + optionLabel="label" + optionValue="value"/> +
+
+
+
+ + onUpdateDocFieldValue(e.value, 'expirationDate')}/> +
+
+
+
+ + +
) } -export default EvaluationExtraFiles; \ No newline at end of file +export default EvaluationExtraFiles; diff --git a/src/service/company-documents-service.js b/src/service/company-documents-service.js index 3d38b71..4472a67 100644 --- a/src/service/company-documents-service.js +++ b/src/service/company-documents-service.js @@ -12,6 +12,10 @@ export default class CompanyDocumentsService { 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) => { NetworkService.put(`${API_BASE_URL}/companyDocument/${id}/document/upload`, {}, callback, errCallback, queryParams); };