diff --git a/README.md b/README.md index a954ef6..6c6c73d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,28 @@ -# ej2-showcase-js-json-xml-to-diagram-visualizer -A JSON/XML-to-Diagram Visualizer converts JSON or XML data into interactive diagrams, helping users easily understand data structures, hierarchies, and relationships visually +# Essential® JS 2 for JavaScript - JSON and XML to Diagram Visualizer + +A JSON/XML-to-Diagram Visualizer converts JSON or XML data into interactive diagrams, helping users easily understand data structures, hierarchies, and relationships visually. + + +## Deployment + +### Install + +* To install all dependent packages, use the below command. + +``` +npm install +``` + +### Run + +To run the sample, use the below command + +``` +npm start +``` + +## Demo + +#### https://ej2.syncfusion.com/showcase/javascript/jsonandxmltodiagramvisualizer/ + +Check all the showcase and tutorial samples from here. \ No newline at end of file diff --git a/package.json b/package.json index b4b1e55..41a861c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "terser-webpack-plugin": "^5.3.9", "webpack": "^5.88.1", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.2.1" + "webpack-dev-server": "^4.15.1" }, "dependencies": { "fast-xml-parser": "^5.2.3", diff --git a/src/hamburger-menu.js b/src/hamburger-menu.js index 6153fdd..61b602a 100644 --- a/src/hamburger-menu.js +++ b/src/hamburger-menu.js @@ -1,47 +1,46 @@ // Enable ripple effect for UI components ej.base.enableRipple(true); -export function initHamburgerMenu(getGraphCollapseState) { - // Define menu items configuration with text, id, and icon properties - const hamburgerMenuItems = [ - { text: 'Export as Image', id: 'exportImage', iconCss: 'e-icons e-export' }, - { text: 'Rotate Layout', id: 'rotateLayout', iconCss: 'e-icons e-refresh' }, - { text: 'Collapse Graph', id: 'collapseGraph', iconCss: 'e-icons e-collapse-2' } - ]; - - // Initialize dropdown button component with menu configuration - const hamburgerDropdownButton = new ej.splitbuttons.DropDownButton({ - iconCss: 'e-icons e-menu', - cssClass: 'e-caret-hide', - items: hamburgerMenuItems, - // Handle menu item selection and dispatch corresponding events - select: function(menuSelectionArgs) { - switch (menuSelectionArgs.item.id) { - case 'exportImage': - window.dispatchEvent(new CustomEvent('exportImage')); - break; - case 'rotateLayout': - window.dispatchEvent(new CustomEvent('rotateLayout')); - break; - case 'collapseGraph': - window.dispatchEvent(new CustomEvent('collapseGraph')); - updateCollapseMenuText(); - break; - } - } - }); +// Toggle menu text and icon based on current graph collapse state +export function updateCollapseMenuText(isGraphCollapsed) { + const isCurrentlyCollapsed = isGraphCollapsed; + const collapseMenuItem = hamburgerMenuItems.find(menuItem => menuItem.id === 'collapseGraph'); + if (collapseMenuItem) { + collapseMenuItem.text = isCurrentlyCollapsed ? 'Expand Graph' : 'Collapse Graph'; + collapseMenuItem.iconCss = isCurrentlyCollapsed ? 'e-icons e-expand' : 'e-icons e-collapse-2'; + hamburgerDropdownButton.items = hamburgerMenuItems; + hamburgerDropdownButton.dataBind(); + } +} +// Define menu items configuration with text, id, and icon properties +const hamburgerMenuItems = [ + { text: 'Export as Image', id: 'exportImage', iconCss: 'e-icons e-export' }, + { text: 'Rotate Layout', id: 'rotateLayout', iconCss: 'e-icons e-refresh' }, + { text: 'Collapse Graph', id: 'collapseGraph', iconCss: 'e-icons e-collapse-2' } +]; - // Toggle menu text and icon based on current graph collapse state - function updateCollapseMenuText() { - const isCurrentlyCollapsed = getGraphCollapseState(); - const collapseMenuItem = hamburgerMenuItems.find(menuItem => menuItem.id === 'collapseGraph'); - if (collapseMenuItem) { - collapseMenuItem.text = isCurrentlyCollapsed ? 'Expand Graph' : 'Collapse Graph'; - collapseMenuItem.iconCss = isCurrentlyCollapsed ? 'e-icons e-expand' : 'e-icons e-collapse-2'; - hamburgerDropdownButton.items = hamburgerMenuItems; - hamburgerDropdownButton.dataBind(); +// Initialize dropdown button component with menu configuration +const hamburgerDropdownButton = new ej.splitbuttons.DropDownButton({ + iconCss: 'e-icons e-menu', + cssClass: 'e-caret-hide', + items: hamburgerMenuItems, + // Handle menu item selection and dispatch corresponding events + select: function (menuSelectionArgs) { + switch (menuSelectionArgs.item.id) { + case 'exportImage': + window.dispatchEvent(new CustomEvent('exportImage')); + break; + case 'rotateLayout': + window.dispatchEvent(new CustomEvent('rotateLayout')); + break; + case 'collapseGraph': + window.dispatchEvent(new CustomEvent('collapseGraph')); + updateCollapseMenuText(false); + break; } } +}); +export function initHamburgerMenu(getGraphCollapseState) { // Append the hamburger menu to the designated DOM element hamburgerDropdownButton.appendTo('#hamburger-menu'); diff --git a/src/index.js b/src/index.js index dd5cf53..1bc1755 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ import { initToolBar } from "./toolbar.js"; import { initExportDetailsDialog } from "./export-details-dialog.js"; import * as monaco from "monaco-editor"; import { XMLBuilder, XMLParser } from "fast-xml-parser"; +import { updateCollapseMenuText } from "./hamburger-menu.js"; // Inject required modules into the diagram ej.diagrams.Diagram.Inject( @@ -134,6 +135,8 @@ function handleEditorContentChange() { updateEditorStatus(false); showSpinner(); } + isGraphCollapsed = false; + updateCollapseMenuText(isGraphCollapsed); } // Initializes and configures the diagram including nodes, connectors, and layout settings @@ -159,6 +162,7 @@ function initializeDiagram() { scrollSettings: { scrollLimit: "Infinity" }, getNodeDefaults: getNodeDefaults, getConnectorDefaults: getConnectorDefaults, + expandStateChange: handleExpandStateChange }); diagram.appendTo("#diagram"); } @@ -353,8 +357,8 @@ function configureParentNodeAnnotations( left: showChildItemsCount ? annotationMargin : showExpandCollapseIcon - ? -annotationMargin - : 0, + ? -annotationMargin + : 0, }; keyAnnotation.horizontalAlignment = showChildItemsCount ? "Left" : "Center"; @@ -432,6 +436,19 @@ function getConnectorDefaults(connector) { connector.targetDecorator = { shape: "None" }; return connector; } +// To handle expand and collapse +function handleExpandStateChange(args) { + const node = args.element; + if (!node || typeof node !== 'object') { + return; + } + // Check if it's a root node (no incoming edges) + const isRootNode = !node.inEdges || node.inEdges.length === 0; + if (isRootNode) { + isGraphCollapsed = !node.isExpanded; + updateCollapseMenuText(isGraphCollapsed); + } +}; // Calculates and returns the size of the node based on its content function calculateNodeSize( @@ -868,7 +885,7 @@ document.addEventListener("fileAction", function (fileActionEvent) { if (fileAction === "import") { importFromFile() .then((importedFileContent) => { - try { + try { editor.setValue(importedFileContent); // Update the Monaco editor with imported content let processedDiagramData; @@ -925,7 +942,7 @@ function importFromFile() { const fileReader = new FileReader(); fileReader.onload = (fileLoadEvent) => { resolve(fileLoadEvent.target.result); - }; + }; fileReader.onerror = () => { reject("Error reading the file"); }; @@ -970,10 +987,12 @@ document.addEventListener("viewOptionToggled", function (viewOptionEvent) { break; case "view-count": showChildItemsCount = !showChildItemsCount; + diagram.fitToPage({ mode: "Page", region: "Content", canZoomIn: true }); diagram.refresh(); break; case "expand-collapse": showExpandCollapseIcon = !showExpandCollapseIcon; + diagram.fitToPage({ mode: "Page", region: "Content", canZoomIn: true }); diagram.refresh(); break; } @@ -1090,7 +1109,7 @@ document.addEventListener("editorTypeChanged", (editorTypeChangeEvent) => { jsonToXmlObject ); // Process the original JSON data using JsonDiagramParser updateEditorStatus(true); // Update editor status to valid - } + } } catch (conversionError) { console.error("Parsing Error:", conversionError); // Log parsing errors updateEditorStatus(false); // Update status to invalid on error @@ -1103,4 +1122,6 @@ document.addEventListener("editorTypeChanged", (editorTypeChangeEvent) => { convertedDiagramData.connectors ); } + isGraphCollapsed = false; + updateCollapseMenuText(isGraphCollapsed); });