Piotr Labudda 7 лет назад
Родитель
Сommit
301332e5c6
1 измененных файлов с 179 добавлено и 51 удалено
  1. 179 51
      SE/se-lib/Route/UrlAction/BiAuditGraph.php.network-graph.js

+ 179 - 51
SE/se-lib/Route/UrlAction/BiAuditGraph.php.network-graph.js

@@ -1,6 +1,6 @@
 var DBG = DBG || false;
 var DBG1 = true;
-var DBG_INIT_SELECTED = [ "BI_audit_ENERGA_RUM_KONTRAHENCI.18661", "BI_audit_KRS.389967" ];
+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";
@@ -22,6 +22,7 @@ var mapStatsNodeToGraphNode = function (node) {
 	return {
 		id: node['@object'] + '.' + node['@primaryKey'],
 		label: Utils.nodeLabelShort(node['@label']),
+		color: Utils.nodeColorByObject(node['@object']),
 		rawLabel: node['@label'],
 		value: 1,
 		level: 0,
@@ -73,17 +74,53 @@ var Utils = (function __makeUtils() {
 	Utils.nodeLabelShort = function (label) {
 		return label.replace('SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ', 'Sp. z o.o.')
 	}
+	Utils.bsColors = {
+		'base': "#777",
+		'blue': "#337ab7",
+		'green': "#5cb85c",
+		'lightblue': "#5bc0de",
+		'orange': "#f0ad4e",
+		'red': "#d9534f",
+	};
+	Utils.bsLightColors = {
+		'base': "#f5f5f5",
+		'blue': "#d9edf7",
+		'green': "#dff0d8",
+		'lightblue': "#d9edf7",
+		'orange': "#fcf8e3",
+		'red': "#f2dede",
+	};
+	Utils.colors = {
+		person: Utils.bsLightColors['orange'],
+		company: Utils.bsLightColors['red'],
+		location: Utils.bsLightColors['base'],
+	};
+	Utils.nodeColorByObject = function (objectName) {
+		switch (objectName) {
+			case 'BI_audit_KRS_person': return Utils.colors['person'];
+			case 'BI_audit_MSIG_person': return Utils.colors['person'];
+			case 'BI_audit_MSIG': return Utils.colors['company'];
+			case 'BI_audit_KRS': return Utils.colors['company'];
+			case 'BI_audit_ENERGA_RUM_KONTRAHENCI': return Utils.colors['company'];
+			case 'TERYT_adresy': return Utils.colors['location'];
+			case 'BI_audit_MSIG_address': return Utils.colors['location'];
+			case 'BI_audit_KRS_company': return Utils.colors['company'];
+			case 'BI_audit_MSIG_company': return Utils.colors['company'];
+			case 'BI_audit_CEIDG': return Utils.colors['company'];
+			default: return '#666';
+		}
+	}
 
 	return Utils;
 })();
 
-{ // TODO: RaportOutputPanel - mv to another file
+{ // TODO: RaportOutputPanel ?
 	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);
+		DBG && console.log('DBG: STATS', STATS);
 		return {
 			nodes: nodes.map(mapStatsNodeToGraphNode),
 			edges: edges.map(mapStatsEdgeToGraphEdge),
@@ -95,7 +132,7 @@ var Utils = (function __makeUtils() {
 	};
 	RaportOutputPanel.store = function (state, action) {
 		var prevState = state || RaportOutputPanel.initialState();
-		DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
+		DBG && console.log('DBG: store', { prevState, action, actionType: action.type });
 		switch (action.type) {
 			case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
 				sentRequestId: action.sentRequestId,
@@ -135,7 +172,7 @@ var Utils = (function __makeUtils() {
 					var state = getState();
 
 					if (state.receivedRequestId > this__requestId) {
-						DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
+						DBG && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
 						return;
 					}
 
@@ -165,9 +202,19 @@ var Utils = (function __makeUtils() {
 		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);
+		DBG && console.log('DBG: STATS', STATS);
+
+		var allNodesSet = new vis.DataSet();
+		allNodesSet.update( nodes.map(mapStatsNodeToGraphNode) );
+		var allEdgesSet = new vis.DataSet();
+		allEdgesSet.update( edges.map(mapStatsEdgeToGraphEdge) );
+		var visibleNodesSet = new vis.DataSet();
+		var selectedNodeIds = [];
 		return {
-			nodes: nodes.map(mapStatsNodeToGraphNode),
+			allNodesSet: allNodesSet,
+			allEdgesSet: allEdgesSet,
+			visibleNodesSet: visibleNodesSet,
+			nodes: nodes.map(mapStatsNodeToGraphNode), // TODO: RMME
 			edges: edges.map(mapStatsEdgeToGraphEdge),
 			paths: paths,
 			isLoading: false,
@@ -177,7 +224,7 @@ var Utils = (function __makeUtils() {
 	};
 	NetworkGraph.store = function (state, action) {
 		var prevState = state || NetworkGraph.initialState();
-		DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
+		DBG && console.log('DBG: store', { prevState, action, actionType: action.type });
 		switch (action.type) {
 			case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
 				sentRequestId: action.sentRequestId,
@@ -189,6 +236,71 @@ var Utils = (function __makeUtils() {
 				edges: action.body.edges,
 				isLoading: (prevState.sentRequestId > action.requestId) ? true : false,
 			});
+			case 'SET_SELECTED': {
+				// TODO: mv from updateSelected
+				var selected = action.selected || [];
+				var idsSelected = selected.map( function (node) { return node.id } )
+				DBG && console.log('DBG:NetworkGraph.SET_SELECTED ', { idsSelected, selected })
+
+				var foundPaths = prevState.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;
+				})
+				var addFidsToGraph = Array.from(new Set(foundPaths.reduce(function (ret, path) {
+					return ret.concat(path.fids.filter(function (fid) {
+						return ( -1 === idsSelected.indexOf(fid) );
+					}))
+				}, [])));
+
+				function markColorSelected(node) {
+					return Object.assign(node, { color: '#95c1fe' });
+				}
+				prevState.visibleNodesSet.clear();
+				prevState.visibleNodesSet.add(selected.map(markColorSelected));
+				addFidsToGraph.forEach(function (fid) {
+					var node = prevState.allNodesSet.get(fid)
+					prevState.visibleNodesSet.update(node);
+				})
+				DBG && console.log('DBG:NetworkGraph.SET_SELECTED new state ', { state: Object.assign(prevState, { selected: selected }) })
+
+				return Object.assign(prevState, { selected: selected });
+			}
+			case 'TEST_ADD_DATA': {
+				if (action.nodes) {
+					action.nodes.forEach(function (node) {
+						prevState.allNodesSet.update(node);
+						prevState.visibleNodesSet.update(node);
+					})
+				}
+				if (action.edges) {
+					action.edges.forEach(function (edge) {
+						prevState.allEdgesSet.update(edge);
+					})
+				}
+				DBG && console.log('DBG:NetworkGraph.TEST_ADD_DATA new state ', { state: Object.assign(prevState, {}) })
+				return Object.assign(prevState, {})
+			}
+			case 'RELOAD_NODES': {
+				var nodes = prevState.visibleNodesSet.map(function(e) { return e; }); // DataSet to Array
+				prevState.visibleNodesSet.clear();
+				var animAddNodes = (function (this__nodes, nodes, wait) {
+					return function (callback) {
+						DBG && console.log('DBG:animAddNodes', { nodes });
+						if (nodes.length > 0) {
+							var node = nodes.pop();
+							this__nodes.add(node);
+							setTimeout(function () {
+								animAddNodes(callback)
+							}, wait);
+						}
+					}
+				})(prevState.visibleNodesSet, nodes, 200);
+				animAddNodes(animAddNodes);
+			}
 			default: return prevState;
 		}
 	};
@@ -217,7 +329,7 @@ var Utils = (function __makeUtils() {
 					var state = getState();
 
 					if (state.receivedRequestId > this__requestId) {
-						DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
+						DBG && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
 						return;
 					}
 
@@ -235,8 +347,13 @@ var Utils = (function __makeUtils() {
 			}
 		}
 
+		var setSelected = function (selected) {
+			return { type: 'SET_SELECTED', selected: selected };
+		}
+
 		return {
 			fetchData: fetchData,
+			setSelected: setSelected,
 		}
 	};
 }
@@ -276,23 +393,27 @@ var p5UI__NetworkGraph = createReactClass({
 	getStateFromStore: function () {
 		var state = this.props.store.getState();
 		return {
+			visibleNodesSet: state.visibleNodesSet,
+			allEdgesSet: state.allEdgesSet,
 			isLoading: state.isLoading,
 			receivedRequestId: state.receivedRequestId, // to force render after udpate nodes, edges
 		}
 	},
 	getInitialState: function () {
-		if (this.props.selected) this._updateSelected(this.props.selected);
-		return {
+		// if (this.props.selected) this._updateSelected(this.props.selected);
+		return Object.assign({
 			initialized: false,
 			isLoading: false,
 			receivedRequestId: null,
-		};
+		}, this.getStateFromStore());
 	},
 	setOutputRef: function (elem) {
 		this._visOutputRef = elem;
 	},
 	componentDidMount: function () {
-		var data = { nodes: this._nodes, edges: this._edges };
+		// var data = { nodes: this._nodes, edges: this._edges };
+		var data = { nodes: this.state.visibleNodesSet, edges: this.state.allEdgesSet };
+		DBG && console.log('DBG:componentDidMount data', { data });
 		this._network = new vis.Network(this._visOutputRef, data, defaultNetworkGraphOptions);
 		if (this.props.onZoom) this._network.on('zoom', this.props.onZoom)
 		this.setState({ initialized: true });
@@ -325,13 +446,16 @@ var p5UI__NetworkGraph = createReactClass({
 	},
 
 	reloadGraph: function () {
+		this.props.store.dispatch({ type: 'RELOAD_NODES' })
+		return;
+
 		if (this._network) {
 			// this._network.setData({ nodes: [], edges: [] });
 			// var edges = this._edges.getDataSet();
 			var networkFit = (function (network) {
 				var _network = network;
 				return function () {
-					DBG1 && console.log('DBG:networkFit');
+					DBG && console.log('DBG:networkFit');
 					_network.fit();
 				}
 			})(this._network);
@@ -340,7 +464,7 @@ var p5UI__NetworkGraph = createReactClass({
 			// 	this._edges.clear();
 			// 	var animAddEdges = (function (this__edges, edges, wait) {
 			// 		return function (callback) {
-			// 			DBG1 && console.log('DBG:animAddEdges', { edges });
+			// 			DBG && console.log('DBG:animAddEdges', { edges });
 			// 			if (edges.length > 0) {
 			// 				var edge = edges.pop();
 			// 				this__edges.add(edge);
@@ -357,7 +481,7 @@ var p5UI__NetworkGraph = createReactClass({
 				this._nodes.clear();
 				var animAddNodes = (function (this__nodes, nodes, wait, onFinishCallback) {
 					return function (callback) {
-						DBG1 && console.log('DBG:animAddNodes', { nodes });
+						DBG && console.log('DBG:animAddNodes', { nodes });
 						if (nodes.length > 0) {
 							var node = nodes.pop();
 							this__nodes.add(node);
@@ -373,7 +497,7 @@ var p5UI__NetworkGraph = createReactClass({
 				})(this._nodes, nodes, 200, networkFit);
 				animAddNodes(animAddNodes);
 			}
-			// DBG1 && console.log('DBG: reloadGraph', { 'this._nodes': this._nodes, 'this._edges': this._edges, edges: edges });
+			// DBG && console.log('DBG: reloadGraph', { 'this._nodes': this._nodes, 'this._edges': this._edges, edges: edges });
 			// this._network.setData({ nodes: this._nodes, edges: this._edges });
 			// this._network.fit() // zoom out to fit container size
 		}
@@ -395,11 +519,20 @@ var p5UI__NetworkGraph = createReactClass({
 	testOnClick3: function () {
 		this.props.store.dispatch( this.props.storeActions.fetchData( this.props.raportId ) );
 	},
+	testOnClick4: function () {
+		DBG && console.log('DBG:Utils cache ', { cache: Utils.getCacheAllEdgeId() })
+	},
+	testOnClick5: function () {
+		var edges = [];
+		var nodes = [ { id: 'TERYT_adresy.123', label: "TER.123" }, { id: 'TERYT_adresy.666', label: "TER.666" } ];
+		DBG && console.log('DBG:testOnClick5 add custom node + edges ', { nodes: nodes, edges: edges })
+		this.props.store.dispatch({ type: 'TEST_ADD_DATA', nodes: nodes, edges: edges })
+	},
 
 	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 });
+		// 	DBG && console.warn("TODO: update nodes, edges", { state });
 		// 	// this._edges.add( edge_or_edges_array )
 		// 	if (state.nodes && state.nodes.length) {
 		// 		var __nodes = this._nodes;
@@ -421,7 +554,7 @@ var p5UI__NetworkGraph = createReactClass({
 		// }
 
 		if (this.props.selected.length != nextProps.selected.length) {
-			this._updateSelected(nextProps.selected)
+			// this._updateSelected(nextProps.selected)
 		}
 		return false;
 	},
@@ -452,32 +585,24 @@ var p5UI__NetworkGraph = createReactClass({
 			// 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);
+		DBG && 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();
 		{ // TODO: convert fid to node on found list
 			{ // if (!this._allNodes) {
 				this._allNodes = new vis.DataSet();
-				this._allNodes.add(state.nodes);
+				this._allNodes.update(state.nodes);
 			}
 
 			var this__allNodes = this._allNodes;
-			var __nodes = this._nodes;
-			var addNodesToGraph = addFidsToGraph.map(function (fid) {
+			var this__nodes = this._nodes;
+			addFidsToGraph.forEach(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');
-				}
+				this__nodes.update(node);
 			})
 		}
-		DBG1 && console.log('DBG: check edges: ', { 'this._edges.length': this._edges.length, 'state.edges.length': state.edges.length });
+		DBG && 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 });
+			DBG && console.log('DBG: TODO: update edges', { 'state.edges': state.edges });
 
 			var this__edges = this._edges;
 			state.edges.forEach(function (edge) {
@@ -495,12 +620,11 @@ var p5UI__NetworkGraph = createReactClass({
 			})
 		}
 		if (this._network) {
-			this._network.setData({ nodes: this._nodes, edges: this._edges });
-			this._network.fit() // zoom out to fit container size
+			// this._network.setData({ nodes: this._nodes, edges: this._edges });
+			// this._network.fit() // zoom to fit container size
 		}
 	},
 	render: function () {
-		DBG1 && console.log('DBG:render');
 		return h('div', { style: { 'position': "relative" } }, [
 			h('div', {
 				ref: this.setOutputRef,
@@ -522,11 +646,13 @@ var p5UI__NetworkGraph = createReactClass({
 					h('button', { onClick: this.reloadGraph, className: "btn btn-xs btn-default", title: "Odśwież" }, [ h('i', { className: "glyphicon glyphicon-random" }) ]),
 				]),
 			]),
-			h('div', {}, [
-				h('button', { onClick: this.testOnClick1 }, [ "TEST 1 ", h('small', [], "(+ node)") ]),
-				h('button', { onClick: this.testOnClick2 }, [ "TEST 2 ", h('small', [], "(+ edge)") ]),
-				h('button', { onClick: this.testOnClick3 }, [ "TEST 3 ", h('small', [], "(+ fetch)") ]),
-			]),
+			// h('div', {}, [
+			// 	h('button', { onClick: this.testOnClick1 }, [ "TEST 1 ", h('small', [], "(+ node)") ]),
+			// 	h('button', { onClick: this.testOnClick2 }, [ "TEST 2 ", h('small', [], "(+ edge)") ]),
+			// 	h('button', { onClick: this.testOnClick3 }, [ "TEST 3 ", h('small', [], "(+ fetch)") ]),
+			// 	h('button', { onClick: this.testOnClick4 }, [ "TEST 4 ", h('small', [], "(+ log Utils.cache)") ]),
+			// 	h('button', { onClick: this.testOnClick5 }, [ "TEST 5 ", h('small', [], "(+ data)") ]),
+			// ]),
 		]);
 	}
 });
@@ -543,14 +669,16 @@ var p5UI__RaportOutputPanel = createReactClass({
 			initSelected = state.nodes.filter(function (node) {
 				return ( -1 !== DBG_INIT_SELECTED.indexOf(node.id));
 			})
+			this.props.store.dispatch( this.props.storeActions.setSelected(initSelected) )
 		}
 		return {
 			selected: initSelected,
 		}
 	},
 	handleSelectFeatures: function (selected) {
-		DBG1 && console.log('DBG:typeahead selected:', { selected })
-		this.setState({ selected: selected });
+		DBG && console.log('DBG:typeahead selected:', { selected })
+		this.setState({ selected: selected }); // TODO: read from this.props.store.getState()
+		this.props.store.dispatch( this.props.storeActions.setSelected( selected ) );
 	},
 	_onZoom: function (event) {
 		// {
@@ -558,15 +686,15 @@ var p5UI__RaportOutputPanel = createReactClass({
 		// 	scale: Number,
 		// 	pointer: {x:pointer_x, y:pointer_y}
 		// }
-		DBG1 && console.log('DBG:onZoom', { scale: event.scale, event })
-		var this__handleZoomUpdate = this.handleZoomUpdate;
-	},
-	handleZoomUpdate: function () {
-		DBG1 && console.warn('DBG:handleZoomUpdate', { event })
+		DBG && console.log('DBG:onZoom', { scale: event.scale, event })
+		// var this__handleZoomUpdate = this.handleZoomUpdate;
 	},
+	// handleZoomUpdate: function () {
+	// 	DBG && console.warn('DBG:handleZoomUpdate', { event })
+	// },
 	render: function () {
 		var state = this.props.store.getState()
-		DBG1 && console.log('DBG: state', state);
+		DBG && console.log('DBG:render - state', state);
 		var nodes = state.nodes || [];
 
 		return h(React.Fragment, {}, [