From e2c1bdf9e178e22f6b9daff848feae0c1f7e3c2e Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 09:17:43 -0800 Subject: [PATCH 01/33] filter: Stop tracking netcreate-config.js. This is an autogenerated file that should not be in the repo. --- build/app/assets/netcreate-config.js | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 build/app/assets/netcreate-config.js diff --git a/build/app/assets/netcreate-config.js b/build/app/assets/netcreate-config.js deleted file mode 100644 index fd4891406..000000000 --- a/build/app/assets/netcreate-config.js +++ /dev/null @@ -1,9 +0,0 @@ - -// this file generated by NC command -const NC_CONFIG = { - dataset: "CHAT", - port: "3000", - googlea: "0" -}; -if (typeof process === "object") module.exports = NC_CONFIG; -if (typeof window === "object") window.NC_CONFIG = NC_CONFIG; \ No newline at end of file From 23ee166ebefb25d8d86d29d3c4e55e4fe59b0c56 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 09:18:28 -0800 Subject: [PATCH 02/33] filter: Move comment to the correct code block. --- .../netcreate/components/d3-simplenetgraph.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/app/view/netcreate/components/d3-simplenetgraph.js b/build/app/view/netcreate/components/d3-simplenetgraph.js index 3d387f23e..69548b0a1 100644 --- a/build/app/view/netcreate/components/d3-simplenetgraph.js +++ b/build/app/view/netcreate/components/d3-simplenetgraph.js @@ -403,20 +403,20 @@ class D3NetGraph { if (d.selected || d.strokeColor) return '5px'; return undefined // don't set stroke width }) -// this "r" is necessary to resize after a link is added .attr("fill", (d) => { // REVIEW: Using label match. Should we use id instead? return COLORMAP[d.attributes["Node_Type"]]; }) .attr("r", (d) => { - let radius = this.data.edges.reduce((acc,ed)=>{ - return (ed.source.id===d.id || ed.target.id===d.id) ? acc+1 : acc - },1); - - d.weight = radius - d.size = radius // save the calculated size - d.degrees = radius - 1 - return this.defaultSize + (this.defaultSize * d.weight / 2) + // this "r" is necessary to resize after a link is added + let radius = this.data.edges.reduce((acc,ed)=>{ + return (ed.source.id===d.id || ed.target.id===d.id) ? acc+1 : acc + },1); + + d.weight = radius + d.size = radius // save the calculated size + d.degrees = radius - 1 + return this.defaultSize + (this.defaultSize * d.weight / 2) }) .transition() .duration(500) From 7287873ac9281282824f46afed48612f2c930161 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 09:19:09 -0800 Subject: [PATCH 03/33] filter: lint - disable complexity complaint. --- build/app/view/netcreate/nc-logic.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/app/view/netcreate/nc-logic.js b/build/app/view/netcreate/nc-logic.js index e351436b7..9ed8584b1 100644 --- a/build/app/view/netcreate/nc-logic.js +++ b/build/app/view/netcreate/nc-logic.js @@ -221,6 +221,7 @@ MOD.Hook("LOADASSETS", () => { /*/ CONFIGURE fires after LOADASSETS, so this is a good place to put TEMPLATE validation. /*/ +// eslint-disable-next-line complexity MOD.Hook("CONFIGURE", () => { // Process Node, NodeColorMap and Edge options From a47e7eece6edc7fbaa04ea9820aced191e4ccb27 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 10:00:21 -0800 Subject: [PATCH 04/33] filter: Rename "Filters" panel to "Highlight" --- build/app/view/netcreate/components/InfoPanel.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/app/view/netcreate/components/InfoPanel.jsx b/build/app/view/netcreate/components/InfoPanel.jsx index 82705a859..04d0e16a9 100644 --- a/build/app/view/netcreate/components/InfoPanel.jsx +++ b/build/app/view/netcreate/components/InfoPanel.jsx @@ -181,7 +181,7 @@ class InfoPanel extends UNISYS.Component { className={classnames({ active: activeTab === '2' })} onClick={() => { this.toggle('2'); this.sendGA('Filter', window.location); }} > - Filters + Highlight From 15f84f2a5e3e1b55fac3bd588a1c552e566da0f1 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 10:08:39 -0800 Subject: [PATCH 05/33] filter: Add Filter tab. --- .../view/netcreate/components/InfoPanel.jsx | 40 ++++++++++++------- .../components/filter/FilterEnums.js | 5 +++ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/build/app/view/netcreate/components/InfoPanel.jsx b/build/app/view/netcreate/components/InfoPanel.jsx index 04d0e16a9..fcd256864 100644 --- a/build/app/view/netcreate/components/InfoPanel.jsx +++ b/build/app/view/netcreate/components/InfoPanel.jsx @@ -29,6 +29,7 @@ const ReactStrap = require('reactstrap'); const { TabContent, TabPane, Nav, NavItem, NavLink, Row, Col, Button } = ReactStrap; const classnames = require('classnames'); +import FILTER from './filter/FilterEnums'; const FiltersPanel = require('./filter/FiltersPanel'); const NodeTable = require('./NodeTable'); const EdgeTable = require('./EdgeTable'); @@ -179,7 +180,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('2'); this.sendGA('Filter', window.location); }} + onClick={() => { this.toggle('2'); this.sendGA('Highlight', window.location); }} > Highlight @@ -187,31 +188,39 @@ class InfoPanel extends UNISYS.Component { { this.toggle('3'); this.sendGA('Nodes Table', window.location); }} + onClick={() => { this.toggle('3'); this.sendGA('Filter', window.location); }} > - Nodes Table + Filter { this.toggle('4'); this.sendGA('Edges Table', window.location); }} + onClick={() => { this.toggle('4'); this.sendGA('Nodes Table', window.location); }} > - Edges Table + Nodes Table { this.toggle('5'); this.sendGA('Vocabulary', window.location); }} + onClick={() => { this.toggle('5'); this.sendGA('Edges Table', window.location); }} > - Vocabulary + Edges Table { this.toggle('6'); this.sendGA('Help', window.location); }} + onClick={() => { this.toggle('6'); this.sendGA('Vocabulary', window.location); }} + > + Vocabulary + + + + { this.toggle('7'); this.sendGA('Help', window.location); }} > Help @@ -221,30 +230,33 @@ class InfoPanel extends UNISYS.Component { - + + + + - {activeTab==="3" && } + {activeTab==="4" && } - + - {activeTab==="4" && } + {activeTab==="5" && } - + - + diff --git a/build/app/view/netcreate/components/filter/FilterEnums.js b/build/app/view/netcreate/components/filter/FilterEnums.js index 5dff9f901..2c4e0b39c 100644 --- a/build/app/view/netcreate/components/filter/FilterEnums.js +++ b/build/app/view/netcreate/components/filter/FilterEnums.js @@ -1,5 +1,10 @@ const FILTER = {}; +// Determines whether filter action is to highlight/fade or remove (filter) nodes and edges +FILTER.ACTION = {}; +FILTER.ACTION.HIGHLIGHT = 'highlight'; +FILTER.ACTION.FILTER = 'filter'; + // Types of filters definable in template files. FILTER.TYPES = {}; FILTER.TYPES.STRING = 'string'; From 3288d1d49c09c4cda9353a04d4d26bd687126a20 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 10:24:37 -0800 Subject: [PATCH 06/33] filter: Add 'filterAction' to Filter components. --- .../app/view/netcreate/components/filter/FilterGroup.jsx | 8 ++++---- .../app/view/netcreate/components/filter/FiltersPanel.jsx | 3 ++- .../app/view/netcreate/components/filter/NumberFilter.js | 5 ++++- .../app/view/netcreate/components/filter/SelectFilter.js | 5 ++++- .../app/view/netcreate/components/filter/StringFilter.jsx | 5 ++++- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/build/app/view/netcreate/components/filter/FilterGroup.jsx b/build/app/view/netcreate/components/filter/FilterGroup.jsx index 488ffbee0..fafde5aeb 100644 --- a/build/app/view/netcreate/components/filter/FilterGroup.jsx +++ b/build/app/view/netcreate/components/filter/FilterGroup.jsx @@ -8,7 +8,7 @@ const ReactStrap = require('reactstrap'); const { Input, Label } = ReactStrap; export default function FilterGroup({ - group, label, filters, transparency + group, label, filters, filterAction, transparency }) { return (
@@ -17,13 +17,13 @@ export default function FilterGroup({ switch (filter.type) { case FILTER.TYPES.STRING: case FILTER.TYPES.NODE: - return + return break; case FILTER.TYPES.NUMBER: - return + return break; case FILTER.TYPES.SELECT: - return + return break; default: console.error(`FilterGroup: Filter Type not found ${filter.type} for filter`, filter); diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index 1b67aaa60..9707fb8ff 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -60,7 +60,7 @@ class FiltersPanel extends UNISYS.Component { } render() { - const { tableHeight } = this.props; + const { tableHeight, filterAction } = this.props; const defs = [this.state.nodes, this.state.edges]; return (
)} diff --git a/build/app/view/netcreate/components/filter/NumberFilter.js b/build/app/view/netcreate/components/filter/NumberFilter.js index 01823f867..9bff45904 100644 --- a/build/app/view/netcreate/components/filter/NumberFilter.js +++ b/build/app/view/netcreate/components/filter/NumberFilter.js @@ -95,6 +95,7 @@ class NumberFilter extends React.Component { } TriggerChangeHandler() { + const { filterAction } = this.props; const { id, type, key, keylabel } = this.props.filter; const filter = { id, @@ -106,11 +107,13 @@ class NumberFilter extends React.Component { }; UDATA.LocalCall('FILTER_DEFINE', { group: this.props.group, - filter + filter, + filterAction }); // set a SINGLE filter } render() { + const { filterAction } = this.props; const { id, key, keylabel, operator, value } = this.props.filter; return (
diff --git a/build/app/view/netcreate/components/filter/SelectFilter.js b/build/app/view/netcreate/components/filter/SelectFilter.js index e969c6c17..8a9f28e39 100644 --- a/build/app/view/netcreate/components/filter/SelectFilter.js +++ b/build/app/view/netcreate/components/filter/SelectFilter.js @@ -92,6 +92,7 @@ class SelectFilter extends React.Component { } TriggerChangeHandler() { + const { filterAction } = this.props; const { id, type, key, keylabel, options } = this.props.filter; const filter = { id, @@ -104,7 +105,8 @@ class SelectFilter extends React.Component { }; UDATA.LocalCall('FILTER_DEFINE', { group: this.props.group, - filter + filter, + filterAction }); // set a SINGLE filter } @@ -116,6 +118,7 @@ class SelectFilter extends React.Component { } render() { + const { filterAction } = this.props; const { id, key, keylabel, operator, value, options } = this.props.filter; return ( diff --git a/build/app/view/netcreate/components/filter/StringFilter.jsx b/build/app/view/netcreate/components/filter/StringFilter.jsx index 1322272e7..116458f53 100644 --- a/build/app/view/netcreate/components/filter/StringFilter.jsx +++ b/build/app/view/netcreate/components/filter/StringFilter.jsx @@ -87,6 +87,7 @@ class StringFilter extends React.Component { } TriggerChangeHandler() { + const { filterAction } = this.props; const { id, type, key, keylabel } = this.props.filter; const filter = { id, @@ -98,11 +99,13 @@ class StringFilter extends React.Component { }; UDATA.LocalCall('FILTER_DEFINE', { group: this.props.group, - filter + filter, + filterAction }); // set a SINGLE filter } render() { + const { filterAction } = this.props; const { id, key, keylabel, operator, value } = this.props.filter; return ( From ac62e84b3d974a1be702445c47d5442fed895fc3 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Wed, 10 Nov 2021 10:24:48 -0800 Subject: [PATCH 07/33] filter: Show different help text based on filter action. --- build/app/view/netcreate/components/filter/FiltersPanel.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index 9707fb8ff..a1b63a283 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -69,6 +69,12 @@ class FiltersPanel extends UNISYS.Component { display: 'flex', flexDirection: 'column', maxHeight: tableHeight }}> +
{defs.map(def => Date: Wed, 10 Nov 2021 17:29:46 -0800 Subject: [PATCH 08/33] filter: Disallow input if filter operator is not yet selected. --- build/app/view/netcreate/components/filter/NumberFilter.js | 3 ++- build/app/view/netcreate/components/filter/StringFilter.jsx | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/build/app/view/netcreate/components/filter/NumberFilter.js b/build/app/view/netcreate/components/filter/NumberFilter.js index 9bff45904..8c1105326 100644 --- a/build/app/view/netcreate/components/filter/NumberFilter.js +++ b/build/app/view/netcreate/components/filter/NumberFilter.js @@ -129,7 +129,8 @@ class NumberFilter extends React.Component { )} + onChange={this.OnChangeValue} bsSize="sm" + disabled={operator === FILTER.OPERATORS.NO_OP.key}/> ); diff --git a/build/app/view/netcreate/components/filter/StringFilter.jsx b/build/app/view/netcreate/components/filter/StringFilter.jsx index 116458f53..ed3cb6e1d 100644 --- a/build/app/view/netcreate/components/filter/StringFilter.jsx +++ b/build/app/view/netcreate/components/filter/StringFilter.jsx @@ -122,8 +122,9 @@ class StringFilter extends React.Component { )} + style={{ maxWidth: '12em', height: '1.5em' }} + onChange={this.OnChangeValue} bsSize="sm" + disabled={operator === FILTER.OPERATORS.NO_OP.key}/> ); From c8426b5c3ef8c3fabeba66331f210d3358d29465 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:01:03 -0800 Subject: [PATCH 09/33] filters: Just use 'filteredTransparency' instead of also using 'isFilteredOut'. The parameters are redundant. --- .../netcreate/components/d3-simplenetgraph.js | 12 +++++----- build/app/view/netcreate/filter-logic.js | 24 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/build/app/view/netcreate/components/d3-simplenetgraph.js b/build/app/view/netcreate/components/d3-simplenetgraph.js index 69548b0a1..4bf31c878 100644 --- a/build/app/view/netcreate/components/d3-simplenetgraph.js +++ b/build/app/view/netcreate/components/d3-simplenetgraph.js @@ -331,7 +331,7 @@ class D3NetGraph { return COLORMAP[d.attributes["Node_Type"]]; }) .style("opacity", d => { - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); // enter node: also append 'text' element @@ -343,7 +343,7 @@ class D3NetGraph { .attr("dy", "0.35em") // ".15em") .text((d) => { return d.label }) .style("opacity", d => { - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); // enter node: also append a 'title' tag @@ -422,7 +422,7 @@ class D3NetGraph { .duration(500) .style("opacity", d => { // console.log(d); - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); // UPDATE text in each node for all nodes @@ -443,7 +443,7 @@ class D3NetGraph { .transition() .duration(500) .style("opacity", d => { - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); nodeElements.merge(nodeElements) @@ -471,7 +471,7 @@ class D3NetGraph { // this.edgeClickFn( d ) // }) .style("opacity", d => { - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); // .merge() updates the visuals whenever the data is updated. @@ -482,7 +482,7 @@ class D3NetGraph { .transition() .duration(500) .style("opacity", d => { - return d.isFilteredOut ? d.filteredTransparency : 1.0 + return d.filteredTransparency }); linkElements.exit().remove() diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index 046bf1909..bf946985d 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -392,13 +392,16 @@ function m_FiltersApplyToNode(node, filters, transparency) { } }); if (all_no_op) { - // no filters defined, undo isFilteredOut - node.isFilteredOut = false; + // all filters are "no_op", so no filters defined, don't filter anything + node.filteredTransparency = 1.0; // opaque, not tranparent } else { // node is filtered out if it fails any filter tests - node.isFilteredOut = !matched; - - node.filteredTransparency = transparency; // set the transparency value ... right now it is inefficient to set this at the node / edge level, but that's more flexible + if (!matched) { + node.filteredTransparency = transparency; // set the transparency value ... right now it is inefficient to set this at the node / edge level, but that's more flexible + } else { + node.filteredTransparency = 1.0; // opaque + } + } } } @@ -471,11 +474,16 @@ function m_FiltersApplyToEdge(edge, filters, transparency) { }); if (all_no_op) { // no filters defined, undo isFilteredOut - edge.isFilteredOut = false; + edge.filteredTransparency = 1.0; } else { // edge is filtered out if it fails ANY filter tests - edge.isFilteredOut = !matched; - edge.filteredTransparency = transparency;; // set the transparency value ... right now it is inefficient to set this at the node / edge level, but that's more flexible + if (!matched) { + edge.filteredTransparency = transparency; // set the transparency value ... right now it is inefficient to set this at the node / edge level, but that's more flexible + } else { + edge.filteredTransparency = 1.0; // opaque + } + } + } } From a97cce65f7ea6b84088d5574ec76265d65c3b5b4 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:03:06 -0800 Subject: [PATCH 10/33] filters: Move 'componentWillUnmount' call to proper order (before custom methods) --- build/app/view/netcreate/components/filter/FiltersPanel.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index a1b63a283..e21e10212 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -46,6 +46,9 @@ class FiltersPanel extends UNISYS.Component { UDATA.OnAppStateChange("FDATA", this.UpdateFilterDefs); } // constructor + componentWillUnmount() { + // console.error('TBD: gracefully unsubscribe!') + } UpdateFilterDefs(data) { this.setState(data); @@ -55,8 +58,6 @@ class FiltersPanel extends UNISYS.Component { UDATA.LocalCall('FILTER_CLEAR'); } - componentWillUnmount() { - // console.error('TBD: gracefully unsubscribe!') } render() { From 6bed8f2e6af178fc10410b65d4545ed2143bb616 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:04:06 -0800 Subject: [PATCH 11/33] filters: Combine Highlight and Filter into a single tab with a toggle button. --- .../view/netcreate/components/InfoPanel.jsx | 34 ++++++------------- .../components/filter/FiltersPanel.jsx | 27 ++++++++++++--- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/build/app/view/netcreate/components/InfoPanel.jsx b/build/app/view/netcreate/components/InfoPanel.jsx index fcd256864..adef1c2f5 100644 --- a/build/app/view/netcreate/components/InfoPanel.jsx +++ b/build/app/view/netcreate/components/InfoPanel.jsx @@ -29,7 +29,6 @@ const ReactStrap = require('reactstrap'); const { TabContent, TabPane, Nav, NavItem, NavLink, Row, Col, Button } = ReactStrap; const classnames = require('classnames'); -import FILTER from './filter/FilterEnums'; const FiltersPanel = require('./filter/FiltersPanel'); const NodeTable = require('./NodeTable'); const EdgeTable = require('./EdgeTable'); @@ -182,20 +181,12 @@ class InfoPanel extends UNISYS.Component { className={classnames({ active: activeTab === '2' })} onClick={() => { this.toggle('2'); this.sendGA('Highlight', window.location); }} > - Highlight + Highlight / Filter { this.toggle('3'); this.sendGA('Filter', window.location); }} - > - Filter - - - - { this.toggle('4'); this.sendGA('Nodes Table', window.location); }} > Nodes Table @@ -203,7 +194,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('5'); this.sendGA('Edges Table', window.location); }} > Edges Table @@ -211,7 +202,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('6'); this.sendGA('Vocabulary', window.location); }} > Vocabulary @@ -219,7 +210,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('7'); this.sendGA('Help', window.location); }} > Help @@ -230,33 +221,30 @@ class InfoPanel extends UNISYS.Component { - + - - - - {activeTab==="4" && } + {activeTab==="3" && } - + - {activeTab==="5" && } + {activeTab==="4" && } - + - + @@ -277,7 +265,7 @@ class InfoPanel extends UNISYS.Component {
); diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index e21e10212..70aeaccf3 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -20,7 +20,7 @@ import React from 'react'; import StringFilter from './StringFilter'; const ReactStrap = require('reactstrap'); -const { Button, Input, Label } = ReactStrap; +const { Button, ButtonGroup, Input, Label } = ReactStrap; const UNISYS = require('unisys/client'); var UDATA = null; @@ -32,8 +32,9 @@ class FiltersPanel extends UNISYS.Component { this.UpdateFilterDefs = this.UpdateFilterDefs.bind(this); this.OnClearBtnClick = this.OnClearBtnClick.bind(this); + this.SelectFilterAction = this.SelectFilterAction.bind(this); - /// Initialize UNISYS DATA LINK for REACT + /// Initialize UNISYS DATA LINK for REACT UDATA = UNISYS.NewDataLink(this); // Load Templates @@ -58,10 +59,14 @@ class FiltersPanel extends UNISYS.Component { UDATA.LocalCall('FILTER_CLEAR'); } + SelectFilterAction(filterAction) { + this.setState({ filterAction }); + UDATA.LocalCall('FILTERS_UPDATE', { filterAction }); } render() { - const { tableHeight, filterAction } = this.props; + const { filterAction } = this.state; + const { tableHeight } = this.props; const defs = [this.state.nodes, this.state.edges]; return (
+ + + +
From 3d43e0b121984e8f9b5549a0909a9fc50ecbceda Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:07:17 -0800 Subject: [PATCH 12/33] filters: Update FILTERED_D3DATA when D3DATA is updated. This will trigger the graph redraw. --- .../components/filter/FiltersPanel.jsx | 9 ++++--- build/app/view/netcreate/filter-logic.js | 27 ++++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index 70aeaccf3..9995db8c1 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -41,9 +41,12 @@ class FiltersPanel extends UNISYS.Component { // The intial `OnAppStateChange("FDATA")` event when the template is // first loaded is called well before FiltersPanel is // even constructed. So we need to explicitly load it here. - let FDATA = UDATA.AppState("FDATA"); - this.state = FDATA; - + const FDATA = UDATA.AppState("FDATA"); + this.state = { + nodes: FDATA.nodes, + edges: FDATA.edges, + filterAction: FILTER.ACTION.HIGHLIGHT + }; UDATA.OnAppStateChange("FDATA", this.UpdateFilterDefs); } // constructor diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index bf946985d..482a38ffd 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -113,8 +113,7 @@ MOD.Hook("INITIALIZE", () => { UDATA.OnAppStateChange("FDATA", data => { if (DBG) console.log(PR + 'OnAppStateChange: FDATA', data); // The filter defs have been updated, so apply the filters. - m_FiltersApply(); - m_UpdateFilterSummary(); + m_UpdateFilters(); }); /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -131,6 +130,22 @@ MOD.Hook("INITIALIZE", () => { m_ClearFilters(); }); + /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + /*/ FILTERS_UPDATE is called by FiltersPanel switches between filters and highlights + /*/ + UDATA.HandleMessage("FILTERS_UPDATE", data => { + const FDATA = UDATA.AppState("FDATA"); + FDATA.filterAction = data.filterAction; + UDATA.SetAppState("FDATA", FDATA); + }); + /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + /*/ // Listen for D3DATA updates so we know to trigger change? + /*/ + UDATA.OnAppStateChange('D3DATA',(data)=>{ + m_UpdateFilters(); + }); + + }); // end UNISYS_INIT @@ -234,12 +249,12 @@ function m_ImportPrompts(prompts) { */ function m_FilterDefine(data) { const FDATA = UDATA.AppState("FDATA"); + FDATA.filterAction = data.filterAction; if (data.group === "nodes") { if (data.type === "transparency") { FDATA.nodes.transparency = data.transparency; - } else{ let nodeFilters = FDATA.nodes.filters; @@ -295,6 +310,11 @@ function m_UpdateFilterSummary() { UDATA.LocalCall('FILTER_SUMMARY_UPDATE', { filtersSummary: summary }); } +function m_UpdateFilters() { + m_FiltersApply(); + m_UpdateFilterSummary(); +} + function m_FiltersToString(filters) { let summary = '' filters.forEach(filter => { @@ -310,6 +330,7 @@ function m_FiltersToString(filters) { function m_OperatorToString(operator) { return FILTER.OPERATORS[operator].label; } + /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ UTILITY FUNCTIONS /*/ From b6f67c887d5ce240d9e9130799738472abf00216 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:08:05 -0800 Subject: [PATCH 13/33] filters: Only do graph redraw on FILTERED_D3DATA changes, not on D3DATA. D3DATA is the core data. We always only draw filtered data changes. --- .../view/netcreate/components/d3-simplenetgraph.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/build/app/view/netcreate/components/d3-simplenetgraph.js b/build/app/view/netcreate/components/d3-simplenetgraph.js index 4bf31c878..77bd40922 100644 --- a/build/app/view/netcreate/components/d3-simplenetgraph.js +++ b/build/app/view/netcreate/components/d3-simplenetgraph.js @@ -165,10 +165,20 @@ class D3NetGraph { this._Dragged = this._Dragged.bind(this); this._Dragended = this._Dragended.bind(this); + // V1.4 CHANGE + // Ignore D3DATA Updates!!! Only listen to FILTERED_D3DATA Updates + // // watch for updates to the D3DATA data object - UDATA.OnAppStateChange('D3DATA',(data)=>{ + // UDATA.OnAppStateChange('D3DATA',(data)=>{ + // // expect { nodes, edges } for this namespace + // if (DBG) console.error(PR,'got state D3DATA',data); + // this._SetData(data); + // }); + + // Special handler for the remove filter + UDATA.HandleMessage('FILTERED_D3DATA',(data)=>{ // expect { nodes, edges } for this namespace - if (DBG) console.log(PR,'got state D3DATA',data); + if (DBG) console.log(PR,'got state FILTERED_D3DATA',data); this._SetData(data); }); From 60f924512cb0614c1a1e9aeb35d96c797bd9c2fa Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:09:01 -0800 Subject: [PATCH 14/33] filter: Rewrite `m_FiltersApplyTo*` to handle either highlighting or filtering. --- build/app/view/netcreate/filter-logic.js | 76 ++++++++++++++++-------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index 482a38ffd..4439d8812 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -286,9 +286,16 @@ function m_FilterDefine(data) { * @param {Object} data A UDATA pkt {defs} */ function m_FiltersApply() { + const FILTERED_D3DATA = UDATA.AppState("D3DATA"); const FDATA = UDATA.AppState("FDATA"); - m_FiltersApplyToNodes(FDATA.nodes.filters, FDATA.nodes.transparency); - m_FiltersApplyToEdges(FDATA.edges.filters, FDATA.edges.transparency); + + // skip if FDATA has not been defined yet + if (Object.keys(FDATA).length < 1) return; + + m_FiltersApplyToNodes(FDATA, FILTERED_D3DATA); + m_FiltersApplyToEdges(FDATA, FILTERED_D3DATA); + // Update FILTERED_D3DATA + UDATA.Call("FILTERED_D3DATA", FILTERED_D3DATA); } function m_ClearFilters() { @@ -300,10 +307,14 @@ function m_ClearFilters() { function m_UpdateFilterSummary() { const FDATA = UDATA.AppState("FDATA"); + // skip if FDATA has not been defined yet + if (Object.keys(FDATA).length < 1) return; + const nodeFilters = FDATA.nodes.filters; const edgeFilters = FDATA.edges.filters; - let summary = ''; + let summary = FDATA.filterAction === FILTER.ACTION.HIGHLIGHT + ? 'HIGHLIGHTING ' : 'FILTERING '; summary += m_FiltersToString(FDATA.nodes.filters); summary += m_FiltersToString(FDATA.edges.filters); @@ -389,19 +400,19 @@ function m_MatchNumber(operator, filterVal, objVal) { /** * Side effect: - * D3DATA.nodes are updated with `isFilteredOut` flags. + * FILTERED_D3DATA.nodes are updated with `isFilteredOut` flags. * * @param {Array} filters */ -function m_FiltersApplyToNodes(filters, transparency) { - const D3DATA = UDATA.AppState("D3DATA"); - D3DATA.nodes.forEach(node => { - m_FiltersApplyToNode(node, filters, transparency); +function m_FiltersApplyToNodes(FDATA, FILTERED_D3DATA) { + const { filterAction } = FDATA; + const { filters, transparency } = FDATA.nodes; + FILTERED_D3DATA.nodes = FILTERED_D3DATA.nodes.filter(node => { + return m_FiltersApplyToNode(node, filters, transparency, filterAction); }); - UDATA.SetAppState("D3DATA", D3DATA); } -function m_FiltersApplyToNode(node, filters, transparency) { +function m_FiltersApplyToNode(node, filters, transparency, filterAction) { let all_no_op = true; let matched = true; // implicit AND. ALL filters must return true. @@ -424,7 +435,14 @@ function m_FiltersApplyToNode(node, filters, transparency) { } } + // FILTER.ACTION.FILTER + if (filterAction === FILTER.ACTION.FILTER) { + if (matched) return true; + return false; } + + // FILTER.ACTION.HIGHLIGHT, so don't filter + return true; } function m_IsNodeMatchedByFilter(node, filter) { @@ -455,7 +473,6 @@ function m_IsNodeMatchedByFilter(node, filter) { break; default: // Else assume it's a number - console.log('NUMBER', filter, node); return m_MatchNumber(filter.operator, filter.value, nodeValue) break; } @@ -466,25 +483,29 @@ function m_IsNodeMatchedByFilter(node, filter) { /*/ EDGE FILTERS /*/ -function m_FiltersApplyToEdges(filters, transparency) { - const D3DATA = UDATA.AppState("D3DATA"); - D3DATA.edges.forEach(edge => { - m_FiltersApplyToEdge(edge, filters, transparency); +function m_FiltersApplyToEdges(FDATA, FILTERED_D3DATA) { + const { filterAction } = FDATA; + const { filters, transparency } = FDATA.edges; + FILTERED_D3DATA.edges = FILTERED_D3DATA.edges.filter(edge => { + return m_FiltersApplyToEdge(edge, filters, transparency, filterAction); }); - UDATA.SetAppState("D3DATA", D3DATA); } -function m_FiltersApplyToEdge(edge, filters, transparency) { - // regardless of filter definition, - // always hide edge if it's attached to a filtered node - if (edge.source.isFilteredOut || edge.target.isFilteredOut) { - edge.isFilteredOut = true; // no filters, revert +function m_FiltersApplyToEdge(edge, filters, transparency, filterAction) { + let all_no_op = true; + let matched = true; + if (edge.source.filteredTransparency < 1.0 || edge.target.filteredTransparency < 1.0) { + // regardless of filter definition, + // always hide edge if it's attached to a filtered node + // FILTER.ACTION.FILTER + if (filterAction === FILTER.ACTION.FILTER) return false; + // else + // FILTER.ACTION.HIGHLIGHT, so don't filter, just fade edge.filteredTransparency = transparency; // set the transparency value ... right now it is inefficient to set this at the node / edge level, but that's more flexible - return; + return true; } - let all_no_op = true; - let matched = true; + // otherwise, look for matches // implicit AND. ALL filters must return true. filters.forEach(filter => { if (filter.operator === FILTER.OPERATORS.NO_OP.key) return; // skip no_op @@ -506,7 +527,14 @@ function m_FiltersApplyToEdge(edge, filters, transparency) { } + // FILTER.ACTION.FILTER + if (filterAction === FILTER.ACTION.FILTER) { + if (matched) return true; + return false; } + + // FILTER.ACTION.HIGHLIGHT, so don't filter + return true; } function m_IsEdgeMatchedByFilter(edge, filter) { From 45fc055908bdd3c6c2972320f1ad818ae875e104 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:16:42 -0800 Subject: [PATCH 15/33] filter: Clarify filter behavior. --- .../netcreate/components/filter/FiltersPanel.jsx | 2 +- build/app/view/netcreate/filter-logic.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/build/app/view/netcreate/components/filter/FiltersPanel.jsx b/build/app/view/netcreate/components/filter/FiltersPanel.jsx index 9995db8c1..153f49d1a 100644 --- a/build/app/view/netcreate/components/filter/FiltersPanel.jsx +++ b/build/app/view/netcreate/components/filter/FiltersPanel.jsx @@ -95,7 +95,7 @@ class FiltersPanel extends UNISYS.Component {
diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index 4439d8812..009bacde9 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -40,6 +40,19 @@ FEATURES + * "Highlight" vs "Filter" + -- Version 1.4 introduces two different types of filtering: + "Highlight" highlights the matching nodes/edges and fades the others + "Filter" shows matching nodes/edges and removes the non-matching + nodes/edges from the display without affecting the underlying data. + + * With Version 1.4, the only data that is graphed is FILTERED_D3DATA. + -- d3-simplenetgraph no longer plots on D3DATA changes. + -- Instead, FILTERED_D3DATA changes are pushed via an AppCall. + -- This way there is only one source of truth: all draw updates + are routed through filter-logic. + -- If filters have not been defined, we just pass the raw D3DATA + * Filters can be stacked. You can define two "Label" filters, for example. The only reason you can't do it right now is because the filter template From 4b0cf181f92b89928d2869c570e748ed6c0f6430 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 15:30:21 -0800 Subject: [PATCH 16/33] filter: Fix InfoPanel tab indices. --- build/app/view/netcreate/components/InfoPanel.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/app/view/netcreate/components/InfoPanel.jsx b/build/app/view/netcreate/components/InfoPanel.jsx index adef1c2f5..d2105df9e 100644 --- a/build/app/view/netcreate/components/InfoPanel.jsx +++ b/build/app/view/netcreate/components/InfoPanel.jsx @@ -187,7 +187,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('4'); this.sendGA('Nodes Table', window.location); }} + onClick={() => { this.toggle('3'); this.sendGA('Nodes Table', window.location); }} > Nodes Table @@ -195,7 +195,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('5'); this.sendGA('Edges Table', window.location); }} + onClick={() => { this.toggle('4'); this.sendGA('Edges Table', window.location); }} > Edges Table @@ -203,7 +203,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('6'); this.sendGA('Vocabulary', window.location); }} + onClick={() => { this.toggle('5'); this.sendGA('Vocabulary', window.location); }} > Vocabulary @@ -211,7 +211,7 @@ class InfoPanel extends UNISYS.Component { { this.toggle('7'); this.sendGA('Help', window.location); }} + onClick={() => { this.toggle('6'); this.sendGA('Help', window.location); }} > Help From a87673eec2d1c06d3db9ed06fd6dbcdf3c5a699f Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 16:39:43 -0800 Subject: [PATCH 17/33] filter: Disable select filter value if NO_OP. --- .../view/netcreate/components/filter/SelectFilter.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/build/app/view/netcreate/components/filter/SelectFilter.js b/build/app/view/netcreate/components/filter/SelectFilter.js index 8a9f28e39..2fdf65560 100644 --- a/build/app/view/netcreate/components/filter/SelectFilter.js +++ b/build/app/view/netcreate/components/filter/SelectFilter.js @@ -136,10 +136,14 @@ class SelectFilter extends React.Component { - {options.map(op => - - )} + onChange={this.OnChangeValue} bsSize="sm" + disabled={operator === FILTER.OPERATORS.NO_OP.key}> + {operator !== FILTER.OPERATORS.NO_OP.key + ? options.map(op => + + ) + : '' + } From 5285d60739b2d2c20ec29ff862e5463afebdc2f0 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Thu, 11 Nov 2021 16:46:18 -0800 Subject: [PATCH 18/33] filter: Specify summary type. Remove summary field if no filters are set. --- build/app/view/netcreate/filter-logic.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index 009bacde9..e22d97cf3 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -40,6 +40,8 @@ FEATURES + * See Whimiscal [diagram](https://whimsical.com/d3-data-flow-B2tTGnQYPSNviUhsPL64Dz) + * "Highlight" vs "Filter" -- Version 1.4 introduces two different types of filtering: "Highlight" highlights the matching nodes/edges and fades the others @@ -326,10 +328,12 @@ function m_UpdateFilterSummary() { const nodeFilters = FDATA.nodes.filters; const edgeFilters = FDATA.edges.filters; - let summary = FDATA.filterAction === FILTER.ACTION.HIGHLIGHT + const typeSummary = FDATA.filterAction === FILTER.ACTION.HIGHLIGHT ? 'HIGHLIGHTING ' : 'FILTERING '; - summary += m_FiltersToString(FDATA.nodes.filters); - summary += m_FiltersToString(FDATA.edges.filters); + const nodeSummary = m_FiltersToString(FDATA.nodes.filters); + const edgeSummary = m_FiltersToString(FDATA.edges.filters); + let summary = ''; + if (nodeSummary || edgeSummary) summary = `${typeSummary} NODES: ${nodeSummary} EDGES: ${edgeSummary}`; UDATA.LocalCall('FILTER_SUMMARY_UPDATE', { filtersSummary: summary }); } From 59d36b339341c149418c41acf3aa30cf081fb2f6 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Mon, 15 Nov 2021 10:04:56 -0800 Subject: [PATCH 19/33] filter: Lint/clean up formatting. --- .../app/view/netcreate/components/NodeTable.jsx | 16 ++++++++-------- build/app/view/netcreate/filter-logic.js | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index be95f1c23..9a3fa7fad 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -172,8 +172,9 @@ countEdges(edges) { } } - /// --- - sortByUpdated(nodes) +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*/ +/*/ sortByUpdated(nodes) { if (nodes) { return nodes.sort( (a,b) => { @@ -371,13 +372,12 @@ render() { this.handleDataUpdate(D3DATA); } - componentWillUnmount() { - this.AppStateChangeOff('D3DATA', this.handleDataUpdate); - this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); - } + componentWillUnmount() { + this.AppStateChangeOff('D3DATA', this.handleDataUpdate); + this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); + } -displayUpdated(nodeEdge) - { + displayUpdated(nodeEdge) { var d = new Date(nodeEdge.meta.revision > 0 ? nodeEdge.meta.updated : nodeEdge.meta.created); var year = "" + d.getFullYear(); diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index e22d97cf3..6ab6a8a71 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -42,7 +42,7 @@ * See Whimiscal [diagram](https://whimsical.com/d3-data-flow-B2tTGnQYPSNviUhsPL64Dz) - * "Highlight" vs "Filter" + * filterAction: "Highlight" vs "Filter" -- Version 1.4 introduces two different types of filtering: "Highlight" highlights the matching nodes/edges and fades the others "Filter" shows matching nodes/edges and removes the non-matching From 26454d6166ea0b1f101fed4ea10b190dba770109 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:27:53 -0800 Subject: [PATCH 20/33] filter: Change FILTERED_D3DATA message to FILTEREDD3DATA app state. This is necessary for table updates to display current filtered data. --- .../netcreate/components/d3-simplenetgraph.js | 6 ++--- build/app/view/netcreate/filter-logic.js | 25 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/build/app/view/netcreate/components/d3-simplenetgraph.js b/build/app/view/netcreate/components/d3-simplenetgraph.js index 77bd40922..3e4be50b3 100644 --- a/build/app/view/netcreate/components/d3-simplenetgraph.js +++ b/build/app/view/netcreate/components/d3-simplenetgraph.js @@ -166,7 +166,7 @@ class D3NetGraph { this._Dragended = this._Dragended.bind(this); // V1.4 CHANGE - // Ignore D3DATA Updates!!! Only listen to FILTERED_D3DATA Updates + // Ignore D3DATA Updates!!! Only listen to FILTEREDD3DATA Updates // // watch for updates to the D3DATA data object // UDATA.OnAppStateChange('D3DATA',(data)=>{ @@ -176,9 +176,9 @@ class D3NetGraph { // }); // Special handler for the remove filter - UDATA.HandleMessage('FILTERED_D3DATA',(data)=>{ + UDATA.OnAppStateChange('FILTEREDD3DATA',(data)=>{ // expect { nodes, edges } for this namespace - if (DBG) console.log(PR,'got state FILTERED_D3DATA',data); + if (DBG) console.log(PR,'got state FILTEREDD3DATA',data); this._SetData(data); }); diff --git a/build/app/view/netcreate/filter-logic.js b/build/app/view/netcreate/filter-logic.js index 6ab6a8a71..636d30c80 100644 --- a/build/app/view/netcreate/filter-logic.js +++ b/build/app/view/netcreate/filter-logic.js @@ -301,16 +301,17 @@ function m_FilterDefine(data) { * @param {Object} data A UDATA pkt {defs} */ function m_FiltersApply() { - const FILTERED_D3DATA = UDATA.AppState("D3DATA"); + const FILTEREDD3DATA = UDATA.AppState("D3DATA"); const FDATA = UDATA.AppState("FDATA"); // skip if FDATA has not been defined yet if (Object.keys(FDATA).length < 1) return; - m_FiltersApplyToNodes(FDATA, FILTERED_D3DATA); - m_FiltersApplyToEdges(FDATA, FILTERED_D3DATA); - // Update FILTERED_D3DATA - UDATA.Call("FILTERED_D3DATA", FILTERED_D3DATA); + m_FiltersApplyToNodes(FDATA, FILTEREDD3DATA); + m_FiltersApplyToEdges(FDATA, FILTEREDD3DATA); + // Update FILTEREDD3DATA + UDATA.SetAppState("FILTEREDD3DATA", FILTEREDD3DATA); + } function m_ClearFilters() { @@ -417,15 +418,15 @@ function m_MatchNumber(operator, filterVal, objVal) { /** * Side effect: - * FILTERED_D3DATA.nodes are updated with `isFilteredOut` flags. + * FILTEREDD3DATA.nodes are updated with `isFilteredOut` flags. * * @param {Array} filters */ -function m_FiltersApplyToNodes(FDATA, FILTERED_D3DATA) { +function m_FiltersApplyToNodes(FDATA, FILTEREDD3DATA) { const { filterAction } = FDATA; const { filters, transparency } = FDATA.nodes; - FILTERED_D3DATA.nodes = FILTERED_D3DATA.nodes.filter(node => { - return m_FiltersApplyToNode(node, filters, transparency, filterAction); + FILTEREDD3DATA.nodes = FILTEREDD3DATA.nodes.filter(node => { + return m_NodeIsFiltered(node, filters, transparency, filterAction); }); } @@ -500,11 +501,11 @@ function m_IsNodeMatchedByFilter(node, filter) { /*/ EDGE FILTERS /*/ -function m_FiltersApplyToEdges(FDATA, FILTERED_D3DATA) { +function m_FiltersApplyToEdges(FDATA, FILTEREDD3DATA) { const { filterAction } = FDATA; const { filters, transparency } = FDATA.edges; - FILTERED_D3DATA.edges = FILTERED_D3DATA.edges.filter(edge => { - return m_FiltersApplyToEdge(edge, filters, transparency, filterAction); + FILTEREDD3DATA.edges = FILTEREDD3DATA.edges.filter(edge => { + return m_EdgeIsFiltered(edge, filters, transparency, filterAction, FILTEREDD3DATA); }); } From 2dde6a21c97127aa5883854226cd0b2c86a43155 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:29:22 -0800 Subject: [PATCH 21/33] filter: Lint --- .../view/netcreate/components/NodeTable.jsx | 140 ++++++++++-------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index 9a3fa7fad..02ea15fa3 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -43,42 +43,88 @@ var UDATA = null; /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// export a class object for consumption by brunch/require class NodeTable extends UNISYS.Component { - constructor (props) { - super(props); + constructor(props) { + super(props); - this.state = { - nodePrompts: this.AppState('TEMPLATE').nodePrompts, - nodes: [], - edgeCounts: {}, // {nodeID:count,...} - isExpanded: true, - sortkey: 'label' - }; + this.state = { + nodePrompts: this.AppState('TEMPLATE').nodePrompts, + nodes: [], + // edgeCounts: {}, // {nodeID:count,...} + filteredNodes: [], + isExpanded: true, + sortkey: 'label' + }; - this.handleDataUpdate = this.handleDataUpdate.bind(this); - this.OnTemplateUpdate = this.OnTemplateUpdate.bind(this); - this.onButtonClick = this.onButtonClick.bind(this); - this.onToggleExpanded = this.onToggleExpanded.bind(this); - this.setSortKey = this.setSortKey.bind(this); - this.sortSymbol = this.sortSymbol.bind(this); + this.handleDataUpdate = this.handleDataUpdate.bind(this); + this.handleFilterDataUpdate = this.handleFilterDataUpdate.bind(this); + this.OnTemplateUpdate = this.OnTemplateUpdate.bind(this); + this.onButtonClick = this.onButtonClick.bind(this); + this.onToggleExpanded = this.onToggleExpanded.bind(this); + this.setSortKey = this.setSortKey.bind(this); + this.sortSymbol = this.sortSymbol.bind(this); - this.sortDirection = -1; + this.sortDirection = -1; - /// Initialize UNISYS DATA LINK for REACT - UDATA = UNISYS.NewDataLink(this); + /// Initialize UNISYS DATA LINK for REACT + UDATA = UNISYS.NewDataLink(this); - // Always make sure class methods are bind()'d before using them - // as a handler, otherwise object context is lost - this.OnAppStateChange('D3DATA', this.handleDataUpdate); + // Always make sure class methods are bind()'d before using them + // as a handler, otherwise object context is lost + this.OnAppStateChange('D3DATA', this.handleDataUpdate); - // Handle Template updates - this.OnAppStateChange('TEMPLATE', this.OnTemplateUpdate); - } // constructor + // Handle Template updates + this.OnAppStateChange('TEMPLATE', this.OnTemplateUpdate); + + // Track Filtered Data Updates too + // UDATA.HandleMessage('FILTEREDD3DATA', (data) => { + this.OnAppStateChange('FILTEREDD3DATA', this.handleFilterDataUpdate); + + } // constructor + +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*/ +/*/ componentDidMount () { + if (DBG) console.error('NodeTable.componentDidMount!'); + // Explicitly retrieve data because we may not have gotten a D3DATA + // update while we were hidden. + + // filtered data needs to be set before D3Data + const FILTEREDD3DATA = UDATA.AppState('FILTEREDD3DATA'); + this.setState({ filteredNodes: FILTEREDD3DATA.nodes }, + () => { + let D3DATA = this.AppState('D3DATA'); + this.handleDataUpdate(D3DATA); + } + ) + } + + componentWillUnmount() { + this.AppStateChangeOff('D3DATA', this.handleDataUpdate); + this.AppStateChangeOff('FILTEREDD3DATA', this.handleFilterDataUpdate); + this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); + } + + displayUpdated(nodeEdge) { + var d = new Date(nodeEdge.meta.revision > 0 ? nodeEdge.meta.updated : nodeEdge.meta.created); + + var year = "" + d.getFullYear(); + var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+ year.substr(2,4); + var time = d.toTimeString().substr(0,5); + var dateTime = date+' at '+time; + var titleString = "v" + nodeEdge.meta.revision; + if(nodeEdge._nlog) + titleString += " by " + nodeEdge._nlog[nodeEdge._nlog.length-1]; + var tag = {dateTime} ; + + return tag; + + } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ Handle updated SELECTION /*/ handleDataUpdate(data) { - if(DBG) + if (DBG) console.log('handle data update') // 2020-09-09 Removing this check and relying on other NodeTable optimizations. BL @@ -100,11 +146,13 @@ class NodeTable extends UNISYS.Component { }); } } -/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OnTemplateUpdate(data) { - this.setState({nodePrompts: data.nodePrompts}); -} -/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + OnTemplateUpdate(data) { + this.setState({nodePrompts: data.nodePrompts}); + } + + /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*/ Build table of counts /*/ // JD removed because "size" seemed to work just fine? (I added a degrees that is size - 1) @@ -288,8 +336,6 @@ countEdges(edges) { /*/ /*/ render() { - if(DBG) - console.log('nodetablerender!') if (this.state.nodes === undefined) return ""; let { nodePrompts } = this.state; let { tableHeight } = this.props; @@ -362,36 +408,6 @@ render() { ); } -/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/*/ -/*/ componentDidMount () { - if (DBG) console.error('NodeTable.componentDidMount!'); - // Explicitly retrieve data because we may not have gotten a D3DATA - // update while we were hidden. - let D3DATA = this.AppState('D3DATA'); - this.handleDataUpdate(D3DATA); - } - - componentWillUnmount() { - this.AppStateChangeOff('D3DATA', this.handleDataUpdate); - this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); - } - - displayUpdated(nodeEdge) { - var d = new Date(nodeEdge.meta.revision > 0 ? nodeEdge.meta.updated : nodeEdge.meta.created); - - var year = "" + d.getFullYear(); - var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+ year.substr(2,4); - var time = d.toTimeString().substr(0,5); - var dateTime = date+' at '+time; - var titleString = "v" + nodeEdge.meta.revision; - if(nodeEdge._nlog) - titleString += " by " + nodeEdge._nlog[nodeEdge._nlog.length-1]; - var tag = {dateTime} ; - - return tag; - - } } // class NodeTable From 8b64258c77f505d9a3461f1f7d1d0b4469f508c7 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:31:58 -0800 Subject: [PATCH 22/33] filter: Improve NodeTable and EdgeTable layout. Tighten up spacing, decrease font size, adjust column size. --- .../view/netcreate/components/EdgeTable.jsx | 16 ++++++------ .../view/netcreate/components/NodeTable.jsx | 25 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/build/app/view/netcreate/components/EdgeTable.jsx b/build/app/view/netcreate/components/EdgeTable.jsx index 96889d3a6..07c6478b6 100644 --- a/build/app/view/netcreate/components/EdgeTable.jsx +++ b/build/app/view/netcreate/components/EdgeTable.jsx @@ -335,11 +335,11 @@ class EdgeTable extends UNISYS.Component { let { tableHeight } = this.props; - let styles = ` - thead, tbody { } + let styles = `thead, tbody { font-size: 0.8em } thead { position: relative; } tbody { overflow: auto; } -` + .btn-sm { font-size: 0.6rem; padding: 0.1rem 0.2rem } + ` return (
- Size -
_Edit_
+
_Edit_
Src ID - - - diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index 02ea15fa3..e7b761fda 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -339,45 +339,46 @@ render() { if (this.state.nodes === undefined) return ""; let { nodePrompts } = this.state; let { tableHeight } = this.props; - let styles = `thead, tbody { } + let styles = `thead, tbody { font-size: 0.8em } thead { position: relative; } tbody { overflow: auto; } + .btn-sm { font-size: 0.6rem; padding: 0.1rem 0.2rem } ` return ( -
+
- - + - - - - From 1d30df4d03ae41e54acddc51a6f009f4713b3b02 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:40:35 -0800 Subject: [PATCH 23/33] filter: Remove edgeCount code, replaced by `degrees`, which is calculated via radius, which in turn is already based on edge count. --- build/app/view/netcreate/components/NodeTable.jsx | 12 ------------ .../view/netcreate/components/d3-simplenetgraph.js | 2 ++ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index e7b761fda..db28dbd66 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -153,18 +153,6 @@ class NodeTable extends UNISYS.Component { } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/*/ Build table of counts -/*/ -// JD removed because "size" seemed to work just fine? (I added a degrees that is size - 1) -countEdges(edges) { - let edgeCounts = {}; // this.state.edgeCounts; - edges.forEach(edge => { - edgeCounts[edge.source.id] = edgeCounts[edge.source.id] !== undefined ? edgeCounts[edge.source.id] + 1 : 1; - edgeCounts[edge.target.id] = edgeCounts[edge.target.id] !== undefined ? edgeCounts[edge.target.id] + 1 : 1; - }); - return edgeCounts; -} - /// UTILITIES ///////////////////////////////////////////////////////////////// /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/app/view/netcreate/components/d3-simplenetgraph.js b/build/app/view/netcreate/components/d3-simplenetgraph.js index 3e4be50b3..ac43a0703 100644 --- a/build/app/view/netcreate/components/d3-simplenetgraph.js +++ b/build/app/view/netcreate/components/d3-simplenetgraph.js @@ -425,6 +425,8 @@ class D3NetGraph { d.weight = radius d.size = radius // save the calculated size + // radius is calculated by counting the number of edges attached + // (+ 1 for a minimum radius), so we hack degrees by using radius-1 d.degrees = radius - 1 return this.defaultSize + (this.defaultSize * d.weight / 2) }) From a246604d9c1ae85784c7135f50d61d7f0ece45e6 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:41:39 -0800 Subject: [PATCH 24/33] filter: Lint/doc. --- .../view/netcreate/components/EdgeTable.jsx | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/build/app/view/netcreate/components/EdgeTable.jsx b/build/app/view/netcreate/components/EdgeTable.jsx index 07c6478b6..cdc62518d 100644 --- a/build/app/view/netcreate/components/EdgeTable.jsx +++ b/build/app/view/netcreate/components/EdgeTable.jsx @@ -4,6 +4,9 @@ EdgeTable is used to to display a table of edges for review. + It displays D3DATA. + But also read FILTEREDD3DATA to show highlight/filtered state + ## TO USE @@ -78,6 +81,42 @@ class EdgeTable extends UNISYS.Component { // Handle Template updates this.OnAppStateChange('TEMPLATE', this.OnTemplateUpdate); } // constructor +/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*/ +/*/ componentDidMount () { + if (DBG) console.log('EdgeTable.componentDidMount!'); + // Explicitly retrieve data because we may not have gotten a D3DATA + // update while we were hidden. + // filtered data needs to be set before D3Data + const FILTEREDD3DATA = UDATA.AppState('FILTEREDD3DATA'); + this.setState({ filteredEdges: FILTEREDD3DATA.edges }, + () => { + let D3DATA = this.AppState('D3DATA'); + this.handleDataUpdate(D3DATA); + } + ) +} + + componentWillUnmount() { + this.AppStateChangeOff('D3DATA', this.handleDataUpdate); + this.AppStateChangeOff('FILTEREDD3DATA', this.handleFilterDataUpdate); + this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); + } + + displayUpdated(nodeEdge) { + var d = new Date(nodeEdge.meta.revision > 0 ? nodeEdge.meta.updated : nodeEdge.meta.created); + + var year = "" + d.getFullYear(); + var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+ year.substr(2,4); + var time = d.toTimeString().substr(0,5); + var dateTime = date+' at '+time; + var titleString = "v" + nodeEdge.meta.revision; + if(nodeEdge._nlog) + titleString += " by " + nodeEdge._nlog[nodeEdge._nlog.length-1]; + var tag = {dateTime} ; + + return tag; + } @@ -419,36 +458,6 @@ class EdgeTable extends UNISYS.Component { ); } -/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/*/ -/*/ componentDidMount () { - if (DBG) console.log('EdgeTable.componentDidMount!'); - // Explicitly retrieve data because we may not have gotten a D3DATA - // update while we were hidden. - let D3DATA = this.AppState('D3DATA'); - this.handleDataUpdate(D3DATA); - } - - componentWillUnmount() { - this.AppStateChangeOff('D3DATA', this.handleDataUpdate); - this.AppStateChangeOff('TEMPLATE', this.OnTemplateUpdate); - } - - displayUpdated(nodeEdge) - { - var d = new Date(nodeEdge.meta.revision > 0 ? nodeEdge.meta.updated : nodeEdge.meta.created); - - var year = "" + d.getFullYear(); - var date = (d.getMonth()+1)+"/"+d.getDate()+"/"+ year.substr(2,4); - var time = d.toTimeString().substr(0,5); - var dateTime = date+' at '+time; - var titleString = "v" + nodeEdge.meta.revision; - if(nodeEdge._nlog) - titleString += " by " + nodeEdge._nlog[nodeEdge._nlog.length-1]; - var tag = {dateTime} ; - - return tag; - } } // class EdgeTable From 32f51964c28f5d38cf6aa5272c9cf5937b7919c1 Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:44:35 -0800 Subject: [PATCH 25/33] filter: Remove stray edgeCount refernces. --- build/app/view/netcreate/components/NodeTable.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index db28dbd66..c27fabc3a 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -49,7 +49,6 @@ class NodeTable extends UNISYS.Component { this.state = { nodePrompts: this.AppState('TEMPLATE').nodePrompts, nodes: [], - // edgeCounts: {}, // {nodeID:count,...} filteredNodes: [], isExpanded: true, sortkey: 'label' @@ -138,7 +137,6 @@ class NodeTable extends UNISYS.Component { // {} if (data.nodes) { - // const edgeCounts = this.countEdges(data.edges); const nodes = this.sortTable(this.state.sortkey, data.nodes); this.setState({ nodes: nodes, @@ -172,7 +170,6 @@ class NodeTable extends UNISYS.Component { /*/ /*/ sortByEdgeCount(nodes) { if (nodes) { - // let edgeCounts = this.state.edgeCounts; return nodes.sort( (a, b) => { let akey = a.degrees || 0, bkey = b.degrees || 0; From 897f5536479a6b5b6876b0620334f56715bbf07e Mon Sep 17 00:00:00 2001 From: Ben Loh Date: Tue, 16 Nov 2021 09:55:15 -0800 Subject: [PATCH 26/33] filter: Show highlighted/filtered state in NodeTable. --- .../view/netcreate/components/NodeTable.jsx | 34 ++++++++++----- build/app/view/netcreate/filter-logic.js | 42 +++++++++++-------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/build/app/view/netcreate/components/NodeTable.jsx b/build/app/view/netcreate/components/NodeTable.jsx index c27fabc3a..6df2edb4b 100644 --- a/build/app/view/netcreate/components/NodeTable.jsx +++ b/build/app/view/netcreate/components/NodeTable.jsx @@ -4,6 +4,8 @@ NodeTable is used to to display a table of nodes for review. + It displays D3DATA. + But also checks FILTEREDD3DATA to show highlight/filtered state ## TO USE @@ -123,8 +125,7 @@ class NodeTable extends UNISYS.Component { /*/ Handle updated SELECTION /*/ handleDataUpdate(data) { - if (DBG) - console.log('handle data update') + if (DBG) console.log('handle data update') // 2020-09-09 Removing this check and relying on other NodeTable optimizations. BL // if (data.bMarkedNode) @@ -137,20 +138,29 @@ class NodeTable extends UNISYS.Component { // {} if (data.nodes) { - const nodes = this.sortTable(this.state.sortkey, data.nodes); - this.setState({ - nodes: nodes, - // edgeCounts: edgeCounts - }); + let nodes = this.sortTable(this.state.sortkey, data.nodes); + const { filteredNodes } = this.state; + // add highlight/filter status + if (filteredNodes.length > 0) { + nodes = nodes.map(node => { + const filteredNode = filteredNodes.find(n => n.id === node.id); + if (!filteredNode) node.isFiltered = true; // not in filteredNode, so it's been removed + return node + }); + } + this.setState({ nodes }); } } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OnTemplateUpdate(data) { - this.setState({nodePrompts: data.nodePrompts}); + handleFilterDataUpdate(data) { + if (data.nodes) this.setState( { filteredNodes: data.nodes } ); } /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + OnTemplateUpdate(data) { + this.setState({nodePrompts: data.nodePrompts}); + } /// UTILITIES ///////////////////////////////////////////////////////////////// /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -370,7 +380,11 @@ render() { {this.state.nodes.map( (node,i) => ( - + {this.state.edges.map( (edge,i) => ( - +