[ARVADOS-WORKBENCH2] updated: 1.1.4-121-g5925c0e
Git user
git at public.curoverse.com
Wed Jun 20 07:28:46 EDT 2018
Summary of changes:
package.json | 4 +-
.../data-table-filters/data-table-filters.test.tsx | 70 ++++++++
.../data-table-filters/data-table-filters.tsx | 189 +++++++++++++++++++++
src/components/data-table/data-column.ts | 4 +
src/components/data-table/data-table.tsx | 22 ++-
.../data-explorer/data-explorer.tsx | 16 ++
yarn.lock | 20 ++-
7 files changed, 314 insertions(+), 11 deletions(-)
create mode 100644 src/components/data-table-filters/data-table-filters.test.tsx
create mode 100644 src/components/data-table-filters/data-table-filters.tsx
via 5925c0eb9468ffca9419e47ae333501968b4e24e (commit)
via fd79729916cf6ddf27063b1865d39a36abb9e038 (commit)
from 1a9eb2261e6030ba78078e2a206bad27653f2475 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 5925c0eb9468ffca9419e47ae333501968b4e24e
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Wed Jun 20 13:28:28 2018 +0200
Create tests for data table filter
Feature #13633
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --git a/src/components/data-table-filters/data-table-filters.test.tsx b/src/components/data-table-filters/data-table-filters.test.tsx
new file mode 100644
index 0000000..6756252
--- /dev/null
+++ b/src/components/data-table-filters/data-table-filters.test.tsx
@@ -0,0 +1,70 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { mount, configure } from "enzyme";
+import DataTableFilter, { DataTableFilterItem } from "./data-table-filters";
+
+import * as Adapter from 'enzyme-adapter-react-16';
+import { Checkbox, ButtonBase, ListItem, Button, ListItemText } from "@material-ui/core";
+import dataTableFilters from "./data-table-filters";
+
+configure({ adapter: new Adapter() });
+
+describe("<DataTableFilter />", () => {
+ it("renders filters according to their state", () => {
+ const filters = [{
+ name: "Filter 1",
+ selected: true
+ }, {
+ name: "Filter 2",
+ selected: false
+ }];
+ const dataTableFilter = mount(<DataTableFilter name="" filters={filters} />);
+ dataTableFilter.find(ButtonBase).simulate("click");
+ expect(dataTableFilter.find(Checkbox).at(0).prop("checked")).toBeTruthy();
+ expect(dataTableFilter.find(Checkbox).at(1).prop("checked")).toBeFalsy();
+ });
+
+ it("updates filters after filters prop change", () => {
+ const filters = [{
+ name: "Filter 1",
+ selected: true
+ }];
+ const updatedFilters = [, {
+ name: "Filter 2",
+ selected: true
+ }];
+ const dataTableFilter = mount(<DataTableFilter name="" filters={filters} />);
+ dataTableFilter.find(ButtonBase).simulate("click");
+ expect(dataTableFilter.find(Checkbox).prop("checked")).toBeTruthy();
+ dataTableFilter.find(ListItem).simulate("click");
+ expect(dataTableFilter.find(Checkbox).prop("checked")).toBeFalsy();
+ dataTableFilter.setProps({filters: updatedFilters});
+ expect(dataTableFilter.find(Checkbox).prop("checked")).toBeTruthy();
+ expect(dataTableFilter.find(ListItemText).text()).toBe("Filter 2");
+ });
+
+ it("calls onChange with modified list of filters", () => {
+ const filters = [{
+ name: "Filter 1",
+ selected: true
+ }, {
+ name: "Filter 2",
+ selected: false
+ }];
+ const onChange = jest.fn();
+ const dataTableFilter = mount(<DataTableFilter name="" filters={filters} onChange={onChange} />);
+ dataTableFilter.find(ButtonBase).simulate("click");
+ dataTableFilter.find(ListItem).at(1).simulate("click");
+ dataTableFilter.find(Button).at(0).simulate("click");
+ expect(onChange).toHaveBeenCalledWith([{
+ name: "Filter 1",
+ selected: true
+ }, {
+ name: "Filter 2",
+ selected: true
+ }]);
+ });
+});
\ No newline at end of file
commit fd79729916cf6ddf27063b1865d39a36abb9e038
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Wed Jun 20 12:59:11 2018 +0200
Create data table filter component
Feature #13633
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --git a/package.json b/package.json
index fda2ead..1f08e6c 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"@material-ui/icons": "1.1.0",
"@types/lodash": "4.14.109",
"axios": "0.18.0",
+ "classnames": "^2.2.6",
"lodash": "4.17.10",
"react": "16.4.1",
"react-dom": "16.4.1",
@@ -27,11 +28,12 @@
"lint": "tslint src/** -t verbose"
},
"devDependencies": {
+ "@types/classnames": "^2.2.4",
"@types/enzyme": "3.1.10",
"@types/enzyme-adapter-react-16": "1.0.2",
"@types/jest": "23.1.0",
"@types/node": "10.3.3",
- "@types/react": "16.3.18",
+ "@types/react": "16.4.1",
"@types/react-dom": "16.0.6",
"@types/react-redux": "6.0.2",
"@types/react-router": "4.0.26",
diff --git a/src/components/data-table-filters/data-table-filters.tsx b/src/components/data-table-filters/data-table-filters.tsx
new file mode 100644
index 0000000..cf0260b
--- /dev/null
+++ b/src/components/data-table-filters/data-table-filters.tsx
@@ -0,0 +1,189 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import {
+ WithStyles,
+ withStyles,
+ ButtonBase,
+ StyleRulesCallback,
+ Theme,
+ Popover,
+ List,
+ ListItem,
+ Checkbox,
+ ListItemText,
+ Button,
+ Card,
+ CardActions,
+ Typography,
+ CardContent
+} from "@material-ui/core";
+import * as classnames from "classnames";
+import { DefaultTransformOrigin } from "../popover/helpers";
+
+export interface DataTableFilterItem {
+ name: string;
+ selected: boolean;
+}
+
+export interface DataTableFilterProps {
+ name: string;
+ filters: DataTableFilterItem[];
+ onChange?: (filters: DataTableFilterItem[]) => void;
+}
+
+interface DataTableFilterState {
+ anchorEl?: HTMLElement;
+ filters: DataTableFilterItem[];
+ prevFilters: DataTableFilterItem[];
+}
+
+class DataTableFilter extends React.Component<DataTableFilterProps & WithStyles<CssRules>, DataTableFilterState> {
+ state: DataTableFilterState = {
+ anchorEl: undefined,
+ filters: [],
+ prevFilters: []
+ };
+ icon = React.createRef<HTMLElement>();
+
+ render() {
+ const { name, classes, children } = this.props;
+ return <>
+ <ButtonBase
+ className={classnames([
+ classes.root,
+ { [classes.active]: this.state.filters.filter(({ selected }) => !selected).length > 0 }])}
+ component="span"
+ onClick={this.open}
+ disableRipple>
+ {children}
+ <i className={classnames(["fas fa-filter", classes.icon])}
+ data-fa-transform="shrink-3"
+ ref={this.icon} />
+ </ButtonBase>
+ <Popover
+ anchorEl={this.state.anchorEl}
+ open={!!this.state.anchorEl}
+ anchorOrigin={DefaultTransformOrigin}
+ transformOrigin={DefaultTransformOrigin}
+ onClose={this.cancel}>
+ <Card>
+ <CardContent>
+ <Typography variant="caption">
+ {name}
+ </Typography>
+ </CardContent>
+ <List dense>
+ {this.state.filters.map((filter, index) =>
+ <ListItem
+ button
+ key={index}
+ onClick={this.toggleFilter(filter)}>
+ <Checkbox
+ disableRipple
+ color="primary"
+ checked={filter.selected}
+ className={classes.checkbox} />
+ <ListItemText>
+ {filter.name}
+ </ListItemText>
+ </ListItem>
+ )}
+ </List>
+ <CardActions>
+ <Button
+ color="primary"
+ variant="raised"
+ size="small"
+ onClick={this.submit}>
+ Ok
+ </Button>
+ <Button
+ color="primary"
+ variant="outlined"
+ size="small"
+ onClick={this.cancel}>
+ Cancel
+ </Button>
+ </CardActions >
+ </Card>
+ </Popover>
+ </>;
+ }
+
+ static getDerivedStateFromProps(props: DataTableFilterProps, state: DataTableFilterState): DataTableFilterState {
+ return props.filters !== state.prevFilters
+ ? { ...state, filters: props.filters, prevFilters: props.filters }
+ : state;
+ }
+
+ open = () => {
+ this.setState({ anchorEl: this.icon.current || undefined });
+ }
+
+ submit = () => {
+ const { onChange } = this.props;
+ if (onChange) {
+ onChange(this.state.filters);
+ }
+ this.setState({ anchorEl: undefined });
+ }
+
+ cancel = () => {
+ this.setState(prev => ({
+ ...prev,
+ filters: prev.prevFilters,
+ anchorEl: undefined
+ }));
+ }
+
+ toggleFilter = (toggledFilter: DataTableFilterItem) => () => {
+ this.setState(prev => ({
+ ...prev,
+ filters: prev.filters.map(filter =>
+ filter === toggledFilter
+ ? { ...filter, selected: !filter.selected }
+ : filter)
+ }));
+ }
+}
+
+
+export type CssRules = "root" | "icon" | "active" | "checkbox";
+
+const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
+ root: {
+ cursor: "pointer",
+ display: "inline-flex",
+ justifyContent: "flex-start",
+ flexDirection: "inherit",
+ alignItems: "center",
+ "&:hover": {
+ color: theme.palette.text.primary,
+ },
+ "&:focus": {
+ color: theme.palette.text.primary,
+ },
+ },
+ active: {
+ color: theme.palette.text.primary,
+ '& $icon': {
+ opacity: 1,
+ },
+ },
+ icon: {
+ marginRight: 4,
+ marginLeft: 4,
+ opacity: 0.7,
+ userSelect: "none",
+ width: 16
+ },
+ checkbox: {
+ width: 24,
+ height: 24
+ }
+});
+
+export default withStyles(styles)(DataTableFilter);
diff --git a/src/components/data-table/data-column.ts b/src/components/data-table/data-column.ts
index f3d9576..7ac568a 100644
--- a/src/components/data-table/data-column.ts
+++ b/src/components/data-table/data-column.ts
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: AGPL-3.0
+import { DataTableFilterItem } from "../data-table-filters/data-table-filters";
+
export interface DataColumn<T> {
name: string;
selected: boolean;
@@ -9,6 +11,8 @@ export interface DataColumn<T> {
key?: React.Key;
sortDirection?: SortDirection;
onSortToggle?: () => void;
+ filters?: DataTableFilterItem[];
+ onFiltersChange?: (filters: DataTableFilterItem[]) => void;
render: (item: T) => React.ReactElement<void>;
renderHeader?: () => React.ReactElement<void> | null;
}
diff --git a/src/components/data-table/data-table.tsx b/src/components/data-table/data-table.tsx
index 43efdd0..26f6faf 100644
--- a/src/components/data-table/data-table.tsx
+++ b/src/components/data-table/data-table.tsx
@@ -5,6 +5,7 @@
import * as React from 'react';
import { Table, TableBody, TableRow, TableCell, TableHead, TableSortLabel, StyleRulesCallback, Theme, WithStyles, withStyles, Typography } from '@material-ui/core';
import { DataColumn } from './data-column';
+import DataTableFilters from "../data-table-filters/data-table-filters";
export type DataColumns<T> = Array<DataColumn<T>>;
@@ -25,16 +26,23 @@ class DataTable<T> extends React.Component<DataTableProps<T> & WithStyles<CssRul
<TableRow>
{columns
.filter(column => column.selected)
- .map(({ name, renderHeader, key, sortDirection, onSortToggle }, index) =>
+ .map(({ name, renderHeader, key, sortDirection, onSortToggle, filters, onFiltersChange }, index) =>
<TableCell key={key || index}>
{renderHeader ?
renderHeader() :
- <TableSortLabel
- active={!!sortDirection}
- direction={sortDirection}
- onClick={() => onSortToggle && onSortToggle()}>
- {name}
- </TableSortLabel>}
+ filters ?
+ <DataTableFilters
+ name={`${name} filters`}
+ onChange={onFiltersChange}
+ filters={filters}>
+ {name}
+ </DataTableFilters> :
+ <TableSortLabel
+ active={!!sortDirection}
+ direction={sortDirection}
+ onClick={() => onSortToggle && onSortToggle()}>
+ {name}
+ </TableSortLabel>}
</TableCell>
)}
</TableRow>
diff --git a/src/views-components/data-explorer/data-explorer.tsx b/src/views-components/data-explorer/data-explorer.tsx
index ffb21f9..dab686e 100644
--- a/src/views-components/data-explorer/data-explorer.tsx
+++ b/src/views-components/data-explorer/data-explorer.tsx
@@ -49,10 +49,26 @@ class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState>
}, {
name: "Status",
selected: true,
+ onFiltersChange: console.log,
+ filters: [{
+ name: "In progress",
+ selected: true
+ }, {
+ name: "Complete",
+ selected: true
+ }],
render: item => renderStatus(item.status)
}, {
name: "Type",
selected: true,
+ onFiltersChange: console.log,
+ filters: [{
+ name: "Collection",
+ selected: true
+ }, {
+ name: "Group",
+ selected: true
+ }],
render: item => renderType(item.type)
}, {
name: "Owner",
diff --git a/yarn.lock b/yarn.lock
index eee6c86..05a6ef1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -65,6 +65,10 @@
version "0.22.7"
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.7.tgz#4a92eafedfb2b9f4437d3a4410006d81114c66ce"
+"@types/classnames@^2.2.4":
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.4.tgz#d3ee9ebf714aa34006707b8f4a58fd46b642305a"
+
"@types/enzyme-adapter-react-16 at 1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.2.tgz#15ae37c64d6221a6f4b3a4aacc357cf773859de4"
@@ -145,12 +149,18 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react at 16.3.18":
+"@types/react@*":
version "16.3.18"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.18.tgz#bf195aed4d77dc86f06e4c9bb760214a3b822b8d"
dependencies:
csstype "^2.2.0"
+"@types/react at 16.4.1":
+ version "16.4.1"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.1.tgz#c53bbfb4a78933db587da085ac60dbf5fcf73f8f"
+ dependencies:
+ csstype "^2.2.0"
+
"@types/redux-devtools at 3.0.44":
version "3.0.44"
resolved "https://registry.yarnpkg.com/@types/redux-devtools/-/redux-devtools-3.0.44.tgz#2781b87067b8aec3102d4cb4a478feb340df5259"
@@ -1559,7 +1569,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
-classnames@^2.2.5:
+classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
@@ -2007,10 +2017,14 @@ cssom at 0.3.x, "cssom@>= 0.3.2 < 0.4.0":
dependencies:
cssom "0.3.x"
-csstype@^2.0.0, csstype@^2.2.0, csstype@^2.5.2:
+csstype@^2.0.0, csstype@^2.5.2:
version "2.5.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.3.tgz#2504152e6e1cc59b32098b7f5d6a63f16294c1f7"
+csstype@^2.2.0:
+ version "2.5.5"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.5.tgz#4125484a3d42189a863943f23b9e4b80fedfa106"
+
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list