BiAuditGraph.php.network-graph.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. var DBG = DBG || false;
  2. var DBG1 = true;
  3. var DBG_INIT_SELECTED = [ "BI_audit_ENERGA_RUM_KONTRAHENCI.18661", "BI_audit_KRS.389967" ];
  4. if ('undefined' === typeof HTML_ID_REF_GRAPH) throw "Missing HTML_ID_REF_GRAPH";
  5. if (!RAPORT_ID) throw "Missing RAPORT_ID";
  6. if (!API_URL) throw "Missing API_URL";
  7. if (!global.p5VendorJs) throw "Missing p5VendorJs";
  8. if (!global.vis) throw "Missing vis";
  9. if (!global.p5VendorJs.Typeahead) throw "Missing Typeahead";
  10. var createReactClass = global.p5VendorJs.createReactClass;
  11. var h = global.p5VendorJs.React.createElement;
  12. var React = global.p5VendorJs.React;
  13. var ReactDOM = global.p5VendorJs.ReactDOM;
  14. var Redux = global.p5VendorJs.Redux;
  15. var ReduxThunk = global.p5VendorJs.ReduxThunk;
  16. var createStoreWithThunkMiddleware = Redux.applyMiddleware(ReduxThunk)(Redux.createStore); // TODO: to vendor.js
  17. var Typeahead = global.p5VendorJs.Typeahead;
  18. var mapStatsNodeToGraphNode = function (node) {
  19. return {
  20. id: node['@object'] + '.' + node['@primaryKey'],
  21. label: Utils.nodeLabelShort(node['@label']),
  22. rawLabel: node['@label'],
  23. value: 1,
  24. level: 0,
  25. }
  26. };
  27. var mapStatsEdgeToGraphEdge = function (edge) {
  28. return {
  29. id: Utils.makeUniqueEdgeId(edge['source'], edge['target']),
  30. from: edge['source'],
  31. to: edge['target'],
  32. pathId: edge['pathId'],
  33. listPathId: [ edge['pathId'] ],
  34. }
  35. };
  36. //// DBG: Utils:
  37. // var from, to;
  38. // from = 'aa.11'; to = 'bb.22'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
  39. // from = 'bb.22'; to = 'aa.11'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
  40. // from = 'cc.22'; to = 'cc.11'; console.log('DBG: Utils.makeUniqueEdgeId('+from+', '+to+')', Utils.makeUniqueEdgeId(from, to), { cache: Utils.getCacheAllEdgeId().join(',') })
  41. var Utils = (function __makeUtils() {
  42. var Utils = {};
  43. var _cacheListFeatureNames = [];
  44. Utils.fidSplit = function (fid) {
  45. var dotPos = fid.indexOf('.');
  46. return [ fid.substr(0, dotPos), fid.substr(dotPos + 1) ];
  47. }
  48. Utils.makeUniqueEdgeId = function (from, to) {
  49. var listFidArr = [ from, to ].sort().map(Utils.fidSplit);
  50. var listIdx = listFidArr.map(function (fidArr) {
  51. var cacheIdx = _cacheListFeatureNames.indexOf(fidArr[0]);
  52. if (-1 === cacheIdx) {
  53. cacheIdx = _cacheListFeatureNames.length;
  54. _cacheListFeatureNames.push(fidArr[0]);
  55. }
  56. return cacheIdx;
  57. })
  58. return listIdx.map(function (cacheIdx, fidIdx) {
  59. return cacheIdx + '.' + listFidArr[fidIdx][1];
  60. }).join('-')
  61. }
  62. Utils.getCacheAllEdgeId = function () {
  63. return [].concat(_cacheListFeatureNames);
  64. }
  65. Utils.nodeLabelShort = function (label) {
  66. return label.replace('SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ', 'Sp. z o.o.')
  67. }
  68. return Utils;
  69. })();
  70. { // TODO: RaportOutputPanel - mv to another file
  71. var RaportOutputPanel = {};
  72. RaportOutputPanel.initialState = function () {
  73. var nodes = (STATS && STATS.nodes) ? STATS.nodes : [];
  74. var edges = (STATS && STATS.edges) ? STATS.edges : [];
  75. var paths = (STATS && STATS.path_list) ? STATS.path_list : [];
  76. DBG1 && console.log('DBG: STATS', STATS);
  77. return {
  78. nodes: nodes.map(mapStatsNodeToGraphNode),
  79. edges: edges.map(mapStatsEdgeToGraphEdge),
  80. paths: paths,
  81. isLoading: false,
  82. sentRequestId: 0,
  83. receivedRequestId: 0,
  84. }
  85. };
  86. RaportOutputPanel.store = function (state, action) {
  87. var prevState = state || RaportOutputPanel.initialState();
  88. DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
  89. switch (action.type) {
  90. case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
  91. sentRequestId: action.sentRequestId,
  92. isLoading: true
  93. });
  94. case 'SET_RESPONSE': return Object.assign(prevState, {
  95. receivedRequestId: action.requestId,
  96. nodes: action.body.nodes.map(mapStatsNodeToGraphNode),
  97. edges: action.body.edges,
  98. isLoading: (prevState.sentRequestId > action.requestId) ? true : false,
  99. });
  100. default: return prevState;
  101. }
  102. };
  103. RaportOutputPanel.createActions = function () {
  104. var setSentRequestId = function (sentRequestId) {
  105. return { type: 'SET_SENT_REQUEST_ID', sentRequestId: sentRequestId };
  106. }
  107. var setResponse = function (response) {
  108. return Object.assign(response, { type: 'SET_RESPONSE' });
  109. }
  110. var fetchData = function (raportId, params) {
  111. return function (dispatch, getState) {
  112. var state = getState();
  113. var this__requestId = state.sentRequestId + 1;
  114. dispatch(setSentRequestId(this__requestId));
  115. var reqPromise = window.fetch(API_URL, {
  116. method: 'GET',
  117. credentials: 'same-origin',
  118. }).then(function (response) {
  119. return response.json();
  120. });
  121. return reqPromise.then(function (response) {
  122. var items = response;
  123. var state = getState();
  124. if (state.receivedRequestId > this__requestId) {
  125. DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
  126. return;
  127. }
  128. dispatch(
  129. setResponse({
  130. requestId: this__requestId,
  131. msg: "Pobrano dane",
  132. body: response.body
  133. })
  134. );
  135. }).catch(function (e) {
  136. p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #GS1: ' + e});
  137. // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button
  138. });
  139. }
  140. }
  141. return {
  142. fetchData: fetchData,
  143. }
  144. };
  145. }
  146. { // TODO: NetworkGraph - mv to another file
  147. var NetworkGraph = {};
  148. NetworkGraph.initialState = function () {
  149. var nodes = (STATS && STATS.nodes) ? STATS.nodes : [];
  150. var edges = (STATS && STATS.edges) ? STATS.edges : [];
  151. var paths = (STATS && STATS.path_list) ? STATS.path_list : [];
  152. DBG1 && console.log('DBG: STATS', STATS);
  153. return {
  154. nodes: nodes.map(mapStatsNodeToGraphNode),
  155. edges: edges.map(mapStatsEdgeToGraphEdge),
  156. paths: paths,
  157. isLoading: false,
  158. sentRequestId: 0,
  159. receivedRequestId: 0,
  160. }
  161. };
  162. NetworkGraph.store = function (state, action) {
  163. var prevState = state || NetworkGraph.initialState();
  164. DBG1 && console.log('DBG: store', { prevState, action, actionType: action.type });
  165. switch (action.type) {
  166. case 'SET_SENT_REQUEST_ID': return Object.assign(prevState, {
  167. sentRequestId: action.sentRequestId,
  168. isLoading: true
  169. });
  170. case 'SET_RESPONSE': return Object.assign(prevState, {
  171. receivedRequestId: action.requestId,
  172. nodes: action.body.nodes.map(mapStatsNodeToGraphNode),
  173. edges: action.body.edges,
  174. isLoading: (prevState.sentRequestId > action.requestId) ? true : false,
  175. });
  176. default: return prevState;
  177. }
  178. };
  179. NetworkGraph.createActions = function () {
  180. var setSentRequestId = function (sentRequestId) {
  181. return { type: 'SET_SENT_REQUEST_ID', sentRequestId: sentRequestId };
  182. }
  183. var setResponse = function (response) {
  184. return Object.assign(response, { type: 'SET_RESPONSE' });
  185. }
  186. var fetchData = function (raportId, params) {
  187. return function (dispatch, getState) {
  188. var state = getState();
  189. var this__requestId = state.sentRequestId + 1;
  190. dispatch(setSentRequestId(this__requestId));
  191. var reqPromise = window.fetch(API_URL, {
  192. method: 'GET',
  193. credentials: 'same-origin',
  194. }).then(function (response) {
  195. return response.json();
  196. });
  197. return reqPromise.then(function (response) {
  198. var items = response;
  199. var state = getState();
  200. if (state.receivedRequestId > this__requestId) {
  201. DBG1 && console.log('DBG: skipped response', { 'state.receivedRequestId': state.receivedRequestId, this__requestId });
  202. return;
  203. }
  204. dispatch(
  205. setResponse({
  206. requestId: this__requestId,
  207. msg: "Pobrano dane",
  208. body: response.body
  209. })
  210. );
  211. }).catch(function (e) {
  212. p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #GS1: ' + e});
  213. // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button
  214. });
  215. }
  216. }
  217. return {
  218. fetchData: fetchData,
  219. }
  220. };
  221. }
  222. var defaultNetworkGraphOptions = {
  223. nodes: {
  224. shape: 'dot',
  225. scaling: {
  226. min: 8, max: 30,
  227. label: {
  228. min: 8, max: 16, drawThreshold: 6, maxVisible: 20
  229. }
  230. },
  231. font: { color: "#666", size: 10, face: 'Helvetica Neue, Helvetica, Arial' }
  232. // font: "8px Helvetica Neue, Helvetica, Arial"
  233. },
  234. interaction: {
  235. hover: true,
  236. hoverConnectedEdges: false,
  237. selectConnectedEdges: true,
  238. },
  239. physics: {
  240. barnesHut: {
  241. avoidOverlap: 0.2
  242. }
  243. },
  244. };
  245. var TMP_COUNTER = 1;
  246. var p5UI__NetworkGraph = createReactClass({
  247. _network: null,
  248. _visOutputRef: React.createRef(),
  249. _allNodes: null, // new vis.DataSet(),
  250. _allEdges: null, // new vis.DataSet(),
  251. _nodes: new vis.DataSet(),
  252. _edges: new vis.DataSet(),
  253. getStateFromStore: function () {
  254. var state = this.props.store.getState();
  255. return {
  256. isLoading: state.isLoading,
  257. receivedRequestId: state.receivedRequestId, // to force render after udpate nodes, edges
  258. }
  259. },
  260. getInitialState: function () {
  261. if (this.props.selected) this._updateSelected(this.props.selected);
  262. return {
  263. initialized: false,
  264. isLoading: false,
  265. receivedRequestId: null,
  266. };
  267. },
  268. setOutputRef: function (elem) {
  269. this._visOutputRef = elem;
  270. },
  271. componentDidMount: function () {
  272. var data = { nodes: this._nodes, edges: this._edges };
  273. this._network = new vis.Network(this._visOutputRef, data, defaultNetworkGraphOptions);
  274. if (this.props.onZoom) this._network.on('zoom', this.props.onZoom)
  275. this.setState({ initialized: true });
  276. this._unsubscribe = this.props.store.subscribe(this._storeUpdated)
  277. },
  278. _storeUpdated: function () {
  279. this.setState( this.getStateFromStore() )
  280. },
  281. fitToContainer: function () {
  282. if (this._network) {
  283. this._network.fit()
  284. }
  285. },
  286. incScale: function () {
  287. if (this._network) {
  288. var scale = this._network.getScale();
  289. this._network.moveTo({
  290. scale: scale + 0.2
  291. })
  292. }
  293. },
  294. decScale: function () {
  295. if (this._network) {
  296. var scale = this._network.getScale();
  297. this._network.moveTo({
  298. scale: (scale > 0.3) ? scale - 0.2 : scale
  299. })
  300. }
  301. },
  302. reloadGraph: function () {
  303. if (this._network) {
  304. // this._network.setData({ nodes: [], edges: [] });
  305. // var edges = this._edges.getDataSet();
  306. var networkFit = (function (network) {
  307. var _network = network;
  308. return function () {
  309. DBG1 && console.log('DBG:networkFit');
  310. _network.fit();
  311. }
  312. })(this._network);
  313. // {
  314. // var edges = this._edges.map(function(e) { return e; }); // DataSet to Array
  315. // this._edges.clear();
  316. // var animAddEdges = (function (this__edges, edges, wait) {
  317. // return function (callback) {
  318. // DBG1 && console.log('DBG:animAddEdges', { edges });
  319. // if (edges.length > 0) {
  320. // var edge = edges.pop();
  321. // this__edges.add(edge);
  322. // setTimeout(function () {
  323. // animAddEdges(callback)
  324. // }, wait);
  325. // }
  326. // }
  327. // })(this._edges, edges, 10);
  328. // animAddEdges(animAddEdges);
  329. // }
  330. {
  331. var nodes = this._nodes.map(function(e) { return e; }); // DataSet to Array
  332. this._nodes.clear();
  333. var animAddNodes = (function (this__nodes, nodes, wait, onFinishCallback) {
  334. return function (callback) {
  335. DBG1 && console.log('DBG:animAddNodes', { nodes });
  336. if (nodes.length > 0) {
  337. var node = nodes.pop();
  338. this__nodes.add(node);
  339. setTimeout(function () {
  340. animAddNodes(callback)
  341. }, wait);
  342. } else if (onFinishCallback) {
  343. setTimeout(function () {
  344. onFinishCallback()
  345. }, 500);
  346. }
  347. }
  348. })(this._nodes, nodes, 200, networkFit);
  349. animAddNodes(animAddNodes);
  350. }
  351. // DBG1 && console.log('DBG: reloadGraph', { 'this._nodes': this._nodes, 'this._edges': this._edges, edges: edges });
  352. // this._network.setData({ nodes: this._nodes, edges: this._edges });
  353. // this._network.fit() // zoom out to fit container size
  354. }
  355. },
  356. testOnClick1: function () {
  357. TMP_COUNTER++;
  358. this._nodes.add({ id: TMP_COUNTER, label: "Node " + TMP_COUNTER, value: TMP_COUNTER, level: 0 });
  359. },
  360. testOnClick2: function () {
  361. TMP_COUNTER++;
  362. var ids = this._nodes.getIds();
  363. var totalNodes = ids.length
  364. if (totalNodes < 3) return;
  365. var fromIdx = Math.floor(Math.random() * totalNodes);
  366. var toIdx = Math.floor(Math.random() * totalNodes);
  367. this._edges.add({ from: ids[fromIdx], to: ids[toIdx] });
  368. },
  369. testOnClick3: function () {
  370. this.props.store.dispatch( this.props.storeActions.fetchData( this.props.raportId ) );
  371. },
  372. shouldComponentUpdate: function (nextProps, nextState) {
  373. // if (this.state.receivedRequestId !== nextState.receivedRequestId) { // add missing nodes
  374. // var state = this.props.store.getState();
  375. // DBG1 && console.warn("TODO: update nodes, edges", { state });
  376. // // this._edges.add( edge_or_edges_array )
  377. // if (state.nodes && state.nodes.length) {
  378. // var __nodes = this._nodes;
  379. // state.nodes.forEach(function (node) {
  380. // __nodes.add(node);
  381. // })
  382. // }
  383. // // edge: { from: page, to: subpageID, color:getEdgeColor(level), level: level, selectionWidth:2, hoverWidth:0 }
  384. // if (state.edges && state.edges.length) {
  385. // var __edges = this._edges;
  386. // // state.edges.forEach(function (edge) {
  387. // state.edges.slice(0, 30).forEach(function (edge) {
  388. // __edges.add({
  389. // from: edge.source,
  390. // to: edge.target,
  391. // });
  392. // })
  393. // }
  394. // }
  395. if (this.props.selected.length != nextProps.selected.length) {
  396. this._updateSelected(nextProps.selected)
  397. }
  398. return false;
  399. },
  400. _updateSelected: function (selected) { // TODO: move to RaportOutputPanel Store
  401. var state = this.props.store.getState();
  402. var idsSelected = (selected || []).map( function (node) { return node.id } )
  403. var nodes = [];
  404. // var edges = state.edges.filter(function (edge) { // use idsSelected - TODO: RMME
  405. // return ( -1 !== idsSelected.indexOf(edge.source) || -1 !== idsSelected.indexOf(edge.target) );
  406. // })
  407. {
  408. // TODO: find all paths with selected fids
  409. var foundPaths = state.paths.filter(function (path) {
  410. for (var i = 0, totalFids = path.fids.length, fid = null; i < totalFids; i++) {
  411. fid = path.fids[i];
  412. DBG && console.log('DBG:foundPaths ', {fid: ''+fid, path});
  413. if ( -1 !== idsSelected.indexOf(fid) ) return true;
  414. }
  415. return false;
  416. })
  417. // TODO: add missing nodes (not selected but on path)
  418. var addFidsToGraph = Array.from(new Set(foundPaths.reduce(function (ret, path) {
  419. return ret.concat(path.fids.filter(function (fid) {
  420. return ( -1 === idsSelected.indexOf(fid) );
  421. }))
  422. }, [])));
  423. // TODO: view only combined path or all not selected nodes? - trying: not selected nodes
  424. // TODO: convert found paths to graph edges
  425. }
  426. DBG1 && console.warn('DBG: TODO set edges by selectd nodes...', { state_nodes: state.nodes, state_edges: state.edges, idsSelected, foundPaths, addFidsToGraph });
  427. this._nodes = new vis.DataSet(selected);
  428. { // TODO: convert fid to node on found list
  429. { // if (!this._allNodes) {
  430. this._allNodes = new vis.DataSet();
  431. this._allNodes.add(state.nodes);
  432. }
  433. var this__allNodes = this._allNodes;
  434. var __nodes = this._nodes;
  435. var addNodesToGraph = addFidsToGraph.map(function (fid) {
  436. var node = this__allNodes.get(fid)
  437. try {
  438. DBG1 && console.log('DBG: TODO add node (fid:'+fid+') ', { node, this__allNodes, fid });
  439. __nodes.add(node);
  440. __nodes.update(Object.assign(node, { color: '#ddd', size: 100 }));
  441. DBG1 && console.log('DBG: added red node (fid:'+fid+') ', { node });
  442. } catch (e) {
  443. DBG1 && console.log(e);
  444. DBG1 && console.log('DBG: skip node (fid:'+fid+') already added');
  445. }
  446. })
  447. }
  448. DBG1 && console.log('DBG: check edges: ', { 'this._edges.length': this._edges.length, 'state.edges.length': state.edges.length });
  449. if (this._edges.length != state.edges.length) {
  450. DBG1 && console.log('DBG: TODO: update edges', { 'state.edges': state.edges });
  451. var this__edges = this._edges;
  452. state.edges.forEach(function (edge) {
  453. var foundEdge = this__edges.get(edge.id);
  454. if (!foundEdge) {
  455. this__edges.add(edge);
  456. } else {
  457. var listPathId = (-1 !== foundEdge.listPathId.indexOf(edge.pathId)) ? foundEdge.listPathId : foundEdge.listPathId.concat(edge.pathId);
  458. var mergedEdge = Object.assign(foundEdge, {
  459. listPathId: listPathId,
  460. width: 1 + (listPathId.length - 1) / 10,
  461. });
  462. this__edges.update(mergedEdge);
  463. }
  464. })
  465. }
  466. if (this._network) {
  467. this._network.setData({ nodes: this._nodes, edges: this._edges });
  468. this._network.fit() // zoom out to fit container size
  469. }
  470. },
  471. render: function () {
  472. DBG1 && console.log('DBG:render');
  473. return h('div', { style: { 'position': "relative" } }, [
  474. h('div', {
  475. ref: this.setOutputRef,
  476. style: {
  477. 'min-height': 600,
  478. 'height': 600,
  479. 'border-radius': "6px",
  480. 'border': "1px solid #ddd",
  481. },
  482. }),
  483. h('div', { className: "", style: { position: "absolute", right: 10, top: 10 } }, [
  484. h('div', { className: "btn-group-vertical", title: "Powiększenie" }, [
  485. h('button', { onClick: this.incScale, className: "btn btn-xs btn-default" }, [ h('i', { className: "glyphicon glyphicon-plus" }) ]),
  486. h('button', { onClick: this.fitToContainer, className: "btn btn-xs btn-default" }, [ "100%" ]),
  487. h('button', { onClick: this.decScale, className: "btn btn-xs btn-default" }, [ h('i', { className: "glyphicon glyphicon-minus" }) ]),
  488. ]),
  489. h('div', { style: { clear: "both", margin: 4 } }),
  490. h('div', { className: "btn-group-vertical", style: { width: "100%" } }, [
  491. h('button', { onClick: this.reloadGraph, className: "btn btn-xs btn-default", title: "Odśwież" }, [ h('i', { className: "glyphicon glyphicon-random" }) ]),
  492. ]),
  493. ]),
  494. h('div', {}, [
  495. h('button', { onClick: this.testOnClick1 }, [ "TEST 1 ", h('small', [], "(+ node)") ]),
  496. h('button', { onClick: this.testOnClick2 }, [ "TEST 2 ", h('small', [], "(+ edge)") ]),
  497. h('button', { onClick: this.testOnClick3 }, [ "TEST 3 ", h('small', [], "(+ fetch)") ]),
  498. ]),
  499. ]);
  500. }
  501. });
  502. /**
  503. * props.store: networkGraphStore
  504. * - used: state.nodes
  505. */
  506. var p5UI__RaportOutputPanel = createReactClass({
  507. getInitialState: function () {
  508. var initSelected = [];
  509. if (DBG_INIT_SELECTED) {
  510. var state = this.props.store.getState()
  511. initSelected = state.nodes.filter(function (node) {
  512. return ( -1 !== DBG_INIT_SELECTED.indexOf(node.id));
  513. })
  514. }
  515. return {
  516. selected: initSelected,
  517. }
  518. },
  519. handleSelectFeatures: function (selected) {
  520. DBG1 && console.log('DBG:typeahead selected:', { selected })
  521. this.setState({ selected: selected });
  522. },
  523. _onZoom: function (event) {
  524. // {
  525. // direction: '+'/'-',
  526. // scale: Number,
  527. // pointer: {x:pointer_x, y:pointer_y}
  528. // }
  529. DBG1 && console.log('DBG:onZoom', { scale: event.scale, event })
  530. var this__handleZoomUpdate = this.handleZoomUpdate;
  531. },
  532. handleZoomUpdate: function () {
  533. DBG1 && console.warn('DBG:handleZoomUpdate', { event })
  534. },
  535. render: function () {
  536. var state = this.props.store.getState()
  537. DBG1 && console.log('DBG: state', state);
  538. var nodes = state.nodes || [];
  539. return h(React.Fragment, {}, [
  540. h(Typeahead, {
  541. labelKey: "label",
  542. multiple: true,
  543. options: nodes,
  544. placeholder: "Wybierz",
  545. bsSize: 'large',
  546. selected: this.state.selected,
  547. onChange: this.handleSelectFeatures,
  548. }),
  549. h(p5UI__NetworkGraph, {
  550. raportId: this.props.raportId,
  551. store: this.props.store,
  552. storeActions: this.props.storeActions,
  553. selected: this.state.selected,
  554. onZoom: window._.throttle(this._onZoom, 500),
  555. })
  556. ])
  557. }
  558. })
  559. ReactDOM.render(
  560. h(p5UI__RaportOutputPanel, {
  561. raportId: RAPORT_ID,
  562. store: createStoreWithThunkMiddleware(NetworkGraph.store),
  563. storeActions: NetworkGraph.createActions(),
  564. }),
  565. document.getElementById(HTML_ID_REF_GRAPH)
  566. );