|
|
@@ -1,5 +1,6 @@
|
|
|
var DBG = DBG || false;
|
|
|
var DBG1 = true;
|
|
|
+var DBG_INIT_SELECTED = [ "BI_audit_ENERGA_RUM_KONTRAHENCI.18661", "BI_audit_KRS.389967" ];
|
|
|
|
|
|
if ('undefined' === typeof HTML_ID_REF_GRAPH) throw "Missing HTML_ID_REF_GRAPH";
|
|
|
if (!RAPORT_ID) throw "Missing RAPORT_ID";
|
|
|
@@ -24,23 +25,71 @@ var mapStatsNodeToGraphNode = function (node) {
|
|
|
value: 1,
|
|
|
level: 0,
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
+var mapStatsEdgeToGraphEdge = function (edge) {
|
|
|
+ return {
|
|
|
+ id: Utils.makeUniqueEdgeId(edge['source'], edge['target']),
|
|
|
+ from: edge['source'],
|
|
|
+ to: edge['target'],
|
|
|
+ pathId: edge['pathId'],
|
|
|
+ listPathId: [ edge['pathId'] ],
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//// DBG: Utils:
|
|
|
+// var from, to;
|
|
|
+// from = 'aa.11'; to = 'bb.22'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
|
|
|
+// from = 'bb.22'; to = 'aa.11'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
|
|
|
+// from = 'cc.22'; to = 'cc.11'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
|
|
|
+var Utils = (function __makeUtils() {
|
|
|
+ var Utils = {};
|
|
|
+ var _cacheListFeatureNames = [];
|
|
|
+
|
|
|
+ Utils.fidSplit = function (fid) {
|
|
|
+ var dotPos = fid.indexOf('.');
|
|
|
+ return [ fid.substr(0, dotPos), fid.substr(dotPos + 1) ];
|
|
|
+ }
|
|
|
+
|
|
|
+ Utils.makeUniqueEdgeId = function (from, to) {
|
|
|
+ var listFidArr = [ from, to ].sort().map(Utils.fidSplit);
|
|
|
+ var listIdx = listFidArr.map(function (fidArr) {
|
|
|
+ var cacheIdx = _cacheListFeatureNames.indexOf(fidArr[0]);
|
|
|
+ if (-1 === cacheIdx) {
|
|
|
+ cacheIdx = _cacheListFeatureNames.length;
|
|
|
+ _cacheListFeatureNames.push(fidArr[0]);
|
|
|
+ }
|
|
|
+ return cacheIdx;
|
|
|
+ })
|
|
|
+ return listIdx.map(function (cacheIdx, fidIdx) {
|
|
|
+ return cacheIdx + '.' + listFidArr[fidIdx][1];
|
|
|
+ }).join('-')
|
|
|
+ }
|
|
|
+
|
|
|
+ Utils.getCacheAllEdgeId = function () {
|
|
|
+ return [].concat(_cacheListFeatureNames);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Utils;
|
|
|
+})();
|
|
|
|
|
|
-{ // TODO: mv to another file
|
|
|
- function getinitialState() {
|
|
|
+{ // TODO: RaportOutputPanel - mv to another file
|
|
|
+ var RaportOutputPanel = {};
|
|
|
+ RaportOutputPanel.initialState = function () {
|
|
|
var nodes = (STATS && STATS.nodes) ? STATS.nodes : [];
|
|
|
var edges = (STATS && STATS.edges) ? STATS.edges : [];
|
|
|
+ var paths = (STATS && STATS.path_list) ? STATS.path_list : [];
|
|
|
DBG1 && console.log('DBG: STATS', STATS);
|
|
|
return {
|
|
|
nodes: nodes.map(mapStatsNodeToGraphNode),
|
|
|
- edges: edges,
|
|
|
+ edges: edges.map(mapStatsEdgeToGraphEdge),
|
|
|
+ paths: paths,
|
|
|
isLoading: false,
|
|
|
sentRequestId: 0,
|
|
|
receivedRequestId: 0,
|
|
|
}
|
|
|
- }
|
|
|
- function networkGraphStore(state, action) {
|
|
|
- var prevState = state || getinitialState();
|
|
|
+ };
|
|
|
+ RaportOutputPanel.store = function (state, action) {
|
|
|
+ var prevState = state || RaportOutputPanel.initialState();
|
|
|
DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
|
|
|
switch (action.type) {
|
|
|
case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
|
|
|
@@ -55,9 +104,90 @@ var mapStatsNodeToGraphNode = function (node) {
|
|
|
});
|
|
|
default: return prevState;
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
+ RaportOutputPanel.createActions = function () {
|
|
|
+ var setSentRequestId = function (sentRequestId) {
|
|
|
+ return { type: 'SET_SENT_REQUEST_ID', sentRequestId: sentRequestId };
|
|
|
+ }
|
|
|
+ var setResponse = function (response) {
|
|
|
+ return Object.assign(response, { type: 'SET_RESPONSE' });
|
|
|
+ }
|
|
|
+
|
|
|
+ var fetchData = function (raportId, params) {
|
|
|
+ return function (dispatch, getState) {
|
|
|
+ var state = getState();
|
|
|
+ var this__requestId = state.sentRequestId + 1;
|
|
|
+ dispatch(setSentRequestId(this__requestId));
|
|
|
+
|
|
|
+ var reqPromise = window.fetch(API_URL, {
|
|
|
+ method: 'GET',
|
|
|
+ credentials: 'same-origin',
|
|
|
+ }).then(function (response) {
|
|
|
+ return response.json();
|
|
|
+ });
|
|
|
+ return reqPromise.then(function (response) {
|
|
|
+ var items = response;
|
|
|
+ var state = getState();
|
|
|
+
|
|
|
+ if (state.receivedRequestId > this__requestId) {
|
|
|
+ DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ dispatch(
|
|
|
+ setResponse({
|
|
|
+ requestId: this__requestId,
|
|
|
+ msg: "Pobrano dane",
|
|
|
+ body: response.body
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }).catch(function (e) {
|
|
|
+ p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #GS1: ' + e});
|
|
|
+ // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ fetchData: fetchData,
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
|
|
|
- function createNetworkGraphStoreActions() {
|
|
|
+{ // TODO: NetworkGraph - mv to another file
|
|
|
+ var NetworkGraph = {};
|
|
|
+ NetworkGraph.initialState = function () {
|
|
|
+ var nodes = (STATS && STATS.nodes) ? STATS.nodes : [];
|
|
|
+ var edges = (STATS && STATS.edges) ? STATS.edges : [];
|
|
|
+ var paths = (STATS && STATS.path_list) ? STATS.path_list : [];
|
|
|
+ DBG1 && console.log('DBG: STATS', STATS);
|
|
|
+ return {
|
|
|
+ nodes: nodes.map(mapStatsNodeToGraphNode),
|
|
|
+ edges: edges.map(mapStatsEdgeToGraphEdge),
|
|
|
+ paths: paths,
|
|
|
+ isLoading: false,
|
|
|
+ sentRequestId: 0,
|
|
|
+ receivedRequestId: 0,
|
|
|
+ }
|
|
|
+ };
|
|
|
+ NetworkGraph.store = function (state, action) {
|
|
|
+ var prevState = state || NetworkGraph.initialState();
|
|
|
+ DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
|
|
|
+ switch (action.type) {
|
|
|
+ case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
|
|
|
+ sentRequestId: action.sentRequestId,
|
|
|
+ isLoading: true
|
|
|
+ });
|
|
|
+ case 'SET_RESPONSE': return Object.assign(prevState, {
|
|
|
+ receivedRequestId: action.requestId,
|
|
|
+ nodes: action.body.nodes.map(mapStatsNodeToGraphNode),
|
|
|
+ edges: action.body.edges,
|
|
|
+ isLoading: (prevState.sentRequestId > action.requestId) ? true : false,
|
|
|
+ });
|
|
|
+ default: return prevState;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ NetworkGraph.createActions = function () {
|
|
|
var setSentRequestId = function (sentRequestId) {
|
|
|
return { type: 'SET_SENT_REQUEST_ID', sentRequestId: sentRequestId };
|
|
|
}
|
|
|
@@ -82,7 +212,7 @@ var mapStatsNodeToGraphNode = function (node) {
|
|
|
var state = getState();
|
|
|
|
|
|
if (state.receivedRequestId > this__requestId) {
|
|
|
- DBG1 && console.log('DBG: skiped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
|
|
|
+ DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -103,16 +233,16 @@ var mapStatsNodeToGraphNode = function (node) {
|
|
|
return {
|
|
|
fetchData: fetchData,
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
-var defaultOptions = {
|
|
|
+var defaultNetworkGraphOptions = {
|
|
|
nodes: {
|
|
|
shape: 'dot',
|
|
|
scaling: {
|
|
|
- min: 20, max: 30,
|
|
|
+ min: 8, max: 30,
|
|
|
label: {
|
|
|
- min: 8, max: 16, drawThreshold: 9, maxVisible: 20
|
|
|
+ min: 8, max: 16, drawThreshold: 6, maxVisible: 20
|
|
|
}
|
|
|
},
|
|
|
font: { color: "#666", size: 10, face: 'Helvetica Neue, Helvetica, Arial' }
|
|
|
@@ -129,6 +259,8 @@ var TMP_COUNTER = 1;
|
|
|
var p5UI__NetworkGraph = createReactClass({
|
|
|
_network: null,
|
|
|
_visOutputRef: React.createRef(),
|
|
|
+ _allNodes: null, // new vis.DataSet(),
|
|
|
+ _allEdges: null, // new vis.DataSet(),
|
|
|
_nodes: new vis.DataSet(),
|
|
|
_edges: new vis.DataSet(),
|
|
|
getStateFromStore: function () {
|
|
|
@@ -139,6 +271,7 @@ var p5UI__NetworkGraph = createReactClass({
|
|
|
}
|
|
|
},
|
|
|
getInitialState: function () {
|
|
|
+ if (this.props.selected) this._updateSelected(this.props.selected);
|
|
|
return {
|
|
|
initialized: false,
|
|
|
isLoading: false,
|
|
|
@@ -150,7 +283,7 @@ var p5UI__NetworkGraph = createReactClass({
|
|
|
},
|
|
|
componentDidMount: function () {
|
|
|
var data = { nodes: this._nodes, edges: this._edges };
|
|
|
- this._network = new vis.Network(this._visOutputRef, data, defaultOptions);
|
|
|
+ this._network = new vis.Network(this._visOutputRef, data, defaultNetworkGraphOptions);
|
|
|
// bindNetwork();
|
|
|
this.setState({ initialized: true });
|
|
|
this._unsubscribe = this.props.store.subscribe(this._storeUpdated)
|
|
|
@@ -177,35 +310,108 @@ var p5UI__NetworkGraph = createReactClass({
|
|
|
},
|
|
|
|
|
|
shouldComponentUpdate: function (nextProps, nextState) {
|
|
|
- if (this.state.receivedRequestId !== nextState.receivedRequestId) { // add missing nodes
|
|
|
- var state = this.props.store.getState();
|
|
|
- DBG1 && console.warn("TODO: update nodes, edges", { state });
|
|
|
- // this._edges.add( edge_or_edges_array )
|
|
|
- if (state.nodes && state.nodes.length) {
|
|
|
- var __nodes = this._nodes;
|
|
|
- state.nodes.forEach(function (node) {
|
|
|
- __nodes.add(node);
|
|
|
- })
|
|
|
- }
|
|
|
- // edge: { from: page, to: subpageID, color:getEdgeColor(level), level: level, selectionWidth:2, hoverWidth:0 }
|
|
|
- if (state.edges && state.edges.length) {
|
|
|
- var __edges = this._edges;
|
|
|
- // state.edges.forEach(function (edge) {
|
|
|
- state.edges.slice(0, 30).forEach(function (edge) {
|
|
|
- __edges.add({
|
|
|
- from: edge.source,
|
|
|
- to: edge.target,
|
|
|
- });
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
+ // if (this.state.receivedRequestId !== nextState.receivedRequestId) { // add missing nodes
|
|
|
+ // var state = this.props.store.getState();
|
|
|
+ // DBG1 && console.warn("TODO: update nodes, edges", { state });
|
|
|
+ // // this._edges.add( edge_or_edges_array )
|
|
|
+ // if (state.nodes && state.nodes.length) {
|
|
|
+ // var __nodes = this._nodes;
|
|
|
+ // state.nodes.forEach(function (node) {
|
|
|
+ // __nodes.add(node);
|
|
|
+ // })
|
|
|
+ // }
|
|
|
+ // // edge: { from: page, to: subpageID, color:getEdgeColor(level), level: level, selectionWidth:2, hoverWidth:0 }
|
|
|
+ // if (state.edges && state.edges.length) {
|
|
|
+ // var __edges = this._edges;
|
|
|
+ // // state.edges.forEach(function (edge) {
|
|
|
+ // state.edges.slice(0, 30).forEach(function (edge) {
|
|
|
+ // __edges.add({
|
|
|
+ // from: edge.source,
|
|
|
+ // to: edge.target,
|
|
|
+ // });
|
|
|
+ // })
|
|
|
+ // }
|
|
|
+ // }
|
|
|
|
|
|
if (this.props.selected.length != nextProps.selected.length) {
|
|
|
- var edges = []; // TODO: by nodes
|
|
|
- this._network.setData({ nodes: nextProps.selected, edges: edges });
|
|
|
+ this._updateSelected(nextProps.selected)
|
|
|
}
|
|
|
return false;
|
|
|
},
|
|
|
+ _updateSelected: function (selected) { // TODO: move to RaportOutputPanel Store
|
|
|
+ var state = this.props.store.getState();
|
|
|
+ var idsSelected = (selected || []).map( function (node) { return node.id } )
|
|
|
+
|
|
|
+ var nodes = [];
|
|
|
+ // var edges = state.edges.filter(function (edge) { // use idsSelected - TODO: RMME
|
|
|
+ // return ( -1 !== idsSelected.indexOf(edge.source) || -1 !== idsSelected.indexOf(edge.target) );
|
|
|
+ // })
|
|
|
+ {
|
|
|
+ // TODO: find all paths with selected fids
|
|
|
+ var foundPaths = state.paths.filter(function (path) {
|
|
|
+ for (var i = 0, totalFids = path.fids.length, fid = null; i < totalFids; i++) {
|
|
|
+ fid = path.fids[i];
|
|
|
+ DBG && console.log('DBG:foundPaths ', {fid: ''+fid, path});
|
|
|
+ if ( -1 !== idsSelected.indexOf(fid) ) return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ })
|
|
|
+ // TODO: add missing nodes (not selected but on path)
|
|
|
+ var addFidsToGraph = Array.from(new Set(foundPaths.reduce(function (ret, path) {
|
|
|
+ return ret.concat(path.fids.filter(function (fid) {
|
|
|
+ return ( -1 === idsSelected.indexOf(fid) );
|
|
|
+ }))
|
|
|
+ }, [])));
|
|
|
+ // TODO: view only combined path or all not selected nodes? - trying: not selected nodes
|
|
|
+ // TODO: convert found paths to graph edges
|
|
|
+ }
|
|
|
+ DBG1 && console.warn('DBG: TODO set edges by selectd nodes...', { state_nodes: state.nodes, state_edges: state.edges, idsSelected, foundPaths, addFidsToGraph });
|
|
|
+ this._nodes = new vis.DataSet(selected);
|
|
|
+ { // TODO: convert fid to node on found list
|
|
|
+ { // if (!this._allNodes) {
|
|
|
+ this._allNodes = new vis.DataSet();
|
|
|
+ this._allNodes.add(state.nodes);
|
|
|
+ }
|
|
|
+
|
|
|
+ var this__allNodes = this._allNodes;
|
|
|
+ var __nodes = this._nodes;
|
|
|
+ var addNodesToGraph = addFidsToGraph.map(function (fid) {
|
|
|
+ var node = this__allNodes.get(fid)
|
|
|
+ try {
|
|
|
+ DBG1 && console.log('DBG: TODO add node (fid:'+fid+') ', { node, this__allNodes, fid });
|
|
|
+ __nodes.add(node);
|
|
|
+ __nodes.update(Object.assign(node, { color: '#ddd', size: 100 }));
|
|
|
+ DBG1 && console.log('DBG: added red node (fid:'+fid+') ', { node });
|
|
|
+ } catch (e) {
|
|
|
+ DBG1 && console.log(e);
|
|
|
+ DBG1 && console.log('DBG: skip node (fid:'+fid+') already added');
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ DBG1 && console.log('DBG: check edges: ', { 'this._edges.length': this._edges.length, 'state.edges.length': state.edges.length });
|
|
|
+ if (this._edges.length != state.edges.length) {
|
|
|
+ DBG1 && console.log('DBG: TODO: update edges', { 'state.edges': state.edges });
|
|
|
+
|
|
|
+ var this__edges = this._edges;
|
|
|
+ state.edges.forEach(function (edge) {
|
|
|
+ var foundEdge = this__edges.get(edge.id);
|
|
|
+ if (!foundEdge) {
|
|
|
+ this__edges.add(edge);
|
|
|
+ } else {
|
|
|
+ var listPathId = (-1 !== foundEdge.listPathId.indexOf(edge.pathId)) ? foundEdge.listPathId : foundEdge.listPathId.concat(edge.pathId);
|
|
|
+ var mergedEdge = Object.assign(foundEdge, {
|
|
|
+ listPathId: listPathId,
|
|
|
+ width: 1 + (listPathId.length - 1) / 10,
|
|
|
+ });
|
|
|
+ this__edges.update(mergedEdge);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (this._network) {
|
|
|
+ this._network.setData({ nodes: this._nodes, edges: this._edges });
|
|
|
+ this._network.fit() // zoom out to fit container size
|
|
|
+ }
|
|
|
+ },
|
|
|
render: function () {
|
|
|
DBG1 && console.log('DBG:render');
|
|
|
return h('div', {}, [
|
|
|
@@ -225,10 +431,21 @@ var p5UI__NetworkGraph = createReactClass({
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-var p5UI__PanelNetworkGraph = createReactClass({
|
|
|
+/**
|
|
|
+ * props.store: networkGraphStore
|
|
|
+ * - used: state.nodes
|
|
|
+ */
|
|
|
+var p5UI__RaportOutputPanel = createReactClass({
|
|
|
getInitialState: function () {
|
|
|
+ var initSelected = [];
|
|
|
+ if (DBG_INIT_SELECTED) {
|
|
|
+ var state = this.props.store.getState()
|
|
|
+ initSelected = state.nodes.filter(function (node) {
|
|
|
+ return ( -1 !== DBG_INIT_SELECTED.indexOf(node.id));
|
|
|
+ })
|
|
|
+ }
|
|
|
return {
|
|
|
- selected: [],
|
|
|
+ selected: initSelected,
|
|
|
}
|
|
|
},
|
|
|
handleSelectFeatures: function (selected) {
|
|
|
@@ -238,14 +455,15 @@ var p5UI__PanelNetworkGraph = createReactClass({
|
|
|
render: function () {
|
|
|
var state = this.props.store.getState()
|
|
|
DBG1 && console.log('DBG: state', state);
|
|
|
- var options = state.nodes || [];
|
|
|
+ var nodes = state.nodes || [];
|
|
|
return h(React.Fragment, {}, [
|
|
|
h(Typeahead, {
|
|
|
labelKey: "label",
|
|
|
multiple: true,
|
|
|
- options: options,
|
|
|
+ options: nodes,
|
|
|
placeholder: "Wybierz",
|
|
|
bsSize: 'large',
|
|
|
+ selected: this.state.selected,
|
|
|
onChange: this.handleSelectFeatures,
|
|
|
}),
|
|
|
h(p5UI__NetworkGraph, {
|
|
|
@@ -259,10 +477,10 @@ var p5UI__PanelNetworkGraph = createReactClass({
|
|
|
})
|
|
|
|
|
|
ReactDOM.render(
|
|
|
- h(p5UI__PanelNetworkGraph, {
|
|
|
+ h(p5UI__RaportOutputPanel, {
|
|
|
raportId: RAPORT_ID,
|
|
|
- store: createStoreWithThunkMiddleware(networkGraphStore),
|
|
|
- storeActions: createNetworkGraphStoreActions(),
|
|
|
+ store: createStoreWithThunkMiddleware(NetworkGraph.store),
|
|
|
+ storeActions: NetworkGraph.createActions(),
|
|
|
}),
|
|
|
document.getElementById(HTML_ID_REF_GRAPH)
|
|
|
);
|