From 84d131b6b0e8d828efdc07b37d561b3f35dafc2d Mon Sep 17 00:00:00 2001 From: Risha Mars Date: Mon, 30 Apr 2018 10:18:47 -0700 Subject: [PATCH] Add a filter to the namespace column in the web UI (#866) Enables filtering by one or more namespaces. Table updates are prevented when the filter menu is open, as table updates will rerender the menu, unselecting anything the user has selected but not confirmed. --- web/app/js/components/MetricsTable.jsx | 41 +++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/web/app/js/components/MetricsTable.jsx b/web/app/js/components/MetricsTable.jsx index 86a53d198..4f3961e8f 100644 --- a/web/app/js/components/MetricsTable.jsx +++ b/web/app/js/components/MetricsTable.jsx @@ -29,12 +29,15 @@ const formatLongTitles = title => { return words; } }; -const columnDefinitions = (sortable = true, resource, ConduitLink) => { +const columnDefinitions = (sortable = true, resource, namespaces, onFilterClick, ConduitLink) => { return [ { title: "Namespace", key: "namespace", dataIndex: "namespace", + filters: namespaces, + onFilterDropdownVisibleChange: onFilterClick, + onFilter: (value, row) => row.namespace.indexOf(value) === 0, sorter: sortable ? (a, b) => (a.namespace || "").localeCompare(b.namespace) : false }, { @@ -102,26 +105,56 @@ export default class MetricsTable extends BaseTable { constructor(props) { super(props); this.api = this.props.api; + this.onFilterDropdownVisibleChange = this.onFilterDropdownVisibleChange.bind(this); + this.state = { + preventTableUpdates: false + }; } preprocessMetrics() { let tableData = _.cloneDeep(this.props.metrics); + let namespaces = []; _.each(tableData, datum => { + namespaces.push(datum.namespace); _.each(datum.latency, (value, quantile) => { datum[quantile] = value; }); }); - return tableData; + return { + rows: tableData, + namespaces: _.uniq(namespaces) + }; + } + + shouldComponentUpdate() { + // prevent the table from updating if the filter dropdown menu is open + // this is because if the table updates, the filters will reset which + // makes it impossible to select a filter + return !this.state.preventTableUpdates; + } + + onFilterDropdownVisibleChange(dropdownVisible) { + this.setState({ preventTableUpdates: dropdownVisible}); } render() { let tableData = this.preprocessMetrics(); - let columns = _.compact(columnDefinitions(this.props.sortable, this.props.resource, this.api.ConduitLink)); + let namespaceFilterText = _.map(tableData.namespaces, ns => { + return { text: ns, value: ns }; + }); + + let columns = _.compact(columnDefinitions( + this.props.sortable, + this.props.resource, + namespaceFilterText, + this.onFilterDropdownVisibleChange, + this.api.ConduitLink + )); return (