This repository has been archived by the owner on Jul 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
/
orchestrate_dsx_workflow.json
1 lines (1 loc) · 27.2 KB
/
orchestrate_dsx_workflow.json
1
[{"id":"ba26b266.d9f99","type":"websocket in","z":"77c7bfd3.0321a","name":"","server":"d9ce3e57.a0ae","client":"","x":150,"y":200,"wires":[["32d2f012.879fb","acd3167d.fb3e1"]]},{"id":"acd3167d.fb3e1","type":"function","z":"77c7bfd3.0321a","name":"","func":"msg._session=\"\";\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":200,"wires":[["c4b135b5.16fea8"]]},{"id":"32d2f012.879fb","type":"debug","z":"77c7bfd3.0321a","name":"Debug msgs","active":true,"console":"false","complete":"payload","x":330,"y":120,"wires":[]},{"id":"c4b135b5.16fea8","type":"websocket out","z":"77c7bfd3.0321a","name":"","server":"d9ce3e57.a0ae","client":"","x":660,"y":200,"wires":[]},{"id":"99a4d2a0.101068","type":"http in","z":"77c7bfd3.0321a","name":"","url":"/engg-insights","method":"get","upload":false,"swaggerDoc":"","x":154,"y":363,"wires":[["ec9ac0e1.f2d94"]]},{"id":"ec9ac0e1.f2d94","type":"template","z":"77c7bfd3.0321a","name":"HTML","field":"payload","fieldType":"msg","format":"handlebars","syntax":"plain","template":"<!DOCTYPE html>\n\n\n<html>\n\n<head>\n <title>Watson Engineering Insights</title>\n\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"/>\n <meta charset=\"utf-8\">\n\n <script src=\"https://code.jquery.com/jquery-3.2.1.min.js\"></script>\n <script src=\"http://code.jquery.com/ui/1.12.1/jquery-ui.min.js\"></script>\n\n <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">\n <link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">\n\n <script src=\"https://d3js.org/d3.v4.min.js\"></script>\n\n <style>\n .body\n {\n height: 600px;\n width:960px;\n margin-left:auto;\n margin-right:auto;\n }\n\n .header {\n font-size: 22px;\n height:40px;\n width: 960px;\n background-color: #1E90FF;\n color: white;\n padding-left:5px;\n }\n\n subHeader {\n font-size: 20px;\n font-family: \"Arial\";\n pointer-events: none;\n color: white;\n }\n\n .searchBox {\n width: 960px;\n }\n\n .searchBox select{\n width: 960px;\n }\n\n .chartDiv {\n border:1px solid black;\n width: 960px;\n height:420px;\n visibility:hidden;\n }\n\n .chartArea {\n width: 960px;\n height:390px;\n }\n\n .chartHeader{\n background-color: #F5F5F5;\n height:30px;\n width:958px;\n text-align: right;\n }\n\n .labelHeading {\n font: 18px sans-serif;\n color: black;\n float: left;\n padding-left:10px;\n padding-top:5px;\n width: 350px;\n text-align: left;\n }\n\n .arrowIcon{\n float:left;\n padding-top:2px;\n width: 100px;\n margin-left: 50px;\n visibility: hidden;\n }\n\n .arrowIcon input {\n align:center;\n border-radius: 50%;\n background-color: #C0C0C0;\n border: none;\n }\n\n .insightsOption {\n font: 16px sans-serif;\n width: 400px;\n margin-left: 8px;\n padding-top:5px;\n float: left;\n visibility: hidden;\n }\n\n .insightsOption select {\n width: 400px;\n }\n\n .goIcon{\n float:right;\n padding-top:2px;\n margin-right: 10px;\n visibility: hidden;\n }\n\n .goIcon input {\n align:center;\n border-radius: 50%;\n background-color: #C0C0C0;\n border: none;\n }\n\n .closeIcon{\n float:right;\n padding-top:2px;\n margin-right: 15px;\n visibility: hidden;\n }\n\n .closeIcon input {\n align:center;\n border-radius: 50%;\n background-color: #C0C0C0;\n border: none;\n }\n\n .links line {\n stroke: #999;\n stroke-opacity: 1.6;\n }\n\n .nodes circle {\n stroke: #fff;\n stroke-width: 1.5px;\n }\n\n text {\n font: 12px sans-serif;\n pointer-events: none;\n color: red;\n }\n\n .label {\n font: 12px sans-serif;\n pointer-events: none;\n color: red;\n }\n </style>\n</head>\n\n<script>\n //Provide node-red base url as mentioned in documentation\n var NODERED_BASE_URL = '';\n var NODERED_websocket_path = '/ws/orchestrate';\n var websocketURL = \"ws://\" + NODERED_BASE_URL + NODERED_websocket_path;\n\n $(document).ready(function() {\n\n if (NODERED_BASE_URL === '') {\n alert(\"Node-red Base URL is not provided.\")\n }\n\n var storedArtifact, storedData;\n\n //Add combo-box with valid options on page load\n var option = new Option(\"Select an option\", \"default\");\n $(\"#options\").append($(option));\n $(\"#options option[value='default']\").attr('disabled', 'disabled');\n\n $(\"#options\").append(new Option(\"Defects\", \"defect\"));\n $(\"#options\").append(new Option(\"Testcases\", \"testcase\"));\n $(\"#options\").append(new Option(\"Requirements\", \"requirement\"));\n\n $(\"#button\").attr(\"disabled\", true);\n\n $( \"#options\" ).change(function() {\n $(\"#button\").attr(\"disabled\", false);\n });\n\n $(\"#goButton\").attr(\"disabled\", true);\n $(\"#arrowButton\").attr(\"disabled\", false);\n $( \"#insights\" ).change(function() {\n $(\"#goButton\").attr(\"disabled\", false);\n });\n });\n\n //Socket communication\n var socket = new WebSocket(websocketURL);\n\n socket.onopen = function() {\n var message = {\n 'cmd': 'Client connected'\n };\n socket.send(JSON.stringify(message));\n };\n\n socket.onclose = function(){\n alert(\"Socket Closed!\");\n console.log('Connection closed');\n };\n\n socket.onerror = function(error) {\n alert(\"Socket Error!\");\n console.log('Error detected: ' + error);\n };\n\n socket.onmessage = function(e) {\n var server_message = e.data;\n responseObject = JSON.parse(server_message);\n\n if (responseObject[\"forCmd\"] == \"DefectList\"){\n showArtifact(responseObject[\"response\"]);\n }\n\n if (responseObject[\"forCmd\"] == \"TestcaseList\"){\n showArtifact(responseObject[\"response\"]);\n }\n\n if (responseObject[\"forCmd\"] == \"ReqsList\"){\n showArtifact(responseObject[\"response\"]);\n }\n\n if (responseObject[\"forCmd\"] == \"DefectRelation\"){\n drawNetworkGraph(responseObject[\"response\"], storedArtifact);\n }\n\n if (responseObject[\"forCmd\"] == \"TestcaseRelation\"){\n drawNetworkGraph(responseObject[\"response\"], storedArtifact);\n }\n\n if (responseObject[\"forCmd\"] == \"Insight\"){\n drawUpdatedBubbleChart(responseObject[\"response\"], storedArtifact);\n }\n };\n\n function send(msg) {\n wait_for_socket_connection(socket, function() {\n socket.send(msg);\n });\n };\n\n function wait_for_socket_connection(socket, callback){\n setTimeout(\n function(){\n if (socket.readyState === 1) {\n if(callback !== undefined){\n callback();\n }\n return;\n } else {\n wait_for_socket_connection(socket,callback);\n }\n }, 5);\n };\n\n //Function to search all defects/testcases/requirements to start visualization for more insight\n function doSearch() {\n\n var message;\n var val = $( \"#options\" ).val().toLowerCase();\n $(\"#chart\").css(\"visibility\", \"visible\");\n\n // if user selects defects\n if ( val.includes(\"defect\") ) {\n message = {\"cmd\":\"DefectList\"};\n send(JSON.stringify(message));\n }\n // if user selects testcases\n else if ( val.includes(\"test\") ) {\n message = {\"cmd\":\"TestcaseList\"};\n send(JSON.stringify(message));\n }\n // if user selects requirements\n else if ( val.includes(\"requirement\") ) {\n message = {\"cmd\":\"ReqsList\"};\n send(JSON.stringify(message));\n }\n else\n alert(\"Input invalid.\")\n }\n\n // Function to add more available insights option dynamically\n // as per the chosen option defects/testcases/requirements\n function addInsights(artifact){\n var defect_insight = [\n \"Get Severity 1 defects\",\n \"Get Severity 2 defects\",\n \"Get Severity 3 defects\",\n \"Get defects with no associated testcase\"\n ];\n\n var test_insight = [\n \"Get all FVT tests\",\n \"Get all SVT tests\",\n \"Get all TVT tests\",\n \"Get testcases with zero defects\"\n ];\n\n var requirement_insight = [\n \"Get requirements with zero defect\",\n \"Get requirements with zero testcases\",\n \"Get requirements with >=5 defects\"\n ];\n\n var option, i;\n $(\"#insights\").empty();\n\n option = new Option(\"More Insights..\", \"default\");\n $(\"#insights\").append($(option));\n $(\"#insights option[value='default']\").attr('disabled', 'disabled');\n\n if (artifact == \"defect\") {\n for (i=0; i<defect_insight.length; i++) {\n value = \"defectInsight\"+ (i+1) ;\n option = new Option(defect_insight[i], value);\n $(\"#insights\").append($(option));\n }\n } else if(artifact == \"test\") {\n for (i=0; i<test_insight.length; i++) {\n value = \"testInsight\"+ (i+1) ;\n option = new Option(test_insight[i], value);\n $(\"#insights\").append($(option));\n }\n } else if(artifact == \"requirement\") {\n for (i=0; i<requirement_insight.length; i++) {\n value = \"requirementInsight\"+ (i+1) ;\n option = new Option(requirement_insight[i], value);\n $(\"#insights\").append($(option));\n }\n }\n }\n\n // Function to trigger - add more insights option and to draw bubble chart\n // for all defects/testcases/requirements according to the chosen option\n function showArtifact(data) {\n var artifact = data.name;\n\n if (artifact == \"defect\") {\n $(\".labelHeading\").text(\"Defects >\");\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n addInsights(artifact);\n $(\".insightsOption\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"display\", \"block\");\n $(\".closeIcon\").css(\"display\", \"none\");\n\n storedArtifact = artifact;\n storedData = data;\n drawBubbleChart(data, artifact);\n\n } else if (artifact == \"test\") {\n $(\".labelHeading\").text(\"Testcases >\");\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n addInsights(artifact);\n $(\".insightsOption\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"display\", \"block\");\n $(\".closeIcon\").css(\"display\", \"none\");\n\n storedArtifact = artifact;\n storedData = data;\n drawBubbleChart(data, artifact);\n\n } else if (artifact == \"requirement\") {\n $(\".labelHeading\").text(\"Requirements >\");\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n addInsights(artifact);\n $(\".insightsOption\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"visibility\", \"visible\");\n $(\".goIcon\").css(\"display\", \"block\");\n $(\".closeIcon\").css(\"display\", \"none\");\n\n storedArtifact = artifact;\n storedData = data;\n drawBubbleChart(data, artifact);\n }\n }\n\n // Function to draw bubble chart as per the data provided\n function drawBubbleChart(data, artifact) {\n\n // remove previous chart if any\n d3.selectAll('svg').remove();\n\n var width=960,\n height=380,\n format = d3.format(\",d\"),\n color = d3.scaleOrdinal(d3.schemeCategory10);\n\n var bubble = d3.pack()\n .size([width, height])\n .padding(1.5);\n\n var svg = d3.select(\"#chartArea\").append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .attr(\"class\", \"bubble\");\n\n var root = d3.hierarchy(classes(data))\n .sum(function(d) { return d.value; })\n .sort(function(a, b) { return b.value - a.value; });\n\n bubble(root);\n var node = svg.selectAll(\".node\")\n .data(root.children)\n .enter().append(\"g\")\n .attr(\"class\", \"node\")\n .attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; });\n\n node.append(\"title\")\n .text(function(d) {\n if (artifact == \"defect\")\n return (\"Defect ID: \" + d.data.className + \", Severity: \" + d.data.group);\n else if (artifact == \"test\")\n return (\"Testcase ID: \" + d.data.className + \", Category: \" + d.data.group);\n else if (artifact == \"requirement\")\n return (\"Requirement ID: \" + d.data.className + \", Priority: \" + d.data.group);\n });\n\n node.append(\"circle\")\n .attr(\"r\", function(d) { return d.r; })\n .style(\"fill\", function(d) {\n return color(d.data.group);\n });\n\n node.append(\"text\")\n .attr(\"dy\", \".3em\")\n .style(\"text-anchor\", \"middle\")\n .text(function(d) {\n if (artifact == \"defect\")\n return (d.data.className + \":Sev\" + d.data.group);\n else if (artifact == \"test\")\n return (d.data.className + \":\" + d.data.group);\n else if (artifact == \"requirement\")\n return (d.data.className + \":P\" + d.data.group);\n });\n\n node.on(\"click\", function(d){\n d3.event.stopPropagation();\n\n if (artifact != \"requirement\")\n storedArtifact = artifact;\n storedData = data;\n showArtifactRelations(d.data.className, artifact);\n });\n\n // Returns a flattened hierarchy containing all leaf nodes under the root.\n function classes(root) {\n var classes = [];\n\n function recurse(name, node) {\n if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });\n else classes.push({packageName: name, className: node.ID, group: node.group, value: node.size});\n }\n\n recurse(null, root);\n return {children: classes};\n }\n\n d3.select(self.frameElement).style(\"height\", height + \"px\");\n }\n\n // Function to draw updated bubble chart as per the insight query response\n function drawUpdatedBubbleChart(data, artifact) {\n\n // remove previous chart if any\n d3.selectAll('svg').remove();\n\n var width=960,\n height=380,\n format = d3.format(\",d\");\n\n var color = d3.scaleThreshold()\n .domain([0, 1, 2, 3])\n .range([\"red\", \"white\", \"#4682B4\", \"#FF8C00\", \"#228B22\"]);\n\n var bubble = d3.pack()\n .size([width, height])\n .padding(1.5);\n\n var svg = d3.select(\"#chartArea\").append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .attr(\"class\", \"bubble\");\n\n var root = d3.hierarchy(classes(data))\n .sum(function(d) { return d.value; })\n .sort(function(a, b) { return b.value - a.value; });\n\n bubble(root);\n var node = svg.selectAll(\".node\")\n .data(root.children)\n .enter().append(\"g\")\n .attr(\"class\", \"node\")\n .attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; });\n\n node.append(\"title\")\n .text(function(d) {\n if(d.data.filter != 0){\n if (artifact == \"defect\")\n return (\"Defect ID: \" + d.data.className + \", Severity: \" + d.data.group);\n else if (artifact == \"test\")\n return (\"Testcase ID: \" + d.data.className + \", Category: \" + d.data.group);\n else if (artifact == \"requirement\")\n return (\"Requirement ID: \" + d.data.className + \", Priority: \" + d.data.group);\n }\n });\n\n node.append(\"circle\")\n .attr(\"r\", function(d) { return d.r; })\n .style(\"fill\", function(d) {\n if (d.data.filter == 0) {\n return color(d.data.filter);\n } else {\n if (artifact == \"test\") {\n if (d.data.group == \"SVT\")\n return color(1);\n if (d.data.group == \"FVT\")\n return color(2);\n if (d.data.group == \"TVT\")\n return color(3);\n } else\n return color(d.data.group);\n }\n });\n\n node.append(\"text\")\n .attr(\"dy\", \".3em\")\n .style(\"text-anchor\", \"middle\")\n .text(function(d) {\n if (d.data.filter != 0) {\n if (artifact == \"defect\")\n return (d.data.className + \":Sev\" + d.data.group);\n else if (artifact == \"test\")\n return (d.data.className + \":\" + d.data.group);\n else if (artifact == \"requirement\")\n return (d.data.className + \":P\" + d.data.group);\n }\n });\n\n node.on(\"click\", function(d){\n d3.event.stopPropagation();\n\n if (artifact != \"requirement\") {\n if (d.data.filter != 0)\n showArtifactRelations(d.data.className, artifact);\n }\n });\n\n // Returns a flattened hierarchy containing all leaf nodes under the root.\n function classes(root) {\n var classes = [];\n\n function recurse(name, node) {\n if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });\n else classes.push({packageName: name, className: node.ID, group: node.group, value: node.size, filter: node.filter});\n }\n\n recurse(null, root);\n return {children: classes};\n }\n\n d3.select(self.frameElement).style(\"height\", height + \"px\");\n }\n\n // Function to get relations among artifacts from back-end using socket\n // On choosing a specific defect/testcase from the bubble chart - relationship among artifacts will be shown\n function showArtifactRelations(chosenID, artifact){\n\n if (artifact == \"defect\") {\n $(\"#labelHeading\").text(\"Defect > Testcases > Requirements\");\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n $(\".insightsOption\").css(\"visibility\", \"hidden\");\n $(\".goIcon\").css(\"display\", \"none\");\n $(\".closeIcon\").css(\"visibility\", \"visible\");\n $(\".closeIcon\").css(\"display\", \"block\");\n\n var message = {\"cmd\":\"DefectRelation\", \"ID\":chosenID};\n send(JSON.stringify(message));\n\n } else if(artifact == \"test\") {\n $(\"#labelHeading\").text(\"Testcases > Requirements\");\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n $(\".insightsOption\").css(\"visibility\", \"hidden\");\n $(\".goIcon\").css(\"display\", \"none\");\n $(\".closeIcon\").css(\"visibility\", \"visible\");\n $(\".closeIcon\").css(\"display\", \"block\");\n\n var message = {\"cmd\":\"TestcaseRelation\", \"ID\": chosenID};\n send(JSON.stringify(message));\n }\n }\n\n // Function to draw a network graph among artifacts\n // On clicking of a defect in bubble chart: defect -> testcase -> requirement relation will be shown\n // On clicking of a testcase in bubble chart: testcase -> requirement relation will be shown\n function drawNetworkGraph(graph){\n\n // remove previous chart if any\n d3.selectAll('svg').remove();\n\n var width=940,\n height=388;\n\n var linkColors = [\"green\", \"cyan\"];\n\n var svg = d3.select(\"#chartArea\").append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height);\n\n var color = d3.scaleOrdinal(d3.schemeCategory20);\n\n var simulation = d3.forceSimulation()\n .force(\"link\", d3.forceLink().id(function(d) { return d.id; }).distance(150).strength(0.1))\n .force(\"charge\", d3.forceManyBody())\n .force(\"center\", d3.forceCenter(width / 4, height / 4));\n\n var link = svg.append(\"g\")\n .attr(\"class\", \"links\")\n .selectAll(\"line\")\n .data(graph.links)\n .enter().append(\"line\")\n .attr(\"transform\", function(d) { return \"translate(\" + width / 4 + \",\" + height / 4 + \")\"; })\n .style(\"stroke\", function(d) {\n if(d.value > 0.6)\n return linkColors[0];\n else if (d.value > 0.4)\n return linkColors[1]; })\n .attr(\"stroke-width\", function(d) {\n if(d.value > 0.6)\n return (d.value * 5);\n else if (d.value > 0.4)\n return (d.value * 3);\n });\n\n link.append(\"title\")\n .text(function(d) {\n return (\"Score:\" + d.value);\n });\n\n var node = svg.append(\"g\")\n .attr(\"class\", \"nodes\")\n .selectAll(\"circle\")\n .data(graph.nodes)\n .enter().append(\"circle\")\n .attr(\"r\", 25)\n .attr(\"fill\", function(d) { return color(d.group); })\n .attr(\"transform\", function(d) { return \"translate(\" + width / 4 + \",\" + height / 4 + \")\"; })\n .call(d3.drag()\n .on(\"start\", dragstarted)\n .on(\"drag\", dragged)\n .on(\"end\", dragended));\n\n var label = svg.append(\"g\")\n .attr(\"class\", \"labels\")\n .selectAll(\"text\")\n .data(graph.nodes)\n .enter().append(\"text\")\n .attr(\"class\", \"label\")\n .attr(\"transform\", function(d) { return \"translate(\" + width / 4 + \",\" + height / 4 + \")\"; })\n .text(function(d) { return d.id; });\n\n node.append(\"title\")\n .text(function(d) {\n return (\"ID: \" + d.id);\n });\n\n simulation\n .nodes(graph.nodes)\n .on(\"tick\", ticked);\n\n simulation.force(\"link\")\n .links(graph.links);\n\n var legend = svg.selectAll(\".legend\")\n .data(linkColors)\n .enter().append(\"g\")\n .attr(\"class\", \"legend\")\n .attr(\"transform\", function(d, i) { return \"translate(0,\" + i * 20 + \")\"; });\n\n if (graph.links.length != 0) {\n legend.append(\"rect\")\n .attr(\"x\", width - 120)\n .attr(\"y\", 15 )\n .attr(\"width\", 18)\n .attr(\"height\", 3)\n .style(\"fill\", function(d,i) { return linkColors[i];});\n\n legend.append(\"text\")\n .attr(\"x\", width - 8)\n .attr(\"y\", 15)\n .attr(\"dy\", \".35em\")\n .style(\"text-anchor\", \"end\")\n .text(function(d, i) { return (i === 0) ? \"score [0.6 - 1]\" :\"score [0.4 - 0.6]\";; });\n }\n\n function ticked() {\n link\n .attr(\"x1\", function(d) { return d.source.x; })\n .attr(\"y1\", function(d) { return d.source.y; })\n .attr(\"x2\", function(d) { return d.target.x; })\n .attr(\"y2\", function(d) { return d.target.y; });\n\n node\n .attr(\"cx\", function(d) { return d.x; })\n .attr(\"cy\", function(d) { return d.y; });\n\n label\n .attr(\"x\", function(d) { return d.x - 12; })\n .attr(\"y\", function (d) { return d.y + 5; });\n }\n\n function dragstarted(d) {\n if (!d3.event.active) simulation.alphaTarget(0.3).restart();\n d.fx = d.x;\n d.fy = d.y;\n }\n\n function dragged(d) {\n d.fx = d3.event.x;\n d.fy = d3.event.y;\n }\n\n function dragended(d) {\n if (!d3.event.active) simulation.alphaTarget(0);\n d.fx = null;\n d.fy = null;\n }\n }\n\n // Function to trigger backend function for the chosen insight query output using socket\n function drawInsightChart() {\n var message;\n var insight = $( \"#insights\" ).val();\n $(\".arrowIcon\").css(\"visibility\", \"visible\");\n\n if (storedArtifact == \"defect\") {\n message = {\"cmd\": \"DefectInsight\", \"ID\": insight};\n send(JSON.stringify(message));\n }\n if (storedArtifact == \"test\") {\n message = {\"cmd\": \"TestInsight\", \"ID\": insight};\n send(JSON.stringify(message));\n }\n if (storedArtifact == \"requirement\") {\n message = {\"cmd\": \"ReqInsight\", \"ID\": insight};\n send(JSON.stringify(message));\n }\n }\n\n // Function to go back to original bubble chart from the insight query output\n function showPreviousChart() {\n $(\"#goButton\").attr(\"disabled\", true);\n $(\".arrowIcon\").css(\"visibility\", \"hidden\");\n $(\"#insights\").val(\"default\");\n drawBubbleChart(storedData, storedArtifact);\n }\n\n // Function to close network graph and go back to original bubble chart\n function closeNetworkChart() {\n showArtifact(storedData);\n }\n</script>\n\n<body class=\"body\">\n <div id=\"header\" class=\"header\">\n Watson | <subHeader>Engineering Insights</subHeader>\n </div>\n <br/>\n\n <div class=\"searchBox\">\n <select name=\"options\" id=\"options\"> </select>\n </div>\n <br/>\n\n <div style=\"border:1px solid white; text-align: center;\">\n <input id=\"button\" type=\"button\" class = \"w3-button w3-green w3-round\" style=\"align:center;\" value = \"Search\" onclick=\"doSearch()\"> </input>\n </div>\n <br/>\n\n <div id=\"chart\" class=\"chartDiv\">\n\n <div class=\"chartHeader\">\n\n <div id=\"labelHeading\" class=\"labelHeading\"> </div>\n\n <div id=\"arrowIcon\" class=\"arrowIcon\">\n <input id=\"arrowButton\" type=\"button\" value = \"<\" onclick=\"showPreviousChart()\"> </input>\n </div>\n\n <div id=\"insightsOption\" class=\"insightsOption\">\n <select name=\"insights\" id=\"insights\"> </select>\n </div>\n\n <div id=\"goIcon\" class=\"goIcon\">\n <input id=\"goButton\" type=\"button\" value = \"Go\" onclick=\"drawInsightChart()\"> </input>\n </div>\n\n <div id=\"closeIcon\" class=\"closeIcon\">\n <input id=\"closeButton\" type=\"button\" value = \"X\" onclick=\"closeNetworkChart()\"> </input>\n </div>\n\n </div>\n\n <div id=\"chartArea\" class=\"chartArea\"> </div>\n\n </div>\n\n</body>\n\n</html>\n","x":434,"y":363,"wires":[["c02f216e.8940d"]]},{"id":"c02f216e.8940d","type":"http response","z":"77c7bfd3.0321a","name":"","x":694,"y":363,"wires":[]},{"id":"5cf06316.644f4c","type":"comment","z":"77c7bfd3.0321a","name":"Flow that creates a Web socket server ","info":"This flow creates a web socket server","x":210,"y":58,"wires":[]},{"id":"e483e7e2.fa3c78","type":"comment","z":"77c7bfd3.0321a","name":"Flow that renders a Web UI","info":"","x":186.5,"y":305,"wires":[]},{"id":"d9ce3e57.a0ae","type":"websocket-listener","z":"","path":"/ws/orchestrate","wholemsg":"false"}]