Skip to content

Commit 5d1eed9

Browse files
committed
config-ip-filter: Documentation and linting.
1 parent 8ed38a4 commit 5d1eed9

File tree

9 files changed

+348
-431
lines changed

9 files changed

+348
-431
lines changed

build/app/assets/templates/_default.template

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
{
22

3-
"_comments": [ "/// NetCreate Template File ///",
4-
"/// IMPORTANT: As of 8/7/2020, the following funcationality is available: ///",
3+
"_comments": [ "/// NetCreate Template File ///",
4+
"/// RELEASE NOTES: As of 8/13/2020, a 'type' specification needs to added to each ///",
5+
"/// nodePrompt and edgePrompt for filters to work. Valid types are: ///",
6+
"/// "string", "number", "select", and "node". The "node" type is only valid for ///",
7+
"/// "source" and "target" objects for edges. ///",
8+
"/// RELEASE NOTES: As of 8/7/2020, the following functionality is available: ///",
59
"/// * `requireLogin: true` will require users to login to view graphs. If the ///",
610
"/// parameter is `false` or missing, graphs are public, and login is not required ///",
7-
"/// IMPORTANT: As of 1/31/2019, the following functionality is available: ///",
11+
"/// RELEASE NOTES: As of 1/31/2019, the following functionality is available: ///",
812
"/// * `label` parameter for each field may be customized ///",
913
"/// * `hidden` parameter may be used to hide fields ///",
1014
"/// * changing the order of the `options` WILL change their order on selections ///",

build/app/view/netcreate/components/filter/FilterEnums.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const FILTER = {};
22

3+
// Types of filters definable in template files.
34
FILTER.TYPES = {};
45
FILTER.TYPES.STRING = 'string';
56
FILTER.TYPES.NUMBER = 'number';
@@ -14,10 +15,6 @@ FILTER.KEY = {};
1415
FILTER.KEY.SOURCE = "source";
1516
FILTER.KEY.TARGET = "target";
1617

17-
FILTER.ACTIONS = {};
18-
FILTER.ACTIONS.CLEAR = "clear";
19-
FILTER.ACTIONS.FILTER_NODES = "filter-nodes";
20-
FILTER.ACTIONS.FILTER_EDGES = "filter-edges";
2118

2219
FILTER.OPERATORS = {};
2320
FILTER.OPERATORS.NO_OP = "no-op";
@@ -38,25 +35,28 @@ FILTER.OPERATORS.NUMBER.LT_EQ = "lt-eq";
3835
FILTER.OPERATORS.NUMBER.EQ = "eq";
3936
FILTER.OPERATORS.NUMBER.NOT_EQ = "not-eq";
4037

41-
/*/
38+
39+
/*/ UDATA MESSAGES ////////////////////////////////////////////////////////////
4240
4341
Filter UDATA Messages
4442
45-
All Filters operations
4643
47-
FILTERDEFS Set the FILTERDEFS data object
48-
FILTERDATA? FILTER_DATA?
49-
FDATA? FLTRDATA
44+
Affects ALL Filters
45+
===================
5046
51-
FILTER_RESET Resets filter form to blank state
47+
FDATA Sets the FDATA data object
48+
Triggers AppStateChange
5249
53-
Individual Filter Operations
50+
FILTER_CLEAR Unhides all objects on the graph
51+
Resets filter form to blank state
5452
55-
FILTER_DEFINE Define a new individual filter
5653
54+
Affects Individual Filters
55+
==========================
5756
58-
/*/
57+
FILTER_DEFINE Define a single new filter
5958
6059
60+
/*/
6161

6262
module.exports = FILTER;

build/app/view/netcreate/components/filter/FilterGroup.jsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,23 @@ export default function FilterGroup({
1212
return (
1313
<div className="filter-group" style={{margin:'5px 5px 5px 0',padding:'10px',backgroundColor:'rgba(0,0,0,0)'}}>
1414
<div className="small text-muted" style={{fontWeight:'bold',textTransform:'uppercase',marginBottom:'0.4em'}}>{label}</div>
15-
{filters.map(filterData => {
16-
switch (filterData.type) {
15+
{filters.map(filter => {
16+
switch (filter.type) {
1717
case FILTER.TYPES.STRING:
1818
case FILTER.TYPES.NODE:
19-
return <StringFilter key={filterData.id} group={group} filter={filterData} />
19+
return <StringFilter key={filter.id} group={group} filter={filter} />
2020
break;
2121
case FILTER.TYPES.NUMBER:
22-
return <NumberFilter key={filterData.id} group={group} filter={filterData} />
22+
return <NumberFilter key={filter.id} group={group} filter={filter} />
2323
break;
2424
case FILTER.TYPES.SELECT:
25-
return <SelectFilter key={filterData.id} group={group} filter={filterData} />
25+
return <SelectFilter key={filter.id} group={group} filter={filter} />
2626
break;
2727
default:
28-
console.error(`FilterGroup: Filter Type not found ${filterData.type}`)
28+
console.error(`FilterGroup: Filter Type not found ${filter.type} for filter`, filter);
2929
break;
3030
}
31+
return '';
3132
})}
3233
</div>
3334
);

build/app/view/netcreate/components/filter/FiltersPanel.jsx

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*//////////////////////////////// ABOUT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*\
2+
3+
FILTERSPANEL
4+
5+
This is the base UI component that displays filters in the InfoPanel.
6+
7+
FiltersPanel
8+
|-- FiltersGroup
9+
|-- StringFilter
10+
|-- NumberFilter
11+
|-- SelectFilter
12+
13+
FiltersPanel reads data directly from FDATA.
14+
15+
\*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ * //////////////////////////////////////*/
16+
117
import FILTER from './FilterEnums';
218
import FilterGroup from './FilterGroup';
319
import React from 'react';
@@ -9,13 +25,7 @@ const { Button, Input, Label } = ReactStrap;
925
const UNISYS = require('unisys/client');
1026
var UDATA = null;
1127

12-
13-
// Storybook has problems with loading unisys without relative ref
14-
// but even with relative ref, it can't load submodules
15-
// const UNISYS = require('../../../../unisys/client');
16-
// class FiltersPanel extends React.Component {
17-
18-
28+
/// CLASS /////////////////////////////////////////////////////////////////////
1929
class FiltersPanel extends UNISYS.Component {
2030
constructor({ filterGroups, onFiltersChange, tableHeight }) {
2131
super();
@@ -26,22 +36,18 @@ class FiltersPanel extends UNISYS.Component {
2636
/// Initialize UNISYS DATA LINK for REACT
2737
UDATA = UNISYS.NewDataLink(this);
2838

29-
30-
console.error('######## fieldPanel Constructor')
3139
// Load Templates
32-
// The intial `OnAppStateChange("FILTERDEFS")` event when the template is
40+
// The intial `OnAppStateChange("FDATA")` event when the template is
3341
// first loaded is called well before FiltersPanel is
3442
// even constructed. So we need to explicitly load it here.
3543
let FDATA = UDATA.AppState("FDATA");
36-
console.error('####### FDATA', FDATA)
3744
this.state = FDATA;
3845

3946
UDATA.OnAppStateChange("FDATA", this.UpdateFilterDefs);
4047
} // constructor
4148

4249

4350
UpdateFilterDefs(data) {
44-
console.log('FiltersPanel: Updating filter defs', data);
4551
this.setState(data);
4652
}
4753

@@ -50,7 +56,7 @@ console.error('######## fieldPanel Constructor')
5056
}
5157

5258
componentWillUnmount() {
53-
console.error('gracefully unsubscribe!')
59+
console.error('TBD: gracefully unsubscribe!')
5460
}
5561

5662
render() {
@@ -80,7 +86,11 @@ console.error('######## fieldPanel Constructor')
8086
}
8187
}
8288

83-
module.exports = FiltersPanel;
89+
/// EXPORT CLASS DEFINITION ///////////////////////////////////////////////////
90+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8491

85-
// storyboard wants a regular export?!?!
92+
// Storybook export
8693
// export default FiltersPanel;
94+
95+
// Brunch export
96+
module.exports = FiltersPanel;

build/app/view/netcreate/components/filter/NumberFilter.js

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
/*//////////////////////////////// ABOUT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*\
2+
3+
NUMBERFILTER
4+
5+
NumberFilter provides the UI for entering search strings for numeric-based
6+
node and edge properties.
7+
8+
Seven Numeric operators are supported:
9+
* >
10+
* >=
11+
* <
12+
* <=
13+
* =
14+
* !=
15+
16+
Matches will SHOW the resulting node or edge.
17+
Any nodes/edges not matching will be hidden.
18+
19+
The filter definition is passed in via props.
20+
21+
props
22+
{
23+
group // "nodes" or "edges"
24+
filter: {
25+
id, // numeric id used for unique React key
26+
type, // filter type, e.g "string" vs "number"
27+
key, // node field key from the template
28+
keylabel, // human friendly display name for the key. This can be customized in the template.
29+
operator, // the comparison function, e.g. 'contains' or '>'
30+
value // the search value to be used for matching
31+
},
32+
onChangeHandler // callback function for parent component
33+
}
34+
35+
The `onChangeHandler` callback function is not currently used. Instead,
36+
selection changes directly trigger a UDATA.LocalCall('FILTER_DEFINE',...).
37+
38+
The `id` variable allows us to potentially support multiple search filters
39+
using the same key, e.g. we could have two 'Label' filters.
40+
41+
\*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ * //////////////////////////////////////*/
42+
43+
144
import FILTER from './FilterEnums';
245
import React from 'react';
346
const ReactStrap = require('reactstrap');
@@ -16,26 +59,8 @@ const OPERATORS = [
1659
{ value: FILTER.OPERATORS.NUMBER.NOT_EQ, label: `\u2260`},
1760
]
1861

19-
/*/
20-
21-
NumberFilter
2262

23-
props
24-
{
25-
group // node or edge
26-
filter: {
27-
id,
28-
type, // filter type, e.g "string" vs "number"
29-
key, // node field key from the template
30-
keylabel, // human friendly display name for the key. This can be customized in the template.
31-
operator,
32-
value
33-
},
34-
onChangeHandler // callback function
35-
}
36-
37-
38-
/*/
63+
/// CLASS /////////////////////////////////////////////////////////////////////
3964
class NumberFilter extends React.Component {
4065

4166
constructor({
@@ -71,10 +96,6 @@ class NumberFilter extends React.Component {
7196

7297
TriggerChangeHandler() {
7398
const { id, type, key, keylabel } = this.props.filter;
74-
75-
// Allow NO_OP so user can reset operator to blank
76-
// if (this.state.operator === FILTER.OPERATORS.NUMBER.NO_OP) return;
77-
7899
const filter = {
79100
id,
80101
type,
@@ -112,4 +133,6 @@ class NumberFilter extends React.Component {
112133
}
113134
}
114135

136+
/// EXPORT CLASS DEFINITION ///////////////////////////////////////////////////
137+
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
115138
export default NumberFilter;
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Filters
2+
3+
Filtering provides the ability to show and hide nodes and edges based on filter criteria.
4+
5+
* Matches will SHOW the resulting node or edge.
6+
* Any nodes/edges not matching will be hidden.
7+
8+
Filters are set via the "Filters" tab panel.
9+
10+
The graph will immediately update with any changes made by the user to a filter.
11+
12+
13+
## Specifying Filters via the Template Spec
14+
15+
The groups of available filters are drawn directly from the current database's template file, e.g. `tacitus.template`. It will reflect any customizations made to the labels and hidden/shown status.
16+
17+
18+
### Filter Types
19+
20+
In order for a filter to be defined for any given object key, it must have a "type" specified, e.g.
21+
22+
`_default.template`
23+
```json
24+
"notes": {
25+
"type": "string",
26+
"label": "Significance",
27+
...
28+
},
29+
```
30+
31+
32+
The available types are:
33+
34+
* "string"
35+
* "number"
36+
* "select" -- Drop down menu
37+
* "node" -- Special type for edge "source" and "target" setting.
38+
39+
Each type has specific operations associated with it, e.g. "string" supports "contains" and "not contains", whereas "number" supports ">" and "!=" etc.
40+
41+
* Any prompt without a "type" specification will be ignored (e.g. no filter setting will be shown for it).
42+
* `"hidden": true` prompts will not show as a filter.
43+
* Alternatively, you can set the `"type": "hidden"` to have the filter not show and retain the value in the database.
44+
45+
46+
## How Filtering Works
47+
48+
49+
#### How are filters applied?
50+
51+
Filters are applied via an implicit `AND`: An item matches the filter if EVERY filter that is active matches. For example, if we have:
52+
53+
Node: `Label contains ab`
54+
Node: `Type contains Person`
55+
56+
...then **person** `Abraham Lincoln` will be displayed, but **event** `Abolition` will not.
57+
58+
A few notes:
59+
60+
* Search is case insensitive.
61+
62+
* This works across both node and edge filters. So ALL node and ALL edge filters must pass.
63+
64+
* Any inactive filter is ignored (e.g. the operator is `--` or the value is `...`).
65+
66+
* Any edge that is connected to a hidden node is automatically hidden, overriding any filter match.
67+
68+
69+
#### How are Nodes/Edges hidden?
70+
71+
Programmatically, any node or edge that is filtered is marked with a `isFilteredOut` flag. If `isFilteredOut` is true, the object is hidden. If `isFilteredOut` is absent or is false, the object is displayed.
72+
73+
Hiding is simply done by setting the opacity of the node or edge. Nodes and edges are not actually removed from the graph.
74+
75+
76+
77+
### Storyboard
78+
79+
With the Filtering system, we introduce a new development toolkit [storybook.js](https://storybook.js.org/). This is primarily used for the basic component development and data architecture design.
80+
81+
* It is not yet fully integrated with the UNISYS architecture.
82+
* It is not yet fully integrated with bootstrap/css, so components are not displayed using the site's settings.
83+
84+
To run storybook, use `npm run storybook`.
85+

0 commit comments

Comments
 (0)