You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ea...@apache.org on 2019/10/04 13:27:19 UTC
[qpid-dispatch] branch eallen-DISPATCH-1385 updated: Implemented
table filtering for overview
This is an automated email from the ASF dual-hosted git repository.
eallen pushed a commit to branch eallen-DISPATCH-1385
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/eallen-DISPATCH-1385 by this push:
new c78dace Implemented table filtering for overview
c78dace is described below
commit c78dacea2ff5de6d627abf439bb39e65c8d3a5d0
Author: Ernest Allen <ea...@redhat.com>
AuthorDate: Fri Oct 4 09:27:01 2019 -0400
Implemented table filtering for overview
---
console/react/src/overview/addressHelper.js | 159 ---------------------
console/react/src/overview/addressesTable.js | 139 +++++++++++++++++-
console/react/src/overview/baseHelper.js | 62 --------
.../{overviewTable.js => overviewTableBase.js} | 86 +++++++++--
console/react/src/overview/routerHelper.js | 68 ---------
console/react/src/overview/routersTable.js | 45 +++++-
6 files changed, 249 insertions(+), 310 deletions(-)
diff --git a/console/react/src/overview/addressHelper.js b/console/react/src/overview/addressHelper.js
deleted file mode 100644
index aa13e64..0000000
--- a/console/react/src/overview/addressHelper.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-import { sortable } from "@patternfly/react-table";
-
-import BaseHelper from "./baseHelper";
-
-class AddressHelper extends BaseHelper {
- constructor(service) {
- super(service);
- this.fields = [
- { title: "Address", field: "address", transforms: [sortable] },
- { title: "Class", field: "class" },
- { title: "Phase", field: "phase" },
- { title: "In-proc", field: "inproc" },
- { title: "Local", field: "local" },
- { title: "Remote", field: "remote" },
- { title: "In", field: "in" },
- { title: "Out", field: "out" }
- ];
- }
-
- fetch = (perPage, page, sortBy) => {
- return new Promise(resolve => {
- var addr_phase = addr => {
- if (!addr) return "-";
- if (addr[0] === "M") return addr[1];
- return "";
- };
- var prettyVal = val => {
- return this.service.utilities.pretty(val || "-");
- };
- let addressFields = [];
- let addressObjs = {};
- // send the requests for all connection and router info for all routers
- this.service.management.topology.fetchAllEntities(
- { entity: "router.address" },
- nodes => {
- for (let node in nodes) {
- let response = nodes[node]["router.address"];
- response.results.forEach(result => {
- let address = this.service.utilities.flatten(
- response.attributeNames,
- result
- );
-
- var addNull = (oldVal, newVal) => {
- if (oldVal != null && newVal != null) return oldVal + newVal;
- if (oldVal != null) return oldVal;
- return newVal;
- };
-
- let uid = address.identity;
- let identity = this.service.utilities.identity_clean(uid);
-
- if (
- !addressObjs[
- this.service.utilities.addr_text(identity) +
- this.service.utilities.addr_class(identity)
- ]
- )
- addressObjs[
- this.service.utilities.addr_text(identity) +
- this.service.utilities.addr_class(identity)
- ] = {
- address: this.service.utilities.addr_text(identity),
- class: this.service.utilities.addr_class(identity),
- phase: addr_phase(identity),
- inproc: address.inProcess,
- local: address.subscriberCount,
- remote: address.remoteCount,
- in: address.deliveriesIngress,
- out: address.deliveriesEgress,
- thru: address.deliveriesTransit,
- toproc: address.deliveriesToContainer,
- fromproc: address.deliveriesFromContainer,
- uid: uid
- };
- else {
- let sumObj =
- addressObjs[
- this.service.utilities.addr_text(identity) +
- this.service.utilities.addr_class(identity)
- ];
- sumObj.inproc = addNull(sumObj.inproc, address.inProcess);
- sumObj.local = addNull(sumObj.local, address.subscriberCount);
- sumObj.remote = addNull(sumObj.remote, address.remoteCount);
- sumObj["in"] = addNull(sumObj["in"], address.deliveriesIngress);
- sumObj.out = addNull(sumObj.out, address.deliveriesEgress);
- sumObj.thru = addNull(sumObj.thru, address.deliveriesTransit);
- sumObj.toproc = addNull(
- sumObj.toproc,
- address.deliveriesToContainer
- );
- sumObj.fromproc = addNull(
- sumObj.fromproc,
- address.deliveriesFromContainer
- );
- }
- });
- }
- for (let obj in addressObjs) {
- addressObjs[obj].inproc = prettyVal(addressObjs[obj].inproc);
- addressObjs[obj].local = prettyVal(addressObjs[obj].local);
- addressObjs[obj].remote = prettyVal(addressObjs[obj].remote);
- addressObjs[obj]["in"] = prettyVal(addressObjs[obj]["in"]);
- addressObjs[obj].out = prettyVal(addressObjs[obj].out);
- addressObjs[obj].thru = prettyVal(addressObjs[obj].thru);
- addressObjs[obj].toproc = prettyVal(addressObjs[obj].toproc);
- addressObjs[obj].fromproc = prettyVal(addressObjs[obj].fromproc);
- addressFields.push(addressObjs[obj]);
- }
- if (addressFields.length === 0) return;
- // update the grid's data
- addressFields.sort((a, b) => {
- return a.address + a["class"] < b.address + b["class"]
- ? -1
- : a.address + a["class"] > b.address + b["class"]
- ? 1
- : 0;
- });
- addressFields[0].title = addressFields[0].address;
- for (let i = 1; i < addressFields.length; ++i) {
- // if this address is the same as the previous address, add a class to the display titles
- if (addressFields[i].address === addressFields[i - 1].address) {
- addressFields[i - 1].title =
- addressFields[i - 1].address +
- " (" +
- addressFields[i - 1]["class"] +
- ")";
- addressFields[i].title =
- addressFields[i].address +
- " (" +
- addressFields[i]["class"] +
- ")";
- } else addressFields[i].title = addressFields[i].address;
- }
- resolve(this.slice(addressFields, page, perPage, sortBy));
- }
- );
- });
- };
-}
-export default AddressHelper;
diff --git a/console/react/src/overview/addressesTable.js b/console/react/src/overview/addressesTable.js
index 160d0b7..b69345c 100644
--- a/console/react/src/overview/addressesTable.js
+++ b/console/react/src/overview/addressesTable.js
@@ -17,14 +17,145 @@ specific language governing permissions and limitations
under the License.
*/
-import OverviewTable from "./overviewTable";
-import AddressHelper from "./addressHelper";
+import { sortable } from "@patternfly/react-table";
-class AddressesTable extends OverviewTable {
+import OverviewTableBase from "./overviewTableBase";
+
+class AddressesTable extends OverviewTableBase {
constructor(props) {
super(props);
- this.helper = new AddressHelper(this.props.service);
+ this.fields = [
+ { title: "Address", field: "address", transforms: [sortable] },
+ { title: "Class", field: "class" },
+ { title: "Phase", field: "phase" },
+ { title: "In-proc", field: "inproc" },
+ { title: "Local", field: "local" },
+ { title: "Remote", field: "remote" },
+ { title: "In", field: "in" },
+ { title: "Out", field: "out" }
+ ];
}
+
+ doFetch = (page, perPage) => {
+ return new Promise(resolve => {
+ var addr_phase = addr => {
+ if (!addr) return "-";
+ if (addr[0] === "M") return addr[1];
+ return "";
+ };
+ var prettyVal = val => {
+ return this.props.service.utilities.pretty(val || "-");
+ };
+ let addressFields = [];
+ let addressObjs = {};
+ // send the requests for all connection and router info for all routers
+ this.props.service.management.topology.fetchAllEntities(
+ { entity: "router.address" },
+ nodes => {
+ for (let node in nodes) {
+ let response = nodes[node]["router.address"];
+ response.results.forEach(result => {
+ let address = this.props.service.utilities.flatten(
+ response.attributeNames,
+ result
+ );
+
+ var addNull = (oldVal, newVal) => {
+ if (oldVal != null && newVal != null) return oldVal + newVal;
+ if (oldVal != null) return oldVal;
+ return newVal;
+ };
+
+ let uid = address.identity;
+ let identity = this.props.service.utilities.identity_clean(uid);
+
+ if (
+ !addressObjs[
+ this.props.service.utilities.addr_text(identity) +
+ this.props.service.utilities.addr_class(identity)
+ ]
+ )
+ addressObjs[
+ this.props.service.utilities.addr_text(identity) +
+ this.props.service.utilities.addr_class(identity)
+ ] = {
+ address: this.props.service.utilities.addr_text(identity),
+ class: this.props.service.utilities.addr_class(identity),
+ phase: addr_phase(identity),
+ inproc: address.inProcess,
+ local: address.subscriberCount,
+ remote: address.remoteCount,
+ in: address.deliveriesIngress,
+ out: address.deliveriesEgress,
+ thru: address.deliveriesTransit,
+ toproc: address.deliveriesToContainer,
+ fromproc: address.deliveriesFromContainer,
+ uid: uid
+ };
+ else {
+ let sumObj =
+ addressObjs[
+ this.props.service.utilities.addr_text(identity) +
+ this.props.service.utilities.addr_class(identity)
+ ];
+ sumObj.inproc = addNull(sumObj.inproc, address.inProcess);
+ sumObj.local = addNull(sumObj.local, address.subscriberCount);
+ sumObj.remote = addNull(sumObj.remote, address.remoteCount);
+ sumObj["in"] = addNull(sumObj["in"], address.deliveriesIngress);
+ sumObj.out = addNull(sumObj.out, address.deliveriesEgress);
+ sumObj.thru = addNull(sumObj.thru, address.deliveriesTransit);
+ sumObj.toproc = addNull(
+ sumObj.toproc,
+ address.deliveriesToContainer
+ );
+ sumObj.fromproc = addNull(
+ sumObj.fromproc,
+ address.deliveriesFromContainer
+ );
+ }
+ });
+ }
+ for (let obj in addressObjs) {
+ addressObjs[obj].inproc = prettyVal(addressObjs[obj].inproc);
+ addressObjs[obj].local = prettyVal(addressObjs[obj].local);
+ addressObjs[obj].remote = prettyVal(addressObjs[obj].remote);
+ addressObjs[obj]["in"] = prettyVal(addressObjs[obj]["in"]);
+ addressObjs[obj].out = prettyVal(addressObjs[obj].out);
+ addressObjs[obj].thru = prettyVal(addressObjs[obj].thru);
+ addressObjs[obj].toproc = prettyVal(addressObjs[obj].toproc);
+ addressObjs[obj].fromproc = prettyVal(addressObjs[obj].fromproc);
+ addressFields.push(addressObjs[obj]);
+ }
+ if (addressFields.length === 0) return;
+ // update the grid's data
+ addressFields.sort((a, b) => {
+ return a.address + a["class"] < b.address + b["class"]
+ ? -1
+ : a.address + a["class"] > b.address + b["class"]
+ ? 1
+ : 0;
+ });
+ addressFields[0].title = addressFields[0].address;
+ for (let i = 1; i < addressFields.length; ++i) {
+ // if this address is the same as the previous address, add a class to the display titles
+ if (addressFields[i].address === addressFields[i - 1].address) {
+ addressFields[i - 1].title =
+ addressFields[i - 1].address +
+ " (" +
+ addressFields[i - 1]["class"] +
+ ")";
+ addressFields[i].title =
+ addressFields[i].address +
+ " (" +
+ addressFields[i]["class"] +
+ ")";
+ } else addressFields[i].title = addressFields[i].address;
+ }
+ resolve(this.slice(addressFields, page, perPage));
+ }
+ );
+ });
+ };
}
export default AddressesTable;
diff --git a/console/react/src/overview/baseHelper.js b/console/react/src/overview/baseHelper.js
deleted file mode 100644
index 831161c..0000000
--- a/console/react/src/overview/baseHelper.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-import { SortByDirection } from "@patternfly/react-table";
-
-class BaseHelper {
- constructor(service) {
- this.service = service;
- this.fields = [];
- }
-
- field2Row = field => ({
- cells: this.fields.map(f => field[f.field])
- });
-
- slice = (fields, page, perPage, sortBy) => {
- let rows = fields.map(f => this.field2Row(f));
- rows = this.sort(rows, sortBy.index, sortBy.direction);
- const total = rows.length;
- const newPages = Math.ceil(total / perPage);
- page = Math.min(page, newPages);
- const start = perPage * (page - 1);
- const end = Math.min(start + perPage, rows.length);
- const slicedRows = rows.slice(start, end);
- return { rows: slicedRows, page, total, allRows: rows };
- };
-
- sort = (rows, index, direction) => {
- if (typeof index === "undefined" || typeof direction === "undefined") {
- return rows;
- }
- rows.sort((a, b) =>
- a.cells[index] < b.cells[index]
- ? -1
- : a.cells[index] > b.cells[index]
- ? 1
- : 0
- );
- if (direction === SortByDirection.desc) {
- rows = rows.reverse();
- }
- return rows;
- };
-}
-
-export default BaseHelper;
diff --git a/console/react/src/overview/overviewTable.js b/console/react/src/overview/overviewTableBase.js
similarity index 60%
rename from console/react/src/overview/overviewTable.js
rename to console/react/src/overview/overviewTableBase.js
index c3f7315..a1969c8 100644
--- a/console/react/src/overview/overviewTable.js
+++ b/console/react/src/overview/overviewTableBase.js
@@ -1,14 +1,20 @@
import React from "react";
-import { Table, TableHeader, TableBody } from "@patternfly/react-table";
-
+import {
+ SortByDirection,
+ Table,
+ TableHeader,
+ TableBody
+} from "@patternfly/react-table";
import { Pagination, Title } from "@patternfly/react-core";
+
import TableToolbar from "./tableToolbar";
-class OverviewTable extends React.Component {
+class OverviewTableBase extends React.Component {
constructor(props) {
super(props);
this.state = {
sortBy: {},
+ filterBy: {},
perPage: 10,
total: 1,
page: 1,
@@ -45,14 +51,13 @@ class OverviewTable extends React.Component {
}
]
};
- this.helper = null; // set in parent class
}
componentDidMount() {
this.mounted = true;
console.log("overviewTable componentDidMount");
// initialize the columns and get the data
- this.setState({ columns: this.helper.fields }, () => {
+ this.setState({ columns: this.fields }, () => {
this.update();
this.timer = setInterval(this.upate, 5000);
});
@@ -68,9 +73,9 @@ class OverviewTable extends React.Component {
};
fetch = (page, perPage) => {
- if (!this.mounted) return;
this.setState({ loading: true });
- this.helper.fetch(perPage, page, this.state.sortBy).then(sliced => {
+ // doFetch is defined in the derived class
+ this.doFetch(page, perPage).then(sliced => {
// if fetch was called and the component was unmounted before
// the results arrived, don't call setState
if (!this.mounted) return;
@@ -78,8 +83,8 @@ class OverviewTable extends React.Component {
this.setState({
rows,
loading: false,
- perPage,
page,
+ perPage,
total,
allRows
});
@@ -87,7 +92,7 @@ class OverviewTable extends React.Component {
};
onSort = (_event, index, direction) => {
- const rows = this.helper.sort(this.state.allRows, index, direction);
+ const rows = this.sort(this.state.allRows, index, direction);
this.setState({ rows, page: 1, sortBy: { index, direction } });
};
@@ -98,8 +103,8 @@ class OverviewTable extends React.Component {
itemCount={total}
page={page}
perPage={perPage}
- onSetPage={(_evt, value) => this.fetch(value, perPage)}
- onPerPageSelect={(_evt, value) => this.fetch(1, value)}
+ onSetPage={(_evt, value) => this.onSetPage(value)}
+ onPerPageSelect={(_evt, value) => this.onPerPageSelect(value)}
variant={variant}
/>
);
@@ -112,8 +117,63 @@ class OverviewTable extends React.Component {
this.fetch(1, value);
};
handleChangeFilterValue = (field, value) => {
+ this.setState({ filterBy: { field, value } }, this.update);
console.log(`handleChangeFilterValue(${field}, ${value})`);
};
+
+ field2Row = field => ({
+ cells: this.fields.map(f => field[f.field])
+ });
+
+ cellIndex = field => {
+ return this.fields.findIndex(f => {
+ return f.title === field;
+ });
+ };
+ slice = (fields, page, perPage) => {
+ const filterField = this.state.filterBy.field;
+ const filterValue = this.state.filterBy.value;
+ let rows = fields.map(f => this.field2Row(f));
+ if (
+ typeof filterField !== "undefined" &&
+ typeof filterValue !== "undefined" &&
+ filterValue !== ""
+ ) {
+ const cellIndex = this.cellIndex(filterField);
+ rows = rows.filter(r => {
+ return r.cells[cellIndex].includes(filterValue);
+ });
+ }
+ rows = this.sort(rows);
+ const total = rows.length;
+ const newPages = Math.ceil(total / perPage);
+ page = Math.min(page, newPages);
+ const start = perPage * (page - 1);
+ const end = Math.min(start + perPage, rows.length);
+ const slicedRows = rows.slice(start, end);
+ return { rows: slicedRows, page, total, allRows: rows };
+ };
+
+ sort = rows => {
+ if (
+ typeof this.state.index === "undefined" ||
+ typeof this.state.direction === "undefined"
+ ) {
+ return rows;
+ }
+ rows.sort((a, b) =>
+ a.cells[this.sate.index] < b.cells[this.sate.index]
+ ? -1
+ : a.cells[this.sate.index] > b.cells[this.sate.index]
+ ? 1
+ : 0
+ );
+ if (this.sate.direction === SortByDirection.desc) {
+ rows = rows.reverse();
+ }
+ return rows;
+ };
+
render() {
console.log("OverviewTable rendered");
const { loading } = this.state;
@@ -125,7 +185,7 @@ class OverviewTable extends React.Component {
perPage={this.state.perPage}
onSetPage={this.onSetPage}
onPerPageSelect={this.onPerPageSelect}
- fields={this.helper.fields}
+ fields={this.fields}
handleChangeFilterValue={this.handleChangeFilterValue}
/>
{!loading && (
@@ -151,4 +211,4 @@ class OverviewTable extends React.Component {
}
}
-export default OverviewTable;
+export default OverviewTableBase;
diff --git a/console/react/src/overview/routerHelper.js b/console/react/src/overview/routerHelper.js
deleted file mode 100644
index 9be13b5..0000000
--- a/console/react/src/overview/routerHelper.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-import { sortable } from "@patternfly/react-table";
-
-import BaseHelper from "./baseHelper";
-class RouterHelper extends BaseHelper {
- constructor(service) {
- super(service);
- this.fields = [
- { title: "Router", field: "name", transforms: [sortable] },
- { title: "Area", field: "area" },
- { title: "Mode", field: "mode" },
- { title: "Addresses", field: "addrCount" },
- { title: "Links", field: "linkCount" },
- { title: "External connections", field: "connections" }
- ];
- }
-
- fetch = (perPage, page, sortBy) => {
- return new Promise(resolve => {
- this.service.management.topology.fetchAllEntities(
- [{ entity: "connection", attrs: ["role"] }, { entity: "router" }],
- nodes => {
- // we have all the data now in the nodes object
- let allRouterFields = [];
- for (let node in nodes) {
- let connections = 0;
- for (let i = 0; i < nodes[node]["connection"].results.length; ++i) {
- // we only requested "role" so it will be at [0]
- if (nodes[node]["connection"].results[i][0] !== "inter-router")
- ++connections;
- }
- let routerRow = {
- connections: connections,
- nodeId: node,
- id: this.service.utilities.nameFromId(node)
- };
- nodes[node]["router"].attributeNames.forEach((routerAttr, i) => {
- if (routerAttr !== "routerId" && routerAttr !== "id")
- routerRow[routerAttr] = nodes[node]["router"].results[0][i];
- });
- allRouterFields.push(routerRow);
- }
- resolve(this.slice(allRouterFields, page, perPage, sortBy));
- }
- );
- });
- };
-}
-
-export default RouterHelper;
diff --git a/console/react/src/overview/routersTable.js b/console/react/src/overview/routersTable.js
index f00dca3..b846c31 100644
--- a/console/react/src/overview/routersTable.js
+++ b/console/react/src/overview/routersTable.js
@@ -17,14 +17,51 @@ specific language governing permissions and limitations
under the License.
*/
-import OverviewTable from "./overviewTable";
-import RouterHelper from "./routerHelper";
+import { sortable } from "@patternfly/react-table";
+import OverviewTableBase from "./overviewTableBase";
-class RoutersTable extends OverviewTable {
+class RoutersTable extends OverviewTableBase {
constructor(props) {
super(props);
- this.helper = new RouterHelper(this.props.service);
+ this.fields = [
+ { title: "Router", field: "name", transforms: [sortable] },
+ { title: "Area", field: "area" },
+ { title: "Mode", field: "mode" },
+ { title: "Addresses", field: "addrCount" },
+ { title: "Links", field: "linkCount" },
+ { title: "External connections", field: "connections" }
+ ];
}
+ doFetch = (page, perPage) => {
+ return new Promise(resolve => {
+ this.props.service.management.topology.fetchAllEntities(
+ [{ entity: "connection", attrs: ["role"] }, { entity: "router" }],
+ nodes => {
+ // we have all the data now in the nodes object
+ let allRouterFields = [];
+ for (let node in nodes) {
+ let connections = 0;
+ for (let i = 0; i < nodes[node]["connection"].results.length; ++i) {
+ // we only requested "role" so it will be at [0]
+ if (nodes[node]["connection"].results[i][0] !== "inter-router")
+ ++connections;
+ }
+ let routerRow = {
+ connections: connections,
+ nodeId: node,
+ id: this.props.service.utilities.nameFromId(node)
+ };
+ nodes[node]["router"].attributeNames.forEach((routerAttr, i) => {
+ if (routerAttr !== "routerId" && routerAttr !== "id")
+ routerRow[routerAttr] = nodes[node]["router"].results[0][i];
+ });
+ allRouterFields.push(routerRow);
+ }
+ resolve(this.slice(allRouterFields, page, perPage));
+ }
+ );
+ });
+ };
}
export default RoutersTable;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org