@topconsultnpm/sdkui-react-beta 6.16.63 → 6.16.64

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.
@@ -6,6 +6,7 @@ interface IWFDiagramProps {
6
6
  translateX?: number;
7
7
  translateY?: number;
8
8
  currentSetID?: string;
9
+ onDiagramImport?: (newXmlString: string) => void;
9
10
  }
10
11
  declare const WFDiagram: React.FC<IWFDiagramProps>;
11
12
  export default WFDiagram;
@@ -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());
@@ -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: [!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' })] })] }), _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 ?
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
11
  export declare const serializeWfDiagramToXml: (wfDiagram: WfDiagram | null) => 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,13 @@ const mapWFAppTypes = (appTypeValue) => {
173
173
  return WFAppTypes.None;
174
174
  }
175
175
  };
176
- // Placeholder per la serializzazione di QueryDescriptor in XML (DA MODIFICARE CON LA LOGICA REALE)
177
- const serializeQueryDescriptorXml = (qd) => {
178
- if (qd) {
179
- // Logica di serializzazione reale qui, ad esempio:
180
- // return `<ID>${qd.ID}</ID><Query>${escapeXml(qd.Query)}</Query>...`
181
- return '[QUERY_DESCRIPTOR_XML_PLACEHOLDER]';
182
- }
183
- return '';
176
+ export const serializeQueryDescriptorXml = async (qd) => {
177
+ console.log('serializeQueryDescriptorXml qd', qd);
178
+ if (!qd)
179
+ return '';
180
+ let xml = await SDK_Globals.tmSession?.NewDcmtPlatformEngine().UtilsSerializeQdAsync(qd) ?? '';
181
+ console.log('serializeQueryDescriptorXml xml', xml);
182
+ return xml;
184
183
  };
185
184
  // Placeholder per la serializzazione di MetadataValues in XML (DA MODIFICARE CON LA LOGICA REALE)
186
185
  const serializeMetadataValuesXml = (values) => {
@@ -341,6 +340,7 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
341
340
  if (!wfDiagram) {
342
341
  return '<?xml version="1.0" encoding="utf-8"?>\n<Root></Root>';
343
342
  }
343
+ console.log('qd', escapeXml('<QueryDescriptor xmlns="http://schemas.datacontract.org/2004/07/TopConsult.TM5.Server.WEBSDK.Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Description i:nil="true"/><ID>0</ID><Name i:nil="true"/><Fetch>0</Fetch><From><TID>8601</TID></From><IsDistinct>false</IsDistinct><IsLexProt>0</IsLexProt><Join i:nil="true"/><MaxDcmtsToBeReturned>1000</MaxDcmtsToBeReturned><Offset>0</Offset><OrderBy i:nil="true"/><Params i:nil="true"/><Select><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601001</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601002</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601006</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601003</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601004</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem><SelectItem><Alias i:nil="true"/><As i:nil="true"/><Function>None</Function><MID>8601005</MID><TID>8601</TID><Visibility>Visible</Visibility></SelectItem></Select><Where><WhereItem><Alias i:nil="true"/><LeftBrackets>(</LeftBrackets><MID>8601006</MID><Operator>GreaterOrEqual</Operator><Or>false</Or><RightBrackets>)</RightBrackets><TID>8601</TID><Value1>100</Value1><Value2 i:nil="true"/></WhereItem></Where></QueryDescriptor>'));
344
344
  let xml = '<?xml version="1.0" encoding="utf-8"?>\n';
345
345
  xml += '<Root>\n';
346
346
  // 1. Serializzazione WfInfo
@@ -354,7 +354,7 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
354
354
  }
355
355
  // 2. Serializzazione DiagramItems
356
356
  xml += ' <DiagramItems>\n';
357
- wfDiagram.DiagramItems.forEach(item => {
357
+ wfDiagram.DiagramItems.forEach(async (item) => {
358
358
  xml += ' <DiagramItem>\n';
359
359
  xml += ` <ID>${escapeXml(item.ID)}</ID>\n`;
360
360
  xml += ` <L>${item.Left}</L>\n`;
@@ -414,14 +414,12 @@ export const serializeWfDiagramToXml = (wfDiagram) => {
414
414
  if (item.EndWFInstance !== undefined)
415
415
  xml += ` <EndWFInstance>${item.EndWFInstance}</EndWFInstance>\n`;
416
416
  // QueryDescriptor (QD)
417
- if (item.QD) {
418
- const qdXmlContent = serializeQueryDescriptorXml(item.QD);
419
- xml += ` <QD><![CDATA[${qdXmlContent}]]></QD>\n`;
420
- }
417
+ if (item.QD)
418
+ xml += ` <QD>${escapeXml(await serializeQueryDescriptorXml(item.QD))}</QD>\n`;
421
419
  if (item.SOD)
422
420
  xml += ` <SOD>${escapeXml(item.SOD)}</SOD>\n`;
423
421
  // MetadataValues
424
- if (item.MetadataValues) {
422
+ if (item.MetadataValues && item.MetadataValues.length > 0) {
425
423
  const mvXmlContent = serializeMetadataValuesXml(item.MetadataValues);
426
424
  xml += ` <MetadataValues><![CDATA[${mvXmlContent}]]></MetadataValues>\n`;
427
425
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.16.63",
3
+ "version": "6.16.64",
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.12",
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",