Search code examples
javascriptreactjsmxgraphjgraph

mxGraph - Some Shapes Not Rendering Correctly in ReactJS Application


I'm creating a React component which will render a graph by using an XML string with mxGraph. The graph is rendering inside the component, but some shapes, such as circles, diamonds, and swimlanes, are not rendering correctly; they appear as simple squares or rectangles instead. This is particularly odd since some non-rectangular shapes (such as Documentation) appear correctly.

The graph is created using an edited version of jgraph's "grapheditor" tool with some customized shapes:

Customized grapheditor tool

This grapheditor tool is identical to the reference implementation, with only the addGeneralPalette() function changed in Sidebar.js to use our customized shapes:

/**
 * Adds the general palette to the sidebar.
 */
Sidebar.prototype.addGeneralPalette = function(expand)
{
    var fns = [
        this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;', 80, 80, 'Start', 'Start', null, null, 'start begin starting beginning'),
        this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;', 200, 120, 'Process', 'Process', null, null, 'process proc'),
        this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;', 200, 120, 'Template', 'Template', null, null, 'template temp'),
        this.createVertexTemplateEntry('rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;', 200, 120, 'Decision', 'Decision', null, null, 'decision decide'),
        this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;', 200, 120, 'Documentation', 'Documentation', null, null, 'documentation doc internal'),
        this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;', 280, 40, 'Action', 'Action', null, null, 'action'),
        this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ffb74d;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#fff3e0;fillColor=#FFFFFF;', 200, 120, 'Sub-Process', 'Sub-Process', null, null, 'subprocess sub-process sub'),
        this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;', 80, 80, 'End', 'End', null, null, 'end ending conclusion resolution close'),
        this.createVertexTemplateEntry('swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;', 1020, 200, 'Phase', 'Swimlane', null, null, 'swimlane organizer phase flow stage')
    ];

    this.addPaletteFunctions('general', mxResources.get('general'), (expand != null) ? expand : true, fns);
};

And editing the File > Save As function in EditorUi.js to print the graph's XML to the console so we can use it elsewhere:

/**
 * Saves the current graph under the given filename.
 */
EditorUi.prototype.save = function(name)
{
    if (name != null){
        if (this.editor.graph.isEditing()){
            this.editor.graph.stopEditing();
        }

        var xml = mxUtils.getXml(this.editor.getGraphXml());

        try{
            if (xml.length < MAX_REQUEST_SIZE){
                //Print XML to console
                console.log('The graph can be imported to mxGraph using the following XML: ');
                console.log(xml);
            }else{
                mxUtils.alert(mxResources.get('drawingTooLarge'));
                mxUtils.popup(xml);
                return;
            }

            this.editor.setModified(false);
            this.editor.setFilename(name);
            this.updateDocumentTitle();
        }catch (e){
            this.editor.setStatus(mxUtils.htmlEntities(mxResources.get('errorSavingFile')));
        }
    }
};

Exporting this graph from the grapheditor tool results in the following XML string:

<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>

Now, in my React application (wholly separate from the grapheditor tool, which is a standalone web application that doesn't interact with my React application), I take this XML string and use mxGraph to decode and render it in a React component:

import React, { Component } from "react";

//We imported mxClient et al via <script> tags in index.html
let mxGraph = window.mxGraph;
let mxUtils = window.mxUtils;
let mxEvent = window.mxEvent;
let mxRubberband = window.mxRubberband;
let mxKeyHandler = window.mxKeyHandler;
let mxCellHighlight = window.mxCellHighlight;
let mxCodec = window.mxCodec;

class App extends Component {

  componentDidMount(){
    var graph = new mxGraph(document.getElementById('divGraph'));
    var rubberband = new mxRubberband(graph);
    var keyHandler = new mxKeyHandler(graph);
    var highlight = new mxCellHighlight(graph, '#999999', 10);

    let xmlString = '<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>';
    var doc = mxUtils.parseXml(xmlString);
    var codec = new mxCodec(doc);
    codec.decode(doc.documentElement, graph.getModel());
    graph.fit();
    graph.setPanning(true);
    graph.setEnabled(false);
    graph.setHtmlLabels(true);

    //graph will listen for click events
    graph.addListener(mxEvent.CLICK, (sender, event) => {
      let cell = event.getProperty('cell');
      if(cell != null){
        //highlight the clicked cell
        highlight.highlight(graph.view.getState(cell));
      }
    });
  }

  render() {
    return (
      <div>
          <div id="divGraph"></div>
      </div>
    )
  }
}

export default App;

This React application uses the following index.html which imports the various mxGraph libraries from a local directory:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />

    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

    <script type="text/javascript">mxBasePath = './mx/src'</script>

    <script type="text/javascript" src="./mx/src/js/mxClient.js"></script>
    <script type="text/javascript" src="./mx/Init.js"></script>
    <script type="text/javascript" src="./mx/EditorUi.js"></script>
    <script type="text/javascript" src="./mx/Editor.js"></script>
    <script type="text/javascript" src="./mx/Sidebar.js"></script>
    <script type="text/javascript" src="./mx/Graph.js"></script>
    <script type="text/javascript" src="./mx/Format.js"></script>
    <script type="text/javascript" src="./mx/Shapes.js"></script>
    <script type="text/javascript" src="./mx/Actions.js"></script>
    <script type="text/javascript" src="./mx/Menus.js"></script>
    <script type="text/javascript" src="./mx/Toolbar.js"></script>
    <script type="text/javascript" src="./mx/Dialogs.js"></script>


    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

Unfortunately, when the application renders the graph, it appears like this:

incorrect rendering

I'm not entirely sure what to attribute this problem to, as I believe I've imported all of the requisite libraries such as Shapes.js and such. I've checked the mxGraph documentation and this thread about a similar issue, but importing Shapes.js as recommended in that thread did not seem to solve the issue (or I may be importing Shapes.js incorrectly).

Any insight on how to approach this problem is greatly appreciated.


Solution

  • It turns out the issue was due to the palette we created in the grapheditor's Sidebar.js file. The shapes which were not rendering correctly needed "shape=" appended to the beginning of their style string, like so:

    this.createVertexTemplateEntry('shape=ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;', 80, 80, 'Start', 'Start', null, null, 'start begin starting beginning'),
    this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;', 200, 120, 'Process', 'Process', null, null, 'process proc'),
    this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;', 200, 120, 'Template', 'Template', null, null, 'template temp'),
    this.createVertexTemplateEntry('shape=rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;', 200, 120, 'Decision', 'Decision', null, null, 'decision decide'),
    this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;', 200, 120, 'Documentation', 'Documentation', null, null, 'documentation doc internal'),
    this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;', 280, 40, 'Action', 'Action', null, null, 'action'),
    this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ffb74d;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#fff3e0;fillColor=#FFFFFF;', 200, 120, 'Sub-Process', 'Sub-Process', null, null, 'subprocess sub-process sub'),
    this.createVertexTemplateEntry('shape=ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;', 80, 80, 'End', 'End', null, null, 'end ending conclusion resolution close'),
    this.createVertexTemplateEntry('shape=swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;', 1020, 200, 'Phase', 'Swimlane', null, null, 'swimlane organizer phase flow stage')
    

    Making this change to the grapheditor tool resulted in proper XML being exported, which, when imported to the React component via mxGraph, rendered correctly.