@topconsultnpm/sdkui-react 6.22.0-dev2.3 → 6.22.0-dev2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +1 -1
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +1 -1
- package/lib/components/base/TMButton.d.ts +13 -0
- package/lib/components/base/TMButton.js +137 -5
- package/lib/components/base/TMDataGrid.d.ts +2 -0
- package/lib/components/base/TMDataGrid.js +81 -8
- package/lib/components/base/TMEditorBase.d.ts +2 -0
- package/lib/components/base/TMFileManager.js +5 -3
- package/lib/components/base/TMFileManagerUtils.d.ts +1 -0
- package/lib/components/base/TMFileManagerUtils.js +16 -0
- package/lib/components/base/TMModal.d.ts +4 -0
- package/lib/components/base/TMModal.js +42 -11
- package/lib/components/base/TMPanel.d.ts +1 -0
- package/lib/components/base/TMPanel.js +79 -20
- package/lib/components/base/TMPopUp.js +3 -0
- package/lib/components/base/TMTooltip.d.ts +2 -1
- package/lib/components/base/TMTooltip.js +23 -6
- package/lib/components/base/TMTreeView.js +108 -67
- package/lib/components/choosers/TMDcmtTypeChooser.js +4 -3
- package/lib/components/choosers/TMDistinctValues.d.ts +9 -7
- package/lib/components/choosers/TMDistinctValues.js +149 -142
- package/lib/components/choosers/TMMetadataChooser.js +1 -1
- package/lib/components/choosers/TMQuickSearchInfo.d.ts +12 -0
- package/lib/components/choosers/TMQuickSearchInfo.js +279 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.d.ts +16 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.js +94 -0
- package/lib/components/choosers/TMSelectedValuesSummary.d.ts +13 -0
- package/lib/components/choosers/TMSelectedValuesSummary.js +91 -0
- package/lib/components/editors/TMDropDown.d.ts +3 -0
- package/lib/components/editors/TMDropDown.js +197 -5
- package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
- package/lib/components/editors/TMMetadataEditor.js +8 -3
- package/lib/components/editors/TMTextBox.js +2 -2
- package/lib/components/features/documents/TMBatchUpdateForm.js +19 -5
- package/lib/components/features/documents/TMDcmtBlog.d.ts +3 -0
- package/lib/components/features/documents/TMDcmtBlog.js +4 -4
- package/lib/components/features/documents/TMDcmtForm.d.ts +7 -0
- package/lib/components/features/documents/TMDcmtForm.js +112 -45
- package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +11 -0
- package/lib/components/features/documents/TMDcmtFormActionButtons.js +74 -7
- package/lib/components/features/documents/TMDcmtPreview.js +10 -6
- package/lib/components/features/documents/TMMasterDetailDcmts.js +95 -33
- package/lib/components/features/documents/TMMasterInfoFields.d.ts +19 -0
- package/lib/components/features/documents/TMMasterInfoFields.js +186 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +40 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +296 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +363 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +259 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +14 -1
- package/lib/components/features/documents/TMRelationViewer.js +69 -20
- package/lib/components/features/search/TMSearch.js +29 -16
- package/lib/components/features/search/TMSearchQueryEditor.js +5 -3
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
- package/lib/components/features/search/TMSearchQueryPanel.js +28 -7
- package/lib/components/features/search/TMSearchResult.d.ts +9 -0
- package/lib/components/features/search/TMSearchResult.js +419 -108
- package/lib/components/features/search/TMTreeSelector.js +18 -5
- package/lib/components/features/workflow/TMWorkflowPopup.d.ts +10 -0
- package/lib/components/features/workflow/TMWorkflowPopup.js +8 -4
- package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +24 -14
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +68 -93
- package/lib/components/layout/panelManager/TMPanelWrapper.js +2 -2
- package/lib/components/layout/panelManager/types.d.ts +3 -0
- package/lib/components/layout/panelManager/utils.js +13 -11
- package/lib/components/viewers/TMMidViewer.js +4 -1
- package/lib/components/viewers/TMTidViewer.js +25 -11
- package/lib/helper/SDKUI_Globals.d.ts +82 -0
- package/lib/helper/SDKUI_Globals.js +119 -0
- package/lib/helper/SDKUI_Localizator.d.ts +24 -0
- package/lib/helper/SDKUI_Localizator.js +240 -0
- package/lib/helper/TMIcons.d.ts +1 -0
- package/lib/helper/TMIcons.js +3 -0
- package/lib/helper/dataGridSearchHelper.d.ts +28 -0
- package/lib/helper/dataGridSearchHelper.js +51 -0
- package/lib/helper/dcmtsHelper.d.ts +20 -0
- package/lib/helper/dcmtsHelper.js +58 -1
- package/lib/helper/helpers.d.ts +20 -0
- package/lib/helper/helpers.js +55 -1
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/helper/queryHelper.d.ts +2 -0
- package/lib/helper/queryHelper.js +3 -1
- package/lib/hooks/tmDistinctValuesGridHelper.d.ts +16 -0
- package/lib/hooks/tmDistinctValuesGridHelper.js +31 -0
- package/lib/hooks/useArchiveListForm.d.ts +39 -0
- package/lib/hooks/useArchiveListForm.js +46 -0
- package/lib/hooks/useCaseFlowApprove.d.ts +56 -0
- package/lib/hooks/useCaseFlowApprove.js +157 -0
- package/lib/hooks/useDataUserIdItem.d.ts +1 -0
- package/lib/hooks/useDataUserIdItem.js +1 -0
- package/lib/hooks/useDocumentOperations.d.ts +2 -0
- package/lib/hooks/useDocumentOperations.js +28 -5
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +100 -0
- package/lib/hooks/useMultiMasterDetailDcmts.js +587 -0
- package/lib/hooks/useRelatedDocuments.js +2 -26
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.d.ts +18 -0
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.js +103 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.d.ts +49 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.js +307 -0
- package/lib/hooks/useTMDistinctValuesSelection.d.ts +42 -0
- package/lib/hooks/useTMDistinctValuesSelection.js +103 -0
- package/lib/hooks/useTMDistinctValuesSource.d.ts +29 -0
- package/lib/hooks/useTMDistinctValuesSource.js +105 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/services/caseflow/CaseFlowService.d.ts +236 -0
- package/lib/services/caseflow/CaseFlowService.js +693 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.d.ts +28 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.js +121 -0
- package/lib/services/caseflow/caseFlowNameCache.d.ts +32 -0
- package/lib/services/caseflow/caseFlowNameCache.js +116 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.d.ts +61 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.js +113 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/index.js +4 -0
- package/lib/services/platform_services.d.ts +1 -1
- package/package.json +66 -66
package/lib/helper/helpers.js
CHANGED
|
@@ -7,6 +7,14 @@ import { buildTypes, FileExtensionHandler, FormModes, moduleTypes } from "../ts"
|
|
|
7
7
|
import { SDKUI_Localizator } from "./SDKUI_Localizator";
|
|
8
8
|
import ReactDOMServer from "react-dom/server";
|
|
9
9
|
import { DeepCompareHelper } from "./DeepCompareHelper";
|
|
10
|
+
/**
|
|
11
|
+
* Handler di hover per elementi con stili inline: applica `over` all'ingresso del mouse e `out` all'uscita.
|
|
12
|
+
* Da spandere sull'elemento: `{...hoverStyle({ background: 'red' }, { background: 'transparent' })}`
|
|
13
|
+
*/
|
|
14
|
+
export const hoverStyle = (over, out) => ({
|
|
15
|
+
onMouseEnter: (e) => Object.assign(e.currentTarget.style, over),
|
|
16
|
+
onMouseLeave: (e) => Object.assign(e.currentTarget.style, out),
|
|
17
|
+
});
|
|
10
18
|
const calcResponsiveSizes = (deviceType, desktopSize, tabletSize, mobileSize) => {
|
|
11
19
|
if (deviceType === DeviceType.DESKTOP)
|
|
12
20
|
return desktopSize;
|
|
@@ -239,6 +247,38 @@ export const searchResultDescriptorToSimpleArray = (searchResult) => {
|
|
|
239
247
|
});
|
|
240
248
|
return result;
|
|
241
249
|
};
|
|
250
|
+
/**
|
|
251
|
+
* Unisce ("accoda") il risultato di una nuova ricerca a quello precedente, sullo stesso tipo documento.
|
|
252
|
+
* - Le righe della nuova ricerca vengono messe in cima (più recenti in alto)
|
|
253
|
+
* - Le righe duplicate sono accettate: lo stesso documento può comparire più volte
|
|
254
|
+
* - Aggiorna i contatori globali (dcmtsFound / dcmtsReturned) sul totale unito
|
|
255
|
+
*
|
|
256
|
+
* @param previous Risultato attualmente in memoria (può essere undefined al primo giro)
|
|
257
|
+
* @param next Nuovo risultato appena ottenuto
|
|
258
|
+
* @returns Un nuovo SearchResultDescriptor con le righe unite, oppure il singolo risultato disponibile
|
|
259
|
+
*/
|
|
260
|
+
export const mergeSearchResultsAppend = (previous, next) => {
|
|
261
|
+
// Se manca uno dei due, non c'è nulla da unire
|
|
262
|
+
if (!next?.dtdResult?.rows?.length)
|
|
263
|
+
return previous;
|
|
264
|
+
if (!previous?.dtdResult?.rows?.length)
|
|
265
|
+
return next;
|
|
266
|
+
// L'accodamento ha senso solo sullo stesso tipo documento (colonne compatibili)
|
|
267
|
+
if (previous.fromTID !== next.fromTID)
|
|
268
|
+
return next;
|
|
269
|
+
const prevRows = previous.dtdResult.rows ?? [];
|
|
270
|
+
const nextRows = next.dtdResult.rows ?? [];
|
|
271
|
+
// Nessuna deduplica: le nuove righe in cima, poi le precedenti (i duplicati sono ammessi)
|
|
272
|
+
const mergedRows = [...nextRows, ...prevRows];
|
|
273
|
+
// Costruisce il nuovo descrittore basandosi sull'ultimo risultato (colonne/qd più recenti), con le righe unite
|
|
274
|
+
const merged = structuredClone(next);
|
|
275
|
+
const mergedDtd = structuredClone(next.dtdResult);
|
|
276
|
+
mergedDtd.rows = mergedRows;
|
|
277
|
+
merged.dtdResult = mergedDtd;
|
|
278
|
+
merged.dcmtsReturned = mergedRows.length;
|
|
279
|
+
merged.dcmtsFound = mergedRows.length;
|
|
280
|
+
return merged;
|
|
281
|
+
};
|
|
242
282
|
export const getCompleteMetadataName = (dcmtTypeName, metadataName) => `${dcmtTypeName}...${metadataName}`;
|
|
243
283
|
export const getQueryCountAsync = async (qd, showSpinner) => {
|
|
244
284
|
try {
|
|
@@ -781,7 +821,21 @@ export var LandingPages;
|
|
|
781
821
|
// #region Exception
|
|
782
822
|
export function getExceptionMessage(ex) {
|
|
783
823
|
let msg = ex.isApiException ? ex.response.title : ex.message;
|
|
784
|
-
|
|
824
|
+
if (msg !== undefined && msg !== null)
|
|
825
|
+
return msg;
|
|
826
|
+
let asString = ex.toString();
|
|
827
|
+
if (asString !== '[object Object]')
|
|
828
|
+
return asString;
|
|
829
|
+
if (ex.errorMessage)
|
|
830
|
+
return ex.errorMessage;
|
|
831
|
+
if (ex.title)
|
|
832
|
+
return ex.title;
|
|
833
|
+
try {
|
|
834
|
+
return JSON.stringify(ex) ?? asString;
|
|
835
|
+
}
|
|
836
|
+
catch {
|
|
837
|
+
return asString;
|
|
838
|
+
}
|
|
785
839
|
}
|
|
786
840
|
export function getContrastColor(inputColor) {
|
|
787
841
|
let hex = inputColor;
|
package/lib/helper/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './Globalization';
|
|
|
5
5
|
export * from './TMIcons';
|
|
6
6
|
export * from './TMImageLibrary';
|
|
7
7
|
export * from './helpers';
|
|
8
|
+
export * from './dataGridSearchHelper';
|
|
8
9
|
export * from './queryHelper';
|
|
9
10
|
export * from './TMUtils';
|
|
10
11
|
export * from './TMCommandsContextMenu';
|
package/lib/helper/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from './Globalization';
|
|
|
5
5
|
export * from './TMIcons';
|
|
6
6
|
export * from './TMImageLibrary';
|
|
7
7
|
export * from './helpers';
|
|
8
|
+
export * from './dataGridSearchHelper';
|
|
8
9
|
export * from './queryHelper';
|
|
9
10
|
export * from './TMUtils';
|
|
10
11
|
export * from './TMCommandsContextMenu';
|
|
@@ -14,6 +14,8 @@ export declare function addWhereClausesForConnect(qd: QueryDescriptor): void;
|
|
|
14
14
|
export declare function getDefaultOperator(dataDomain: MetadataDataDomains | undefined, dataType: MetadataDataTypes | undefined): QueryOperators.Equal | QueryOperators.Contain | QueryOperators.In;
|
|
15
15
|
export declare const getQD: (tid: number | undefined, easyOr: boolean, newMaxDcmtsToBeReturned: number) => Promise<QueryDescriptor | undefined>;
|
|
16
16
|
export declare const getWorkItemSetIDAsync: (vid: number, did: number) => Promise<string | undefined>;
|
|
17
|
+
/** Id assegnato alla ricerca di sistema con tutti i documenti: non è in cache, va ricostruita a runtime con getSysAllDcmtsSQD */
|
|
18
|
+
export declare const SYS_ALL_DCMTS_SQD_ID = 1;
|
|
17
19
|
export declare const getSysAllDcmtsSQD: (tid: number | undefined, easyOr: boolean) => Promise<SavedQueryDescriptor>;
|
|
18
20
|
export declare const searchResultToMetadataValues: (tid: number | undefined, dtd: DataTableDescriptor | undefined, rows: string[], mids: number[], metadata: MetadataDescriptor[], layoutMode: LayoutModes, isReadOnlyOrigin?: boolean) => MetadataValueDescriptorEx[];
|
|
19
21
|
export declare const handleArchiveVisibility: (md: MetadataDescriptor) => boolean;
|
|
@@ -251,9 +251,11 @@ export const getWorkItemSetIDAsync = async (vid, did) => {
|
|
|
251
251
|
let result = await SDK_Globals.tmSession?.NewSearchEngine().SearchByIDAsync(qd);
|
|
252
252
|
return result?.dtdResult?.rows?.[0]?.[0];
|
|
253
253
|
};
|
|
254
|
+
/** Id assegnato alla ricerca di sistema con tutti i documenti: non è in cache, va ricostruita a runtime con getSysAllDcmtsSQD */
|
|
255
|
+
export const SYS_ALL_DCMTS_SQD_ID = 1;
|
|
254
256
|
export const getSysAllDcmtsSQD = async (tid, easyOr) => {
|
|
255
257
|
let sqd = new SavedQueryDescriptor();
|
|
256
|
-
sqd.id =
|
|
258
|
+
sqd.id = SYS_ALL_DCMTS_SQD_ID;
|
|
257
259
|
sqd.masterTID = tid;
|
|
258
260
|
sqd.isEasyWhere = 1;
|
|
259
261
|
sqd.name = SDKUI_Localizator.AllDcmts;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DataColumnDescriptor, DataColumnTypes, MetadataDescriptor, MetadataFormats } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Funzioni condivise dalle due sorgenti di TMDistinctValues (valori distinti e ricerca rapida):
|
|
4
|
+
* stanno fuori dagli hook perché non dipendono da alcuno stato.
|
|
5
|
+
*/
|
|
6
|
+
export declare const withRowIndex: <T>(rows: Array<T>) => T[];
|
|
7
|
+
export declare const toGridDataType: (dataType: DataColumnTypes | undefined) => "string" | "number" | "datetime" | "boolean";
|
|
8
|
+
export declare const getMetadataName: (columnMd: MetadataDescriptor | undefined) => string | undefined;
|
|
9
|
+
export declare const getDateDisplayFormat: (format: MetadataFormats | undefined, formatCulture: string | undefined | null) => {
|
|
10
|
+
formatter: (value: string | number | Date) => string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Risolve il MID della colonna di un risultato di ricerca: la proprietà estesa è la fonte principale,
|
|
14
|
+
* in mancanza resta l'allineamento posizionale tra selectMIDs e colonne del risultato.
|
|
15
|
+
*/
|
|
16
|
+
export declare const getColumnMid: (column: DataColumnDescriptor | undefined, selectMIDs: number[] | undefined, columnIndex: number) => number;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DataColumnTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
import { formatDateTimeByMetadataFormat } from '../helper';
|
|
3
|
+
/**
|
|
4
|
+
* Funzioni condivise dalle due sorgenti di TMDistinctValues (valori distinti e ricerca rapida):
|
|
5
|
+
* stanno fuori dagli hook perché non dipendono da alcuno stato.
|
|
6
|
+
*/
|
|
7
|
+
// rowIndex è la chiave delle griglie di TMDistinctValues: va riallineato all'ordine finale delle righe
|
|
8
|
+
export const withRowIndex = (rows) => {
|
|
9
|
+
rows.forEach((row, index) => { row.rowIndex = index; });
|
|
10
|
+
return rows;
|
|
11
|
+
};
|
|
12
|
+
export const toGridDataType = (dataType) => {
|
|
13
|
+
switch (dataType) {
|
|
14
|
+
case DataColumnTypes.DateTime: return 'datetime';
|
|
15
|
+
case DataColumnTypes.Bool: return 'boolean';
|
|
16
|
+
case DataColumnTypes.Number: return 'number';
|
|
17
|
+
default: return 'string';
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
// Nome del metadato con cui viene intestata la colonna, nella lingua scelta dall'utente
|
|
21
|
+
export const getMetadataName = (columnMd) => (SDK_Globals.useLocalizedName ? columnMd?.nameLoc : columnMd?.name) ?? columnMd?.name ?? columnMd?.nameLoc ?? undefined;
|
|
22
|
+
// Le date vanno mostrate con il formato definito sul metadato, come nel risultato di ricerca
|
|
23
|
+
export const getDateDisplayFormat = (format, formatCulture) => ({
|
|
24
|
+
// La griglia passa al formatter un oggetto Date già istanziato, ma il valore può arrivare anche come stringa
|
|
25
|
+
formatter: (value) => formatDateTimeByMetadataFormat(value instanceof Date ? value : new Date(value), format, formatCulture)
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Risolve il MID della colonna di un risultato di ricerca: la proprietà estesa è la fonte principale,
|
|
29
|
+
* in mancanza resta l'allineamento posizionale tra selectMIDs e colonne del risultato.
|
|
30
|
+
*/
|
|
31
|
+
export const getColumnMid = (column, selectMIDs, columnIndex) => Number(column?.extendedProperties?.['MID'] ?? 0) || (selectMIDs?.[columnIndex] ?? 0);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { MutableRefObject } from 'react';
|
|
2
|
+
import { MetadataValueDescriptorEx } from '../ts';
|
|
3
|
+
/** Modalità "aggiungi a elenco": il form non archivia a sistema, restituisce i metadati al chiamante (TMMultiMasterDetailDcmts). */
|
|
4
|
+
export interface ArchiveListMode {
|
|
5
|
+
/** true quando si modifica una riga già presente nell'elenco ("Modifica" al posto di "Aggiungi"). */
|
|
6
|
+
isEditingRow: boolean;
|
|
7
|
+
/** Restituisce metadati e file al chiamante, che aggiunge o aggiorna la riga nell'elenco (senza archiviare). */
|
|
8
|
+
onUpsertRow: (metadataValues: Array<MetadataValueDescriptorEx>, file: File | undefined, tid?: number) => void;
|
|
9
|
+
}
|
|
10
|
+
interface UseArchiveListFormParams {
|
|
11
|
+
/** Assente = modalità "aggiungi a elenco" spenta. */
|
|
12
|
+
mode?: ArchiveListMode;
|
|
13
|
+
/** Valori della riga in modifica, con cui pre-compilare il form. */
|
|
14
|
+
editingRowValues?: Array<{
|
|
15
|
+
mid: number;
|
|
16
|
+
value: string;
|
|
17
|
+
}>;
|
|
18
|
+
/** Template vuoto del form. */
|
|
19
|
+
formDataOrig: Array<MetadataValueDescriptorEx>;
|
|
20
|
+
/** Ref ai valori correnti del form (per leggerli al submit senza stale closure). */
|
|
21
|
+
formDataRef: MutableRefObject<Array<MetadataValueDescriptorEx>>;
|
|
22
|
+
/** Ref al file caricato. */
|
|
23
|
+
dcmtFileRef: MutableRefObject<File | null>;
|
|
24
|
+
tid?: number;
|
|
25
|
+
isModal?: boolean;
|
|
26
|
+
/** Id del form, usato come parentId del message box quando è in modale. */
|
|
27
|
+
id?: string;
|
|
28
|
+
/** Svuota il form dopo aver restituito i valori. */
|
|
29
|
+
clearForm: () => void;
|
|
30
|
+
}
|
|
31
|
+
/** Isola la logica della modalità "aggiungi a elenco": valori di riferimento, submit e chiusura del form. */
|
|
32
|
+
export declare const useArchiveListForm: ({ mode, editingRowValues, formDataOrig, formDataRef, dcmtFileRef, tid, isModal, id, clearForm, }: UseArchiveListFormParams) => {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
isEditingRow: boolean;
|
|
35
|
+
referenceValues: MetadataValueDescriptorEx[];
|
|
36
|
+
submit: () => void;
|
|
37
|
+
requestClose: (isModified: boolean, onClose?: () => void) => boolean;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
import { ButtonNames, TMMessageBoxManager } from '../components';
|
|
3
|
+
/** Isola la logica della modalità "aggiungi a elenco": valori di riferimento, submit e chiusura del form. */
|
|
4
|
+
export const useArchiveListForm = ({ mode, editingRowValues, formDataOrig, formDataRef, dcmtFileRef, tid, isModal, id, clearForm, }) => {
|
|
5
|
+
const enabled = !!mode;
|
|
6
|
+
const isEditingRow = !!mode?.isEditingRow;
|
|
7
|
+
// Valori con cui si confronta il form per capire cosa è cambiato (flag "modificato" ed evidenza gialla).
|
|
8
|
+
// Modificando una riga si parte dai suoi valori, così i campi pre-compilati non risultano subito modificati.
|
|
9
|
+
const referenceValues = useMemo(() => {
|
|
10
|
+
if (!isEditingRow || !editingRowValues || editingRowValues.length === 0)
|
|
11
|
+
return formDataOrig;
|
|
12
|
+
return formDataOrig.map(md => {
|
|
13
|
+
const rowValue = editingRowValues.find(rv => rv.mid === md.mid);
|
|
14
|
+
return rowValue ? { ...md, value: rowValue.value } : md;
|
|
15
|
+
});
|
|
16
|
+
}, [isEditingRow, editingRowValues, formDataOrig]);
|
|
17
|
+
// Restituisce metadati e file al chiamante, poi svuota il form.
|
|
18
|
+
const submit = useCallback(() => {
|
|
19
|
+
if (!mode)
|
|
20
|
+
return;
|
|
21
|
+
const values = formDataRef.current.filter(md => md.mid !== undefined && md.mid > 99);
|
|
22
|
+
mode.onUpsertRow(values, dcmtFileRef.current ?? undefined, tid);
|
|
23
|
+
clearForm();
|
|
24
|
+
}, [mode, formDataRef, dcmtFileRef, tid, clearForm]);
|
|
25
|
+
// Gestisce la chiusura del form
|
|
26
|
+
const requestClose = useCallback((isModified, onClose) => {
|
|
27
|
+
if (!mode)
|
|
28
|
+
return false;
|
|
29
|
+
if (!isModified) {
|
|
30
|
+
onClose?.();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
TMMessageBoxManager.show({
|
|
34
|
+
parentId: isModal ? "TMDcmtFormShowConfirmForClose-" + id : undefined,
|
|
35
|
+
message: "Chiudendo, le modifiche andranno perse. Proseguire?",
|
|
36
|
+
buttons: [ButtonNames.YES, ButtonNames.NO],
|
|
37
|
+
onButtonClick: (e) => {
|
|
38
|
+
// Sì: scarta le modifiche e chiude senza aggiungere all'elenco. No: resta sul form.
|
|
39
|
+
if (e == ButtonNames.YES)
|
|
40
|
+
onClose?.();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return true;
|
|
44
|
+
}, [mode, isModal, id]);
|
|
45
|
+
return { enabled, isEditingRow, referenceValues, submit, requestClose };
|
|
46
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CaseFlowInstanceDescriptor, CaseFlowWorkItem } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Attività (workitem) delle PRATICHE assegnate all'utente, con il documento su
|
|
4
|
+
* cui lavorano già risolto.
|
|
5
|
+
*
|
|
6
|
+
* Gemello di `useWorkflowApprove` per il modulo CaseFlow: i dati stanno in una
|
|
7
|
+
* cache di modulo e le istanze del hook si sincronizzano con un evento, così il
|
|
8
|
+
* form del documento — da qualunque punto venga aperto — sa che su quel TID/DID
|
|
9
|
+
* c'è una firma da fare o un'approvazione da dare, senza che il chiamante debba
|
|
10
|
+
* passargli nulla.
|
|
11
|
+
*/
|
|
12
|
+
/** Workitem di pratica già risolto sul documento cui si riferisce. */
|
|
13
|
+
export interface CaseFlowDcmtWorkItem {
|
|
14
|
+
caseflow: CaseFlowInstanceDescriptor;
|
|
15
|
+
workItem: CaseFlowWorkItem;
|
|
16
|
+
tid: number;
|
|
17
|
+
did: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ricarica i workitem di pratica dell'utente. Con `force` ignora la finestra
|
|
21
|
+
* anti-raffica (da usare dopo un'operazione che li ha modificati).
|
|
22
|
+
*/
|
|
23
|
+
export declare const refreshCaseFlowApproveData: (force?: boolean) => Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Workitem di pratica pendenti su quel documento (lettura sincrona dalla cache).
|
|
26
|
+
*
|
|
27
|
+
* TID/DID vanno NORMALIZZATI: pur essendo tipati `number`, arrivano come stringhe
|
|
28
|
+
* quando il documento è aperto da una griglia (righe di datagrid) — per lo stesso
|
|
29
|
+
* motivo il resto della libreria fa `Number(TID)`/`Number(DID)` in ogni confronto.
|
|
30
|
+
* Senza normalizzazione il confronto stretto falliva, e l'attività risultava
|
|
31
|
+
* assente aprendo il documento dalla ricerca mentre compariva dal widget "Per te".
|
|
32
|
+
*/
|
|
33
|
+
export declare const getCaseFlowWorkItemsByDcmt: (tid?: number | string, did?: number | string) => CaseFlowDcmtWorkItem[];
|
|
34
|
+
/** Svuota la cache (logout / cambio archivio). */
|
|
35
|
+
export declare const clearCaseFlowApproveData: () => void;
|
|
36
|
+
/** Completa il workitem di pratica e ricarica la cache. */
|
|
37
|
+
export declare const completeCaseFlowWorkItem: (item: CaseFlowDcmtWorkItem, comment?: string) => Promise<void>;
|
|
38
|
+
/** Rifiuta il workitem di pratica (motivo obbligatorio) e ricarica la cache. */
|
|
39
|
+
export declare const rejectCaseFlowWorkItem: (item: CaseFlowDcmtWorkItem, reason: string) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Completa l'attività di FIRMA di una pratica sul documento indicato, se esiste.
|
|
42
|
+
* La chiama il viewer di firma quando la firma è riuscita: è il gemello di quanto
|
|
43
|
+
* già avviene per i workitem del workflow legacy.
|
|
44
|
+
* @returns true se un'attività è stata completata.
|
|
45
|
+
*/
|
|
46
|
+
export declare const completeCaseFlowSignatureForDcmt: (tid: number | string, did: number | string, comment?: string) => Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Attività di pratica sul documento indicato. Senza sessione o senza attività
|
|
49
|
+
* l'elenco è vuoto e nulla cambia nella UI.
|
|
50
|
+
*/
|
|
51
|
+
export declare const useCaseFlowApprove: (tid?: number | string, did?: number | string) => {
|
|
52
|
+
caseFlowWorkItems: CaseFlowDcmtWorkItem[];
|
|
53
|
+
refreshCaseFlowApprove: (force?: boolean) => Promise<void>;
|
|
54
|
+
completeCaseFlowWorkItem: (item: CaseFlowDcmtWorkItem, comment?: string) => Promise<void>;
|
|
55
|
+
rejectCaseFlowWorkItem: (item: CaseFlowDcmtWorkItem, reason: string) => Promise<void>;
|
|
56
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { CaseFlowService } from '../services/caseflow/CaseFlowService';
|
|
4
|
+
import { getWorkItemTargetDoc, isMoreInfoWorkItem, isSignatureWorkItem } from '../services/caseflow/caseFlowWorkItemUtils';
|
|
5
|
+
const CASEFLOW_APPROVE_CHANGED_EVENT = 'onCaseFlowApproveChange';
|
|
6
|
+
let cache = [];
|
|
7
|
+
let inFlight;
|
|
8
|
+
let lastLoadedAt = 0;
|
|
9
|
+
/**
|
|
10
|
+
* Finestra minima fra due ricariche: il form del documento chiede un refresh a
|
|
11
|
+
* ogni apertura e la lista è una scansione delle istanze, non una query puntuale.
|
|
12
|
+
*/
|
|
13
|
+
const MIN_RELOAD_INTERVAL_MS = 15000;
|
|
14
|
+
const notifyChanged = () => {
|
|
15
|
+
if (typeof window === 'undefined')
|
|
16
|
+
return;
|
|
17
|
+
window.dispatchEvent(new CustomEvent(CASEFLOW_APPROVE_CHANGED_EVENT));
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Ricarica la cache: i workitem pendenti dell'utente, risolti sul documento su
|
|
21
|
+
* cui lavorano. Le richieste di informazioni sono escluse (si rispondono nella
|
|
22
|
+
* pratica, non sul documento) come i workitem senza documento.
|
|
23
|
+
*/
|
|
24
|
+
const reload = async () => {
|
|
25
|
+
const userId = SDK_Globals.tmSession?.SessionDescr?.userID;
|
|
26
|
+
if (userId == null) {
|
|
27
|
+
cache = [];
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const groups = await CaseFlowService.getMyPendingWorkItems(userId);
|
|
31
|
+
const resolved = [];
|
|
32
|
+
for (const { caseflow, workItems } of groups) {
|
|
33
|
+
// Le richieste di informazioni si rispondono nella pratica, non sul documento.
|
|
34
|
+
const relevant = workItems.filter(wi => !isMoreInfoWorkItem(wi));
|
|
35
|
+
if (relevant.length === 0)
|
|
36
|
+
continue;
|
|
37
|
+
// Il TID dell'azione è autorato sul TEMPLATE e non materializzato
|
|
38
|
+
// sull'istanza: senza template risolto il documento non è calcolabile.
|
|
39
|
+
if (caseflow.cftid != null) {
|
|
40
|
+
await CaseFlowService.getTemplate(caseflow.cftid);
|
|
41
|
+
}
|
|
42
|
+
// I DOCUMENTI AGGANCIATI non arrivano dalla RetrieveAll (che porta solo i
|
|
43
|
+
// dati delle card): serve la Retrieve completa, altrimenti `dcmts` è vuoto
|
|
44
|
+
// e nessun workitem risulterebbe associato a un documento.
|
|
45
|
+
let instance = caseflow;
|
|
46
|
+
if ((instance.dcmts?.length ?? 0) === 0 && instance.id != null) {
|
|
47
|
+
instance = (await CaseFlowService.getCaseflow(instance.id, instance.cftid)) ?? instance;
|
|
48
|
+
}
|
|
49
|
+
for (const wi of relevant) {
|
|
50
|
+
const target = getWorkItemTargetDoc(instance, wi);
|
|
51
|
+
if (!target)
|
|
52
|
+
continue;
|
|
53
|
+
resolved.push({ caseflow: instance, workItem: wi, tid: target.tid, did: target.did });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
cache = resolved;
|
|
57
|
+
lastLoadedAt = Date.now();
|
|
58
|
+
// Diagnostica del bring-up: se il Toppy non compare, qui si vede a che punto
|
|
59
|
+
// la catena si interrompe (nessun workitem / nessun documento risolto).
|
|
60
|
+
// Rimuovibile una volta stabilizzato il flusso.
|
|
61
|
+
console.debug('[CaseFlow] attività su documenti:', {
|
|
62
|
+
istanzeConPendenti: groups.length,
|
|
63
|
+
workItemPendenti: groups.reduce((n, g) => n + g.workItems.length, 0),
|
|
64
|
+
risolteSuDocumento: resolved.length,
|
|
65
|
+
documenti: resolved.map(r => `${r.tid}/${r.did}`),
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Ricarica i workitem di pratica dell'utente. Con `force` ignora la finestra
|
|
70
|
+
* anti-raffica (da usare dopo un'operazione che li ha modificati).
|
|
71
|
+
*/
|
|
72
|
+
export const refreshCaseFlowApproveData = async (force = false) => {
|
|
73
|
+
if (inFlight)
|
|
74
|
+
return inFlight;
|
|
75
|
+
if (!force && lastLoadedAt > 0 && Date.now() - lastLoadedAt < MIN_RELOAD_INTERVAL_MS)
|
|
76
|
+
return;
|
|
77
|
+
inFlight = reload()
|
|
78
|
+
.catch(error => { console.error('Errore nel caricare le attività di pratica sui documenti', error); })
|
|
79
|
+
.finally(() => { inFlight = undefined; notifyChanged(); });
|
|
80
|
+
return inFlight;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Workitem di pratica pendenti su quel documento (lettura sincrona dalla cache).
|
|
84
|
+
*
|
|
85
|
+
* TID/DID vanno NORMALIZZATI: pur essendo tipati `number`, arrivano come stringhe
|
|
86
|
+
* quando il documento è aperto da una griglia (righe di datagrid) — per lo stesso
|
|
87
|
+
* motivo il resto della libreria fa `Number(TID)`/`Number(DID)` in ogni confronto.
|
|
88
|
+
* Senza normalizzazione il confronto stretto falliva, e l'attività risultava
|
|
89
|
+
* assente aprendo il documento dalla ricerca mentre compariva dal widget "Per te".
|
|
90
|
+
*/
|
|
91
|
+
export const getCaseFlowWorkItemsByDcmt = (tid, did) => {
|
|
92
|
+
const t = Number(tid);
|
|
93
|
+
const d = Number(did);
|
|
94
|
+
if (!Number.isFinite(t) || !Number.isFinite(d))
|
|
95
|
+
return [];
|
|
96
|
+
return cache.filter(r => Number(r.tid) === t && Number(r.did) === d);
|
|
97
|
+
};
|
|
98
|
+
/** Svuota la cache (logout / cambio archivio). */
|
|
99
|
+
export const clearCaseFlowApproveData = () => {
|
|
100
|
+
cache = [];
|
|
101
|
+
lastLoadedAt = 0;
|
|
102
|
+
notifyChanged();
|
|
103
|
+
};
|
|
104
|
+
/** Completa il workitem di pratica e ricarica la cache. */
|
|
105
|
+
export const completeCaseFlowWorkItem = async (item, comment) => {
|
|
106
|
+
if (item.caseflow.id == null || item.workItem.id == null)
|
|
107
|
+
return;
|
|
108
|
+
await CaseFlowService.completeWorkItem(item.caseflow.id, item.workItem.id, comment?.trim() || undefined);
|
|
109
|
+
await refreshCaseFlowApproveData(true);
|
|
110
|
+
};
|
|
111
|
+
/** Rifiuta il workitem di pratica (motivo obbligatorio) e ricarica la cache. */
|
|
112
|
+
export const rejectCaseFlowWorkItem = async (item, reason) => {
|
|
113
|
+
if (item.caseflow.id == null || item.workItem.id == null)
|
|
114
|
+
return;
|
|
115
|
+
await CaseFlowService.rejectWorkItem(item.caseflow.id, item.workItem.id, reason);
|
|
116
|
+
await refreshCaseFlowApproveData(true);
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Completa l'attività di FIRMA di una pratica sul documento indicato, se esiste.
|
|
120
|
+
* La chiama il viewer di firma quando la firma è riuscita: è il gemello di quanto
|
|
121
|
+
* già avviene per i workitem del workflow legacy.
|
|
122
|
+
* @returns true se un'attività è stata completata.
|
|
123
|
+
*/
|
|
124
|
+
export const completeCaseFlowSignatureForDcmt = async (tid, did, comment) => {
|
|
125
|
+
const target = getCaseFlowWorkItemsByDcmt(tid, did).find(r => isSignatureWorkItem(r.workItem));
|
|
126
|
+
if (!target)
|
|
127
|
+
return false;
|
|
128
|
+
await completeCaseFlowWorkItem(target, comment);
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Attività di pratica sul documento indicato. Senza sessione o senza attività
|
|
133
|
+
* l'elenco è vuoto e nulla cambia nella UI.
|
|
134
|
+
*/
|
|
135
|
+
export const useCaseFlowApprove = (tid, did) => {
|
|
136
|
+
const readItems = useCallback(() => getCaseFlowWorkItemsByDcmt(tid, did), [tid, did]);
|
|
137
|
+
const [caseFlowWorkItems, setCaseFlowWorkItems] = useState(readItems);
|
|
138
|
+
useEffect(() => { setCaseFlowWorkItems(readItems()); }, [readItems]);
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const handleChange = () => setCaseFlowWorkItems(readItems());
|
|
141
|
+
window.addEventListener(CASEFLOW_APPROVE_CHANGED_EVENT, handleChange);
|
|
142
|
+
return () => window.removeEventListener(CASEFLOW_APPROVE_CHANGED_EVENT, handleChange);
|
|
143
|
+
}, [readItems]);
|
|
144
|
+
// All'apertura di un documento la cache può essere vecchia (attività assegnate
|
|
145
|
+
// dopo l'ultimo caricamento) o non ancora popolata.
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (tid == null || did == null)
|
|
148
|
+
return;
|
|
149
|
+
void refreshCaseFlowApproveData();
|
|
150
|
+
}, [tid, did]);
|
|
151
|
+
return {
|
|
152
|
+
caseFlowWorkItems,
|
|
153
|
+
refreshCaseFlowApprove: refreshCaseFlowApproveData,
|
|
154
|
+
completeCaseFlowWorkItem,
|
|
155
|
+
rejectCaseFlowWorkItem,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
@@ -3,6 +3,7 @@ import { UserDescriptor } from '@topconsultnpm/sdk-ts';
|
|
|
3
3
|
export declare const useDataUserIdItem: () => {
|
|
4
4
|
loadUsersAsync: (userIDs: Set<number>) => Promise<void>;
|
|
5
5
|
getUserItem: (userId: number) => UserDescriptor | undefined;
|
|
6
|
+
getCompleteUserName: (domain: string | undefined, name: string | undefined) => string | undefined;
|
|
6
7
|
clearCache: () => void;
|
|
7
8
|
hasUser: (userId: number) => boolean;
|
|
8
9
|
usersCache: React.MutableRefObject<Map<number, UserDescriptor>>;
|
|
@@ -105,6 +105,7 @@ interface UseDocumentOperationsProps {
|
|
|
105
105
|
}
|
|
106
106
|
export interface UseDocumentOperationsResult {
|
|
107
107
|
operationItems: Array<TMContextMenuItemProps>;
|
|
108
|
+
selectedDcmtInfos: Array<DcmtInfo>;
|
|
108
109
|
renderFloatingBar: React.ReactNode;
|
|
109
110
|
renderDcmtOperations: React.ReactNode;
|
|
110
111
|
features: {
|
|
@@ -118,6 +119,7 @@ export interface UseDocumentOperationsResult {
|
|
|
118
119
|
closeDcmtFormHandler: () => void;
|
|
119
120
|
handleSignApprove: () => void;
|
|
120
121
|
showSearchTMDatagrid: boolean;
|
|
122
|
+
showDcmtTypesSelection: boolean;
|
|
121
123
|
showExportForm: boolean;
|
|
122
124
|
checkoutInfo: UseCheckInOutOperationsReturn;
|
|
123
125
|
relatedDocumentsInfo: UseRelatedDocumentsReturn;
|
|
@@ -21,10 +21,11 @@ import { useDcmtOperations } from "./useDcmtOperations";
|
|
|
21
21
|
import useFloatingBarPinnedItems from "./useFloatingBarPinnedItems";
|
|
22
22
|
import { useInputAttachmentsDialog, useInputCvtFormatDialog } from "./useInputDialog";
|
|
23
23
|
import { useRelatedDocuments } from "./useRelatedDocuments";
|
|
24
|
-
import { convertSearchResultDescriptorToFileItems, dcmtsFileCachePreview, getDcmtCicoStatus, getMoreInfoTasksForDocument, IconActivity, IconArchiveDetail, IconArchiveDoc, IconArchiveMaster, IconBatchUpdate, IconCheck, IconCheckFile, IconCheckIn, IconCircleInfo, IconCloseCircle, IconConvertFilePdf, IconCopy, IconCustom, IconDelete, IconDetailDcmts, IconDotsVerticalCircleOutline, IconDownload, IconEdit, IconExportTo, IconFileDots, IconHide, IconInfo, IconMenuCAArchive, IconMoveToFolder, IconPair, IconPin, IconPlatform, IconPreview, IconRelation, IconSearch, IconShare, IconSharedDcmt, IconShow, IconSignaturePencil, IconStar, IconSubstFile, IconUndo, IconUnpair, IconUserGroupOutline, isConvertibleToPdfExt, isPdfEditorAvailable, S4T_USER_REGISTRY_MASTER, SDKUI_Globals, SDKUI_Localizator, searchResultToMetadataValues, TMImageLibrary, IconCertificateBadge } from '../helper';
|
|
24
|
+
import { convertSearchResultDescriptorToFileItems, dcmtsFileCachePreview, getDcmtCicoStatus, getMoreInfoTasksForDocument, IconActivity, IconArchiveDetail, IconArchiveDoc, IconArchiveMaster, IconBatchUpdate, IconCheck, IconCheckFile, IconCheckIn, IconCircleInfo, IconCloseCircle, IconConvertFilePdf, IconCopy, IconCustom, IconDelete, IconDetailDcmts, IconDotsVerticalCircleOutline, IconDownload, IconEdit, IconExportTo, IconFileDots, IconHide, IconInfo, IconMenuCAArchive, IconMoveToFolder, IconPair, IconPin, IconPlatform, IconPreview, IconRelation, IconSearch, IconShare, IconSharedDcmt, IconShow, IconSignaturePencil, IconStar, IconSubstFile, IconUndo, IconUnpair, IconUserGroupOutline, isConvertibleToPdfExt, isPdfEditorAvailable, S4T_USER_REGISTRY_MASTER, SDKUI_Globals, SDKUI_Localizator, searchResultToMetadataValues, TMImageLibrary, IconCertificateBadge, IconArchiveMultipleDetailDocuments } from '../helper';
|
|
25
25
|
import { isXMLFileExt } from "../helper/dcmtsHelper";
|
|
26
26
|
import TMCopyToFolderForm from "../components/features/documents/TMCopyToFolderForm";
|
|
27
27
|
import TMMergeToPdfForm from "../components/features/documents/TMMergeToPdfForm";
|
|
28
|
+
import TMMultiMasterDetailDcmtsForm from "../components/features/documents/TMMultiMasterDetailDcmtsForm";
|
|
28
29
|
export const getSelectedDcmtsOrFocused = (selectedItems, focusedItem, fileFormat) => {
|
|
29
30
|
if (selectedItems.length <= 0 && !focusedItem)
|
|
30
31
|
return [];
|
|
@@ -152,6 +153,7 @@ export const useDocumentOperations = (props) => {
|
|
|
152
153
|
const [currentCustomButton, setCurrentCustomButton] = useState();
|
|
153
154
|
// State to control the visibility of the details form
|
|
154
155
|
const [showSearchTMDatagrid, setShowSearchTMDatagrid] = useState(false);
|
|
156
|
+
const [showDcmtTypesSelection, setShowDcmtTypesSelection] = useState(false);
|
|
155
157
|
const [secondaryMasterDcmts, setSecondaryMasterDcmts] = useState([]);
|
|
156
158
|
const [isOpenSharedArchive, setIsOpenSharedArchive] = useState(false);
|
|
157
159
|
const [sharedDcmtFile, setSharedDcmtFile] = useState(undefined);
|
|
@@ -169,6 +171,7 @@ export const useDocumentOperations = (props) => {
|
|
|
169
171
|
// State to control modal opening for master/detail documents
|
|
170
172
|
const [isOpenDetailsModal, setIsOpenDetailsModal] = useState(false);
|
|
171
173
|
const [isOpenMasterModal, setIsOpenMasterModal] = useState(false);
|
|
174
|
+
const [isOpenMultiDetailModal, setIsOpenMultiDetailModal] = useState(false);
|
|
172
175
|
const openDetailDcmtsFormHandler = (value) => { setIsOpenDetails(value); };
|
|
173
176
|
const openMasterDcmtsFormHandler = (value) => { setIsOpenMaster(value); };
|
|
174
177
|
const openDetailDcmtsModalHandler = (value) => { setIsOpenDetailsModal(value); };
|
|
@@ -907,10 +910,18 @@ export const useDocumentOperations = (props) => {
|
|
|
907
910
|
id: 'rel-ark-det',
|
|
908
911
|
icon: _jsx(IconArchiveDetail, {}),
|
|
909
912
|
name: SDKUI_Localizator.ArchiveDetailDocument,
|
|
910
|
-
operationType: '
|
|
911
|
-
disabled: canArchiveDetailRelation !== true,
|
|
913
|
+
operationType: 'singleRow',
|
|
914
|
+
disabled: canArchiveDetailRelation !== true || isDisabledForMultiRow(),
|
|
912
915
|
onClick: async () => await archiveDetailDocuments(selectedDcmtInfos?.[0]?.TID)
|
|
913
916
|
},
|
|
917
|
+
{
|
|
918
|
+
id: 'multi-detail',
|
|
919
|
+
icon: _jsx(IconArchiveMultipleDetailDocuments, {}),
|
|
920
|
+
name: SDKUI_Localizator.ArchiveMultipleDetailDocuments,
|
|
921
|
+
operationType: 'singleRow',
|
|
922
|
+
disabled: canArchiveDetailRelation !== true || isDisabledForMultiRow(),
|
|
923
|
+
onClick: () => setIsOpenMultiDetailModal(true),
|
|
924
|
+
},
|
|
914
925
|
{
|
|
915
926
|
id: 'rel-mst',
|
|
916
927
|
icon: _jsx(IconDetailDcmts, { transform: 'scale(-1, 1)' }),
|
|
@@ -1054,6 +1065,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1054
1065
|
]
|
|
1055
1066
|
};
|
|
1056
1067
|
};
|
|
1068
|
+
const canToggleDcmtTypesSelection = !isMobile && context === SearchResultContext.WORKFLOW_APPROVE;
|
|
1057
1069
|
const otherOperationsMenuItem = () => {
|
|
1058
1070
|
return {
|
|
1059
1071
|
id: 'oth',
|
|
@@ -1085,7 +1097,15 @@ export const useDocumentOperations = (props) => {
|
|
|
1085
1097
|
disabled: false,
|
|
1086
1098
|
onClick: () => setShowFloatingBar(prev => !prev)
|
|
1087
1099
|
}]
|
|
1088
|
-
: [])
|
|
1100
|
+
: []),
|
|
1101
|
+
{
|
|
1102
|
+
id: 'oth-dcmt-types',
|
|
1103
|
+
icon: showDcmtTypesSelection ? _jsx(IconHide, {}) : _jsx(IconShow, {}),
|
|
1104
|
+
name: showDcmtTypesSelection ? SDKUI_Localizator.HideDcmtTypes : SDKUI_Localizator.ShowDcmtTypes,
|
|
1105
|
+
visible: canToggleDcmtTypesSelection,
|
|
1106
|
+
disabled: false,
|
|
1107
|
+
onClick: () => setShowDcmtTypesSelection(prev => !prev)
|
|
1108
|
+
}
|
|
1089
1109
|
]
|
|
1090
1110
|
};
|
|
1091
1111
|
};
|
|
@@ -1381,7 +1401,8 @@ export const useDocumentOperations = (props) => {
|
|
|
1381
1401
|
onRefreshBlogDatagrid,
|
|
1382
1402
|
onRefreshPreviewDatagrid
|
|
1383
1403
|
}, fetchRemoteCertificates: fetchRemoteCertificates, graphometricManager: graphometricManager })) }), (showHistory && dtd && selectedDcmtInfos.length > 0) && _jsx(TMViewHistoryDcmt, { fromDTD: dtd, deviceType: deviceType, inputDcmt: selectedDcmtInfos[0], onClose: hideHistoryCallback, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), (commentFormState.show && selectedDcmtInfos.length > 0) && _jsx(TMBlogCommentForm, { context: { engine: 'SearchEngine', object: { tid: selectedDcmtInfos[0].TID, did: selectedDcmtInfos[0].DID } }, onClose: hideCommentFormCallback, refreshCallback: onRefreshBlog, participants: [], showAttachmentsSection: true, allArchivedDocumentsFileItems: convertSearchResultDescriptorToFileItems(currentSearchResults ?? []), isCommentRequired: commentFormState.isRequired, removeAndEditAttachment: commentFormState.removeAndEditAttachment, selectedAttachmentDid: [Number(selectedDcmtInfos[0].DID)] }), (showCheckoutInformationForm && dtd && selectedDcmtInfos.length > 0) &&
|
|
1384
|
-
_jsx(TMDcmtCheckoutInfoForm, { dtdName: dtd.name ?? SDKUI_Localizator.SearchResult, selectedDcmtOrFocused: selectedDcmtInfos[0], onClose: hideCheckoutInformationFormCallback }), isOpenDetailsModal && _jsx(TMModal, { width: "95%", height: "95%", onClose: () => setIsOpenDetailsModal(false), title: SDKUI_Localizator.Relations, children: _jsx(TMMasterDetailDcmts, { ...masterDetailDetailsCommonProps, onBack: () => setIsOpenDetailsModal(false) }) }), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDetails, children: isOpenDetails && _jsx(TMMasterDetailDcmts, { ...masterDetailDetailsCommonProps, onBack: () => setIsOpenDetails(false) }) }),
|
|
1404
|
+
_jsx(TMDcmtCheckoutInfoForm, { dtdName: dtd.name ?? SDKUI_Localizator.SearchResult, selectedDcmtOrFocused: selectedDcmtInfos[0], onClose: hideCheckoutInformationFormCallback }), isOpenDetailsModal && _jsx(TMModal, { width: "95%", height: "95%", onClose: () => setIsOpenDetailsModal(false), title: SDKUI_Localizator.Relations, children: _jsx(TMMasterDetailDcmts, { ...masterDetailDetailsCommonProps, onBack: () => setIsOpenDetailsModal(false) }) }), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDetails, children: isOpenDetails && _jsx(TMMasterDetailDcmts, { ...masterDetailDetailsCommonProps, onBack: () => setIsOpenDetails(false) }) }), (isOpenMultiDetailModal && dtd) &&
|
|
1405
|
+
_jsx(TMMultiMasterDetailDcmtsForm, { dtd: dtd, masterDcmt: selectedDcmtInfos[0], onClose: () => setIsOpenMultiDetailModal(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showDcmtFormSidebar: showDcmtFormSidebar, showTodoDcmtForm: showTodoDcmtForm, openFileUploaderPdfEditor: openFileUploaderPdfEditor, graphometricManager: graphometricManager, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, fetchRemoteCertificates: fetchRemoteCertificates, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onReferenceClick: onReferenceClick, onTaskCreateRequest: onTaskCreateRequest, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onFileOpened: onFileOpened, passToArchiveCallback: passToArchiveCallback, openWGsCopyMoveForm: openWGsCopyMoveForm }), isOpenMasterModal && _jsx(TMModal, { width: "95%", height: "95%", onClose: () => setIsOpenMasterModal(false), title: SDKUI_Localizator.Relations, children: _jsx(TMMasterDetailDcmts, { ...masterDetailMasterCommonProps, onBack: () => setIsOpenMasterModal(false) }) }), _jsxs(StyledMultiViewPanel, { "$isVisible": isOpenMaster, children: [isOpenMaster && _jsx(TMMasterDetailDcmts, { ...masterDetailMasterCommonProps, onBack: () => setIsOpenMaster(false) }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
|
|
1385
1406
|
return (_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { ...masterDetailMasterCommonProps, inputDcmts: [dcmt], allowNavigation: false, onBack: () => handleRemoveItem(dcmt.TID, dcmt.DID) }) }, `${index}-${dcmt.DID}`));
|
|
1386
1407
|
})] }), isOpenArchiveRelationForm && _jsx(TMDcmtForm, { isModal: true, titleModal: SDKUI_Localizator.Archive + ' - ' + (archiveType === 'detail' ? SDKUI_Localizator.DcmtsDetail : SDKUI_Localizator.DcmtsMaster), TID: archiveRelatedDcmtFormTID, layoutMode: LayoutModes.Ark, inputMids: archiveRelatedDcmtFormMids, showBackButton: false, allowButtonsRefs: false, onClose: () => {
|
|
1387
1408
|
setIsOpenArchiveRelationForm(false);
|
|
@@ -1446,6 +1467,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1446
1467
|
} }))] }));
|
|
1447
1468
|
return {
|
|
1448
1469
|
operationItems: operationItems(),
|
|
1470
|
+
selectedDcmtInfos,
|
|
1449
1471
|
renderFloatingBar,
|
|
1450
1472
|
renderDcmtOperations,
|
|
1451
1473
|
features: {
|
|
@@ -1454,6 +1476,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1454
1476
|
dcmtFormLayoutMode,
|
|
1455
1477
|
onDcmtFormOpenChange,
|
|
1456
1478
|
showSearchTMDatagrid,
|
|
1479
|
+
showDcmtTypesSelection,
|
|
1457
1480
|
showExportForm,
|
|
1458
1481
|
isOpenBatchUpdate,
|
|
1459
1482
|
isModifiedBatchUpdate,
|