|
@@ -6,6 +6,7 @@ if ('undefined' === typeof PRIMARY_KEY) throw "Missing PRIMARY_KEY";
|
|
|
// if ('undefined' === typeof FUNCTION_FETCH_PARENTS) throw "Missing FUNCTION_FETCH_PARENTS";
|
|
// if ('undefined' === typeof FUNCTION_FETCH_PARENTS) throw "Missing FUNCTION_FETCH_PARENTS";
|
|
|
// if ('undefined' === typeof JS_CHANNEL_UPDATE_NAME) throw "Missing JS_CHANNEL_UPDATE_NAME";
|
|
// if ('undefined' === typeof JS_CHANNEL_UPDATE_NAME) throw "Missing JS_CHANNEL_UPDATE_NAME";
|
|
|
var DBG = DBG || 0;
|
|
var DBG = DBG || 0;
|
|
|
|
|
+var SHOW_FLOW_DIAGRAM = SHOW_FLOW_DIAGRAM || 0;
|
|
|
|
|
|
|
|
var _isFullScreen = true; // TODO: get from arg
|
|
var _isFullScreen = true; // TODO: get from arg
|
|
|
var _html = {
|
|
var _html = {
|
|
@@ -17,6 +18,19 @@ var _html = {
|
|
|
var _nodes = new vis.DataSet(); // [ { id: '', label: '' }, ... ]
|
|
var _nodes = new vis.DataSet(); // [ { id: '', label: '' }, ... ]
|
|
|
var _edges = new vis.DataSet(); // [ { id: '', from: '', to: '' }, ... ]
|
|
var _edges = new vis.DataSet(); // [ { id: '', from: '', to: '' }, ... ]
|
|
|
var _network = null; // graph object
|
|
var _network = null; // graph object
|
|
|
|
|
+
|
|
|
|
|
+if (SHOW_FLOW_DIAGRAM) {
|
|
|
|
|
+ var _sankeyNode = null;
|
|
|
|
|
+ var _sankeyLink = null;
|
|
|
|
|
+ var sankey = null;
|
|
|
|
|
+ var _sankeySvgNode = null;
|
|
|
|
|
+ var _sankeySvgWidth = 0;
|
|
|
|
|
+ var _sankeyHeight = 0;
|
|
|
|
|
+ var _sankeyFormatNumber = d3.format(",.0f");
|
|
|
|
|
+ var _sankeyFormat = function(d) { return _sankeyFormatNumber(d) + " TWh"; };
|
|
|
|
|
+ var _sankeyColor = d3.scaleOrdinal(d3.schemeCategory10);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
var _todoGraphData = [ { nodes: [], edges: [] } ]; // data by levels
|
|
var _todoGraphData = [ { nodes: [], edges: [] } ]; // data by levels
|
|
|
var _defaultWfsParams = {
|
|
var _defaultWfsParams = {
|
|
|
resolve: 'all',
|
|
resolve: 'all',
|
|
@@ -132,11 +146,37 @@ function dataMakeFetchMoreEdge(parentNodeId, fetchMoreNode) {
|
|
|
p5WFS_GetFeature(featureTypeName, wfsParams).then(function (features) {
|
|
p5WFS_GetFeature(featureTypeName, wfsParams).then(function (features) {
|
|
|
if(DBG)console.log('features', features)
|
|
if(DBG)console.log('features', features)
|
|
|
updateWfsResponse(features, featureTypeName)
|
|
updateWfsResponse(features, featureTypeName)
|
|
|
|
|
+
|
|
|
|
|
+ updateSankeyDiagram()
|
|
|
|
|
+
|
|
|
}).catch(function (e) {
|
|
}).catch(function (e) {
|
|
|
if(DBG)console.warn(e)
|
|
if(DBG)console.warn(e)
|
|
|
p5UI__notifyAjaxCallback({ type: 'error', msg: e })
|
|
p5UI__notifyAjaxCallback({ type: 'error', msg: e })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+ if (SHOW_FLOW_DIAGRAM) {
|
|
|
|
|
+ _sankeySvgNode = document.getElementById("d3-sankey-test")
|
|
|
|
|
+ var d3SvgNode = d3.select(_sankeySvgNode);
|
|
|
|
|
+ var svgWidth = d3SvgNode.attr("width")
|
|
|
|
|
+ if ('%' === svgWidth.substr(-1)) {
|
|
|
|
|
+ svgWidth = parseInt(svgWidth.substr(0, svgWidth.length - 1))
|
|
|
|
|
+ svgWidth = (isNaN(svgWidth) || svgWidth > 100 || svgWidth < 0) ? 100 : svgWidth
|
|
|
|
|
+ var parentNodeStyle = getComputedStyle(_sankeySvgNode.parentNode)
|
|
|
|
|
+ var wrapNodeWidth = _sankeySvgNode.parentNode.clientWidth - parseFloat(parentNodeStyle.paddingLeft || 0) - parseFloat(parentNodeStyle.paddingRight || 0);
|
|
|
|
|
+ d3SvgNode.attr("width", (100 === svgWidth)
|
|
|
|
|
+ ? wrapNodeWidth
|
|
|
|
|
+ : Math.floor(wrapNodeWidth * svgWidth / 100)
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ _sankeySvgWidth = parseInt(d3SvgNode.attr("width"));
|
|
|
|
|
+ _sankeyHeight = parseInt(d3SvgNode.attr("height"));
|
|
|
|
|
+
|
|
|
|
|
+ sankey = d3.sankey()
|
|
|
|
|
+ .nodeWidth(15)
|
|
|
|
|
+ .nodePadding(10)
|
|
|
|
|
+ .extent([ [ 1, 1 ], [ _sankeySvgWidth - 1, _sankeyHeight - 6 ] ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
renderLayout()
|
|
renderLayout()
|
|
|
})();
|
|
})();
|
|
|
|
|
|
|
@@ -204,6 +244,7 @@ function updateWfsResponse(features, featureTypeName) {
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function isP5LinkObject(json) {
|
|
function isP5LinkObject(json) {
|
|
@@ -391,6 +432,8 @@ function fetchNodeMoreRefs(selectedNode, featureID) {
|
|
|
_edges.add(dataMakeFetchMoreEdge(parentNodeId, nodeObject))
|
|
_edges.add(dataMakeFetchMoreEdge(parentNodeId, nodeObject))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ updateSankeyDiagram()
|
|
|
|
|
+
|
|
|
return "Pobrano nowe dane"
|
|
return "Pobrano nowe dane"
|
|
|
}).then(function (msg) {
|
|
}).then(function (msg) {
|
|
|
p5UI__notifyAjaxCallback({ type: 'info', msg: msg })
|
|
p5UI__notifyAjaxCallback({ type: 'info', msg: msg })
|
|
@@ -431,6 +474,9 @@ function fetchNodeRecurse(selectedNode, featureID) {
|
|
|
})
|
|
})
|
|
|
if (!refFields.length) return "Brak danych"
|
|
if (!refFields.length) return "Brak danych"
|
|
|
updateWfsResponse(features, featureTypeName)
|
|
updateWfsResponse(features, featureTypeName)
|
|
|
|
|
+
|
|
|
|
|
+ updateSankeyDiagram()
|
|
|
|
|
+
|
|
|
return "Pobrano nowe dane"
|
|
return "Pobrano nowe dane"
|
|
|
}).then(function (msg) {
|
|
}).then(function (msg) {
|
|
|
p5UI__notifyAjaxCallback({ type: 'info', msg: msg })
|
|
p5UI__notifyAjaxCallback({ type: 'info', msg: msg })
|
|
@@ -532,6 +578,131 @@ function renderSelectedNode(node) {
|
|
|
_html['selected'].innerHTML = '' + node.id + ' ' + gotToTableLink + ' ' + editLink;
|
|
_html['selected'].innerHTML = '' + node.id + ' ' + gotToTableLink + ' ' + editLink;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function updateSankeyDiagram() {
|
|
|
|
|
+ console.log('updateSankeyDiagram..');
|
|
|
|
|
+ if (!SHOW_FLOW_DIAGRAM || !sankey) return;
|
|
|
|
|
+ // var sankeyData = { // example
|
|
|
|
|
+ // nodes: [
|
|
|
|
|
+ // /* 0 */ { name: "A" },
|
|
|
|
|
+ // /* 1 */ { name: "B" },
|
|
|
|
|
+ // /* 2 */ { name: "C" },
|
|
|
|
|
+ // /* 3 */ { name: "D" },
|
|
|
|
|
+ // /* 4 */ { name: "E" },
|
|
|
|
|
+ // /* 5 */ { name: "F" },
|
|
|
|
|
+ // ],
|
|
|
|
|
+ // links: [
|
|
|
|
|
+ // { "source": 0, "target": 1, "value": 100 },
|
|
|
|
|
+ // { "source": 1, "target": 2, "value": 100 },
|
|
|
|
|
+ // { "source": 2, "target": 3, "value": 100 },
|
|
|
|
|
+ // { "source": 3, "target": 4, "value": 100 },
|
|
|
|
|
+ // { "source": 5, "target": 2, "value": 100 },
|
|
|
|
|
+ // { "source": 0, "target": 4, "value": 100 },
|
|
|
|
|
+ // ]
|
|
|
|
|
+ // }
|
|
|
|
|
+
|
|
|
|
|
+ p5Utils__clearNode(_sankeySvgNode)
|
|
|
|
|
+ var d3SvgNode = d3.select(_sankeySvgNode);
|
|
|
|
|
+ _sankeyLink = d3SvgNode.append("g")
|
|
|
|
|
+ .attr("class", "links")
|
|
|
|
|
+ .attr("fill", "none")
|
|
|
|
|
+ .attr("stroke", "#000")
|
|
|
|
|
+ .attr("stroke-opacity", 0.2)
|
|
|
|
|
+ .selectAll("path");
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyNode = d3SvgNode.append("g")
|
|
|
|
|
+ .attr("class", "nodes")
|
|
|
|
|
+ .attr("font-family", "sans-serif")
|
|
|
|
|
+ .attr("font-size", 10)
|
|
|
|
|
+ .selectAll("g");
|
|
|
|
|
+
|
|
|
|
|
+ // var sankeyInstance = sankey(sankeyData);
|
|
|
|
|
+ var mapVisNodeIdToIdx = _nodes.getIds().reduce(function (ret, id, idx) {
|
|
|
|
|
+ ret[id] = idx;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }, {});
|
|
|
|
|
+ var countOutLinks = _edges.get().reduce(function (ret, edge) {
|
|
|
|
|
+ if (!mapVisNodeIdToIdx.hasOwnProperty(edge.from)) throw "Missing to in mapVisNodeIdToIdx["+edge.from+"]"
|
|
|
|
|
+ var idxTarget = mapVisNodeIdToIdx[edge.from]
|
|
|
|
|
+ ret[idxTarget] = (ret[idxTarget] > 0) ? ret[idxTarget] + 1 : 1
|
|
|
|
|
+ console.log('DBG:sankey: countOutLinks reduce', edge, ret);
|
|
|
|
|
+ return ret
|
|
|
|
|
+ }, {})
|
|
|
|
|
+ console.log('DBG:sankey: mapVisNodeIdToIdx', mapVisNodeIdToIdx);
|
|
|
|
|
+ console.log('DBG:sankey: countOutLinks', countOutLinks);
|
|
|
|
|
+ var sankeyInstance = sankey({
|
|
|
|
|
+ nodes: _nodes.map(function (node) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ name: node.label
|
|
|
|
|
+ }
|
|
|
|
|
+ }),
|
|
|
|
|
+ links: _edges.map(function (edge) {
|
|
|
|
|
+ if (!mapVisNodeIdToIdx.hasOwnProperty(edge.from)) throw "Missing from in mapVisNodeIdToIdx["+edge.from+"]"
|
|
|
|
|
+ if (!mapVisNodeIdToIdx.hasOwnProperty(edge.to)) throw "Missing to in mapVisNodeIdToIdx["+edge.to+"]"
|
|
|
|
|
+ var idxTarget = mapVisNodeIdToIdx[edge.to]
|
|
|
|
|
+ return {
|
|
|
|
|
+ source: mapVisNodeIdToIdx[edge.from],
|
|
|
|
|
+ target: idxTarget,
|
|
|
|
|
+ value: (countOutLinks[idxTarget] || 1) * 10
|
|
|
|
|
+ }
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+ // var sankeyInstance = sankey()
|
|
|
|
|
+ // .nodes(
|
|
|
|
|
+ // _nodes.map(function (node) {
|
|
|
|
|
+ // return {
|
|
|
|
|
+ // name: node.label
|
|
|
|
|
+ // }
|
|
|
|
|
+ // })
|
|
|
|
|
+ // )
|
|
|
|
|
+ // .edges(
|
|
|
|
|
+ // _edges.map(function (edge) {
|
|
|
|
|
+ // if (!mapVisNodeIdToIdx.hasOwnProperty(edge.from)) throw "Missing from in mapVisNodeIdToIdx["+edge.from+"]"
|
|
|
|
|
+ // if (!mapVisNodeIdToIdx.hasOwnProperty(edge.to)) throw "Missing to in mapVisNodeIdToIdx["+edge.to+"]"
|
|
|
|
|
+ // var idxTarget = mapVisNodeIdToIdx[edge.to]
|
|
|
|
|
+ // return {
|
|
|
|
|
+ // source: mapVisNodeIdToIdx[edge.from],
|
|
|
|
|
+ // target: idxTarget,
|
|
|
|
|
+ // value: (countOutLinks[idxTarget] || 1) * 10
|
|
|
|
|
+ // }
|
|
|
|
|
+ // })
|
|
|
|
|
+ // )
|
|
|
|
|
+ // .layout(32);
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyLink = _sankeyLink
|
|
|
|
|
+ .data(sankeyInstance.links)
|
|
|
|
|
+ .enter().append("path")
|
|
|
|
|
+ .attr("d", d3.sankeyLinkHorizontal())
|
|
|
|
|
+ .attr("stroke-width", function(d) { return Math.max(1, d.width); });
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyLink.append("title")
|
|
|
|
|
+ .text(function(d) { return d.source.name + " → " + d.target.name + "\n" + _sankeyFormat(d.value); });
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyNode = _sankeyNode
|
|
|
|
|
+ .data(sankeyInstance.nodes)
|
|
|
|
|
+ .enter().append("g");
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyNode.append("rect")
|
|
|
|
|
+ .attr("x", function(d) { return d.x0; })
|
|
|
|
|
+ .attr("y", function(d) { return d.y0; })
|
|
|
|
|
+ .attr("height", function(d) { return d.y1 - d.y0; })
|
|
|
|
|
+ .attr("width", function(d) { return d.x1 - d.x0; })
|
|
|
|
|
+ .attr("fill", function(d) { return _sankeyColor(d.name.replace(/ .*/, "")); })
|
|
|
|
|
+ .attr("stroke", "#000");
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyNode.append("text")
|
|
|
|
|
+ .attr("x", function(d) { return d.x0 - 6; })
|
|
|
|
|
+ .attr("y", function(d) { return (d.y1 + d.y0) / 2; })
|
|
|
|
|
+ .attr("dy", "0.35em")
|
|
|
|
|
+ .attr("text-anchor", "end")
|
|
|
|
|
+ .text(function(d) { return d.name; })
|
|
|
|
|
+ .filter(function(d) { return d.x0 < _sankeySvgWidth / 2; })
|
|
|
|
|
+ .attr("x", function(d) { return d.x1 + 6; })
|
|
|
|
|
+ .attr("text-anchor", "start");
|
|
|
|
|
+
|
|
|
|
|
+ _sankeyNode.append("title")
|
|
|
|
|
+ .text(function(d) { return d.name + "\n" + _sankeyFormat(d.value); });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// global['FUNCTION_FETCH_CHILDRENS'] = 'refGraphFetchChildrens'
|
|
// global['FUNCTION_FETCH_CHILDRENS'] = 'refGraphFetchChildrens'
|
|
|
// global['FUNCTION_FETCH_PARENTS'] = 'refGraphFetchParents'
|
|
// global['FUNCTION_FETCH_PARENTS'] = 'refGraphFetchParents'
|
|
|
// global['_nodes'] = _nodes // TODO: DBG
|
|
// global['_nodes'] = _nodes // TODO: DBG
|