@topconsultnpm/sdkui-react-beta 6.16.63 → 6.16.65
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/features/workflow/diagram/WFDiagram.d.ts +1 -0
- package/lib/components/features/workflow/diagram/WFDiagram.js +49 -5
- package/lib/components/features/workflow/diagram/xmlParser.d.ts +3 -2
- package/lib/components/features/workflow/diagram/xmlParser.js +23 -19
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@ import ConnectionComponent from './ConnectionComponent';
|
|
|
8
8
|
import DiagramItemComponent from './DiagramItemComponent';
|
|
9
9
|
import DiagramItemSvgContent from './DiagramItemSvgContent';
|
|
10
10
|
import { calculateArrowAngle, downloadFile, getConnectionPoint, isConnectionNonLinear, validateDiagram } from './workflowHelpers';
|
|
11
|
-
import { IconFlowChart, IconUndo, IconRestore, IconAdjust, IconCopy, IconCut, IconPaste, IconPin, IconUnpin, IconChevronRight, IconCloseOutline, IconNew, SDKUI_Localizator, generateUUID, IconExport } from '../../../../helper';
|
|
11
|
+
import { IconFlowChart, IconUndo, IconRestore, IconAdjust, IconCopy, IconCut, IconPaste, IconPin, IconUnpin, IconChevronRight, IconCloseOutline, IconNew, SDKUI_Localizator, generateUUID, IconExport, IconImport } from '../../../../helper';
|
|
12
12
|
import { TMExceptionBoxManager } from '../../../base/TMPopUp';
|
|
13
13
|
import { StyledLoadingContainer, StyledSpinner } from '../../../base/Styled';
|
|
14
14
|
import DiagramItemForm from './DiagramItemForm';
|
|
@@ -205,7 +205,7 @@ const DiagramMessage = styled.div `
|
|
|
205
205
|
color: #555;
|
|
206
206
|
text-align: center;
|
|
207
207
|
`;
|
|
208
|
-
const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel = 1, translateX = 0, translateY = 0 }) => {
|
|
208
|
+
const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel = 1, translateX = 0, translateY = 0, onDiagramImport }) => {
|
|
209
209
|
const [isLoading, setIsLoading] = useState(true);
|
|
210
210
|
const [wfDiagram, setWfDiagram] = useState(null);
|
|
211
211
|
const [selectedItems, setSelectedItems] = useState(new Set());
|
|
@@ -589,7 +589,7 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel
|
|
|
589
589
|
return;
|
|
590
590
|
}
|
|
591
591
|
}, [wfDiagram, selectedItems, selectedConnections, handleUndo, handleRedo, handleDelete, updateDiagram, handleCopy, handleCut, handlePaste, readOnly]);
|
|
592
|
-
const handleExportDiagram = useCallback(() => {
|
|
592
|
+
const handleExportDiagram = useCallback(async () => {
|
|
593
593
|
if (!wfDiagram) {
|
|
594
594
|
// Visualizza un errore se il diagramma non è stato caricato o è vuoto
|
|
595
595
|
TMExceptionBoxManager.show({ exception: new Error('Diagram not loaded.') });
|
|
@@ -597,7 +597,7 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel
|
|
|
597
597
|
}
|
|
598
598
|
try {
|
|
599
599
|
// 1. Serializza il diagramma in XML
|
|
600
|
-
const xmlString = serializeWfDiagramToXml(wfDiagram);
|
|
600
|
+
const xmlString = await serializeWfDiagramToXml(wfDiagram);
|
|
601
601
|
// 2. Determina il nome del file (usa l'ID o un UUID se non disponibile)
|
|
602
602
|
const filename = `WorkflowDiagram_${wfDiagram.Info?.ID || generateUUID()}.xml`;
|
|
603
603
|
// 3. Avvia il download (la cartella è scelta dal browser)
|
|
@@ -607,6 +607,49 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel
|
|
|
607
607
|
TMExceptionBoxManager.show({ exception: e });
|
|
608
608
|
}
|
|
609
609
|
}, [wfDiagram]); // Dipende dallo stato attuale del diagramma
|
|
610
|
+
const fileInputRef = useRef(null);
|
|
611
|
+
// Gestore dell'evento click sul bottone (apre la finestra di selezione file)
|
|
612
|
+
const handleImportDiagramClick = useCallback(() => {
|
|
613
|
+
if (fileInputRef.current) {
|
|
614
|
+
fileInputRef.current.click();
|
|
615
|
+
}
|
|
616
|
+
}, []);
|
|
617
|
+
// Gestore dell'evento di selezione file (esegue il parse e chiama il genitore)
|
|
618
|
+
const handleFileChange = useCallback((event) => {
|
|
619
|
+
const file = event.target.files?.[0];
|
|
620
|
+
if (!file) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
const reader = new FileReader();
|
|
624
|
+
reader.onload = (e) => {
|
|
625
|
+
try {
|
|
626
|
+
const xmlContent = e.target?.result;
|
|
627
|
+
// 1. Esegui il parse per validare il file.
|
|
628
|
+
// parseWfDiagramXml lancerà un errore se l'XML è invalido o malformato,
|
|
629
|
+
// intercettato nel blocco catch.
|
|
630
|
+
// NON ASSEGNIAMO wfDiagram QUI, MA CHIAMIAMO SOLO PER VERIFICA.
|
|
631
|
+
parseWfDiagramXml(xmlContent);
|
|
632
|
+
// 2. Se il parsing ha successo, comunichiamo la nuova stringa XML al genitore.
|
|
633
|
+
// Il genitore sarà responsabile di aggiornare lo stato di xmlDiagramString,
|
|
634
|
+
// il che farà re-renderizzare questo componente con il nuovo diagramma.
|
|
635
|
+
onDiagramImport?.(xmlContent);
|
|
636
|
+
// 3. Resetta l'input per permettere re-import dello stesso file
|
|
637
|
+
if (fileInputRef.current) {
|
|
638
|
+
fileInputRef.current.value = '';
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
// Gestione dell'errore di parsing (es. file non valido)
|
|
643
|
+
const errorMessage = 'Error importing diagram. Invalid XML format.';
|
|
644
|
+
TMExceptionBoxManager.show({ exception: new Error(errorMessage + `\n${error.message}`) });
|
|
645
|
+
// Resetta l'input anche in caso di errore
|
|
646
|
+
if (fileInputRef.current) {
|
|
647
|
+
fileInputRef.current.value = '';
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
reader.readAsText(file, 'UTF-8');
|
|
652
|
+
}, [onDiagramImport]);
|
|
610
653
|
const calculateConnectionPath = useCallback((connection, sourceItem, sinkItem) => {
|
|
611
654
|
const sourcePoint = getConnectionPoint(sourceItem, connection.Source.ConnectorName);
|
|
612
655
|
const sinkPoint = getConnectionPoint(sinkItem, connection.Sink.ConnectorName);
|
|
@@ -1410,7 +1453,8 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, readOnly = false, zoomLevel
|
|
|
1410
1453
|
isUndoingRedoing.current = false;
|
|
1411
1454
|
}
|
|
1412
1455
|
}, [wfDiagram]);
|
|
1413
|
-
return (_jsxs(CanvasContainer, { children: [
|
|
1456
|
+
return (_jsxs(CanvasContainer, { children: [_jsx("input", { ref: fileInputRef, type: "file", accept: ".xml" // Filtra per file XML
|
|
1457
|
+
, onChange: handleFileChange, style: { display: 'none' } }), !readOnly && (_jsxs(ToolbarContainer, { "$isCollapsed": isToolbarCollapsed, "$isFloating": isToolbarFloating, "$isToolboxVisible": isToolboxVisible, children: [_jsx(ButtonGroup, { "$isFloating": isToolbarFloating, children: _jsxs("button", { onClick: handleToggleToolboxVisibility, title: "Show toolbox", children: [_jsx(IconFlowChart, {}), !isToolbarCollapsed && _jsx("span", { children: "Mostra/nascondi toolbox" })] }) }), _jsxs(ButtonGroup, { "$isFloating": isToolbarFloating, children: [_jsxs("button", { onClick: handleUndo, disabled: historyIndex === 0, title: "Undo", children: [_jsx(IconUndo, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Undo" })] }), _jsxs("button", { onClick: handleRedo, disabled: historyIndex === wfDiagramHistory.length - 1, title: "Redo", children: [_jsx(IconUndo, { style: { transform: 'scaleX(-1)' } }), " ", !isToolbarCollapsed && _jsx("span", { children: "Redo" })] }), _jsxs("button", { onClick: handleRestore, title: "Restore", children: [_jsx(IconRestore, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Restore" })] }), _jsxs("button", { onClick: handleNew, title: "New diagram", disabled: readOnly, children: [_jsx(IconNew, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "New" })] }), _jsxs("button", { onClick: handleExportDiagram, disabled: readOnly || !wfDiagram, title: SDKUI_Localizator.Export || 'Export Diagram', children: [_jsx(IconExport, {}), _jsx("span", { children: SDKUI_Localizator.Export || 'Export' })] }), _jsxs("button", { onClick: handleImportDiagramClick, disabled: readOnly, title: SDKUI_Localizator.Import || 'Import Diagram', children: [_jsx(IconImport, {}), _jsx("span", { children: SDKUI_Localizator.Import || 'Import' })] })] }), _jsx(ButtonGroup, { "$isFloating": isToolbarFloating, children: _jsxs("button", { onClick: handleAutoAdjust, title: "Auto adjust", children: [_jsx(IconAdjust, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Auto Adjust" })] }) }), _jsxs(ButtonGroup, { "$isFloating": isToolbarFloating, children: [_jsxs("button", { onClick: handleCopy, disabled: selectedItems.size === 0, title: "Copy", children: [_jsx(IconCopy, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Copy" })] }), _jsxs("button", { onClick: handleCut, disabled: selectedItems.size === 0, title: "Cut", children: [_jsx(IconCut, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Cut" })] }), _jsxs("button", { onClick: handlePaste, disabled: copiedItems.length === 0 && copiedConnections.length === 0, title: "Paste", children: [_jsx(IconPaste, {}), " ", !isToolbarCollapsed && _jsx("span", { children: "Paste" })] })] }), _jsxs("button", { onClick: handleToggleToolbarMode, title: isToolbarFloating ? "Dock Toolbar" : "Float Toolbar", children: [isToolbarFloating ? _jsx(IconPin, {}) : _jsx(IconUnpin, {}), !isToolbarCollapsed && !isToolbarFloating && _jsx("span", { children: "Toggle Mode" })] }), !isToolbarFloating && _jsx(ToolbarToggle, { onClick: () => setIsToolbarCollapsed(!isToolbarCollapsed), title: isToolbarCollapsed ? "Expand Toolbar" : "Collapse Toolbar", children: isToolbarCollapsed ? _jsx(IconChevronRight, {}) : _jsx(IconCloseOutline, {}) })] })), !readOnly && (_jsx(ToolboxContainer, { "$isVisible": isToolboxVisible, children: isToolboxVisible && availableItemTypes.map(type => (_jsxs(ToolboxItem, { draggable: true, onDragStart: (e) => handleToolboxDragStart(e, type), onDragEnd: handleToolboxDragEnd, children: [_jsx(DiagramItemSvgContent, { itemType: type, width: 40, height: 40, isToolboxPreview: true }), _jsx("span", { children: DiagramItemTypes[type] })] }, type))) })), _jsx(SvgScrollContainer, { children: isLoading ?
|
|
1414
1458
|
(_jsxs(StyledLoadingContainer, { children: [_jsx(StyledSpinner, {}), _jsx("span", { children: `${'Caricamento diagramma'}...` })] })) : wfDiagram ? (_jsx(StyledSvg, { ref: svgRef, tabIndex: 0, onKeyDownCapture: handleKeyDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onMouseDown: handleMouseDown, onDrop: handleDropOnCanvas, onDragOver: handleDragOver, width: svgWidth, height: svgHeight, children: _jsxs(ScalableGroup, { "$scale": zoomLevel, "$translateX": translateX, "$translateY": translateY, children: [wfDiagram?.DiagramItems.map(item => (_jsx(DiagramItemComponent, { wf: wfDiagram?.Info, readOnly: readOnly, item: item, isSelected: selectedItems.has(item.ID), isCurrent: item.ID === currentSetID, onClick: handleDiagramItemClick, onDrag: handleDrag, onDragEnd: handleDragEnd, onConnectorMouseDown: handleConnectorMouseDown, onConnectorMouseUp: handleConnectorMouseUp, onDimensionsChange: handleItemDimensionsChange, onDoubleClick: handleDoubleClickItem }, item.ID))), calculatedConnections.map(connection => {
|
|
1415
1459
|
const sourceItem = wfDiagram?.DiagramItems.find(item => item.ID === connection.Source.ParentDiagramItem.ID);
|
|
1416
1460
|
const sinkItem = wfDiagram?.DiagramItems.find(item => item.ID === connection.Sink.ParentDiagramItem.ID);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { WfDiagram } from './interfaces';
|
|
2
|
-
import { CultureIDs, Severities, WFAppTypes, WorkItemSetRules, WorkItemStatus } from '@topconsultnpm/sdk-ts-beta';
|
|
2
|
+
import { CultureIDs, QueryDescriptor, Severities, WFAppTypes, WorkItemSetRules, WorkItemStatus } from '@topconsultnpm/sdk-ts-beta';
|
|
3
3
|
export declare const getCultureIDsNumber: (cultureID: CultureIDs | undefined) => number;
|
|
4
4
|
export declare const getWorkItemStatusNumber: (status: WorkItemStatus | undefined) => number;
|
|
5
5
|
export declare const getSeveritiesNumber: (severity: Severities | undefined) => number;
|
|
6
6
|
export declare const getWorkItemSetRulesNumber: (setRule: WorkItemSetRules | undefined) => number;
|
|
7
7
|
export declare const getWFAppTypesNumber: (appType: WFAppTypes | undefined) => number;
|
|
8
8
|
export declare const mapCultureIDs: (cultureIDValue: number) => CultureIDs;
|
|
9
|
+
export declare const serializeQueryDescriptorXml: (qd: QueryDescriptor | undefined) => Promise<string>;
|
|
9
10
|
export declare const parseWfDiagramXml: (xmlString: string) => WfDiagram;
|
|
10
|
-
export declare const serializeWfDiagramToXml: (wfDiagram: WfDiagram | null) => string
|
|
11
|
+
export declare const serializeWfDiagramToXml: (wfDiagram: WfDiagram | null) => Promise<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArrowSymbol } from './interfaces';
|
|
2
|
-
import { CultureIDs, Severities, WFAppTypes, WorkItemSetRules, WorkItemStatus } from '@topconsultnpm/sdk-ts-beta';
|
|
2
|
+
import { CultureIDs, SDK_Globals, Severities, WFAppTypes, WorkItemSetRules, WorkItemStatus } from '@topconsultnpm/sdk-ts-beta';
|
|
3
3
|
import { parseQueryDescriptorXml } from './queryDescriptorParser'; // Import the new parser
|
|
4
4
|
import { parseMetadataValuesXml } from './metadataParser';
|
|
5
5
|
// Funzione helper per escapare i caratteri XML speciali (necessaria per i campi stringa)
|
|
@@ -173,14 +173,17 @@ const mapWFAppTypes = (appTypeValue) => {
|
|
|
173
173
|
return WFAppTypes.None;
|
|
174
174
|
}
|
|
175
175
|
};
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (qd)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
176
|
+
export const serializeQueryDescriptorXml = async (qd) => {
|
|
177
|
+
// try {
|
|
178
|
+
if (!qd)
|
|
179
|
+
return '';
|
|
180
|
+
let xml = await SDK_Globals.tmSession?.NewDcmtPlatformEngine().UtilsSerializeQdAsync(qd) ?? '';
|
|
181
|
+
return xml;
|
|
182
|
+
// } catch (error) {
|
|
183
|
+
// console.error('Error serializing QueryDescriptor to XML:', error);
|
|
184
|
+
//TODO: gestire errore
|
|
185
|
+
// return '';
|
|
186
|
+
// }
|
|
184
187
|
};
|
|
185
188
|
// Placeholder per la serializzazione di MetadataValues in XML (DA MODIFICARE CON LA LOGICA REALE)
|
|
186
189
|
const serializeMetadataValuesXml = (values) => {
|
|
@@ -193,7 +196,6 @@ const serializeMetadataValuesXml = (values) => {
|
|
|
193
196
|
export const parseWfDiagramXml = (xmlString) => {
|
|
194
197
|
const parser = new DOMParser();
|
|
195
198
|
const xmlDoc = parser.parseFromString(xmlString, "application/xml");
|
|
196
|
-
console.log('xmlDoc', xmlDoc);
|
|
197
199
|
const wfDiagram = {
|
|
198
200
|
Info: {
|
|
199
201
|
ID: "",
|
|
@@ -337,7 +339,7 @@ export const parseWfDiagramXml = (xmlString) => {
|
|
|
337
339
|
return wfDiagram;
|
|
338
340
|
};
|
|
339
341
|
// Funzione di serializzazione (inclusa per completezza, se l'avevi)
|
|
340
|
-
export const serializeWfDiagramToXml = (wfDiagram) => {
|
|
342
|
+
export const serializeWfDiagramToXml = async (wfDiagram) => {
|
|
341
343
|
if (!wfDiagram) {
|
|
342
344
|
return '<?xml version="1.0" encoding="utf-8"?>\n<Root></Root>';
|
|
343
345
|
}
|
|
@@ -354,7 +356,8 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
|
|
|
354
356
|
}
|
|
355
357
|
// 2. Serializzazione DiagramItems
|
|
356
358
|
xml += ' <DiagramItems>\n';
|
|
357
|
-
|
|
359
|
+
// Usa Promise.all con map invece di forEach
|
|
360
|
+
for (const item of wfDiagram.DiagramItems) {
|
|
358
361
|
xml += ' <DiagramItem>\n';
|
|
359
362
|
xml += ` <ID>${escapeXml(item.ID)}</ID>\n`;
|
|
360
363
|
xml += ` <L>${item.Left}</L>\n`;
|
|
@@ -415,16 +418,17 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
|
|
|
415
418
|
xml += ` <EndWFInstance>${item.EndWFInstance}</EndWFInstance>\n`;
|
|
416
419
|
// QueryDescriptor (QD)
|
|
417
420
|
if (item.QD) {
|
|
418
|
-
|
|
419
|
-
|
|
421
|
+
let qdXmlContent = await serializeQueryDescriptorXml(item.QD);
|
|
422
|
+
let qdEscaped = escapeXml(qdXmlContent);
|
|
423
|
+
xml += ` <QD>${qdEscaped}</QD>\n`;
|
|
420
424
|
}
|
|
421
425
|
if (item.SOD)
|
|
422
426
|
xml += ` <SOD>${escapeXml(item.SOD)}</SOD>\n`;
|
|
423
427
|
// MetadataValues
|
|
424
|
-
if (item.MetadataValues) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
+
// if (item.MetadataValues && item.MetadataValues.length > 0) {
|
|
429
|
+
// const mvXmlContent = serializeMetadataValuesXml(item.MetadataValues);
|
|
430
|
+
// xml += ` <MetadataValues><![CDATA[${mvXmlContent}]]></MetadataValues>\n`;
|
|
431
|
+
// }
|
|
428
432
|
if (item.Severity !== undefined)
|
|
429
433
|
xml += ` <Severity>${getSeveritiesNumber(item.Severity)}</Severity>\n`;
|
|
430
434
|
if (item.RegAsWfInstPart !== undefined)
|
|
@@ -456,7 +460,7 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
|
|
|
456
460
|
if (item.Trunc !== undefined)
|
|
457
461
|
xml += ` <Trunc>${item.Trunc}</Trunc>\n`;
|
|
458
462
|
xml += ' </DiagramItem>\n';
|
|
459
|
-
}
|
|
463
|
+
}
|
|
460
464
|
xml += ' </DiagramItems>\n';
|
|
461
465
|
// 3. Serializzazione Connections
|
|
462
466
|
xml += ' <Connections>\n';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topconsultnpm/sdkui-react-beta",
|
|
3
|
-
"version": "6.16.
|
|
3
|
+
"version": "6.16.65",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"lib"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@topconsultnpm/sdk-ts-beta": "6.16.
|
|
42
|
+
"@topconsultnpm/sdk-ts-beta": "6.16.13",
|
|
43
43
|
"buffer": "^6.0.3",
|
|
44
44
|
"devextreme": "25.1.4",
|
|
45
45
|
"devextreme-react": "25.1.4",
|