[ARVADOS-WORKBENCH2] updated: 1.1.4-123-g9e4aa2f

Git user git at public.curoverse.com
Thu Jun 21 05:52:24 EDT 2018


Summary of changes:
 src/components/context-menu/context-menu.test.tsx  |  34 ++-----
 src/components/context-menu/context-menu.tsx       |  15 ++-
 .../data-explorer/data-explorer-column.tsx         |  19 ----
 src/components/data-explorer/data-explorer.tsx     |  87 ++++++------------
 src/components/data-table/data-column.ts           |  13 +--
 src/components/data-table/data-table.test.tsx      |  60 ++++++++++--
 src/components/data-table/data-table.tsx           | 101 ++++++++++++---------
 .../project-explorer/project-explorer.tsx          |  73 ++++++++++-----
 8 files changed, 209 insertions(+), 193 deletions(-)
 delete mode 100644 src/components/data-explorer/data-explorer-column.tsx

       via  9e4aa2fd44835698c0a3e6f321a2cf88b6f11939 (commit)
      from  bca77b4dbbc90bc60de06bd90a20e9a46c02fcfa (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 9e4aa2fd44835698c0a3e6f321a2cf88b6f11939
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Thu Jun 21 11:52:08 2018 +0200

    Refactor code for easier testing
    
    Feature #13633
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/components/context-menu/context-menu.test.tsx b/src/components/context-menu/context-menu.test.tsx
index 9e4a9a4..e4e2397 100644
--- a/src/components/context-menu/context-menu.test.tsx
+++ b/src/components/context-menu/context-menu.test.tsx
@@ -11,41 +11,25 @@ import { ListItem } from "@material-ui/core";
 configure({ adapter: new Adapter() });
 
 describe("<ContextMenu />", () => {
-
-    const item = {
-        name: "",
-        owner: "",
-        lastModified: "",
-        type: ""
-    };
-
     const actions = [[{
         icon: "",
-        name: "Action 1.1",
-        onClick: jest.fn()
-    },
-    {
+        name: "Action 1.1"
+    }, {
         icon: "",
-        name: "Action 1.2",
-        onClick: jest.fn()
+        name: "Action 1.2"
     },], [{
         icon: "",
-        name: "Action 2.1",
-        onClick: jest.fn()
+        name: "Action 2.1"
     }]];
 
-    it("calls provided actions with provided item", () => {
+    it("calls onActionClick with clicked action", () => {
+        const onActionClick = jest.fn();
         const contextMenu = mount(<ContextMenu
             anchorEl={document.createElement("div")}
             onClose={jest.fn()}
-            {...{ actions, item }} />);
-
-        contextMenu.find(ListItem).at(0).simulate("click");
-        contextMenu.find(ListItem).at(1).simulate("click");
+            onActionClick={onActionClick}
+            actions={actions} />);
         contextMenu.find(ListItem).at(2).simulate("click");
-
-        expect(actions[0][0].onClick).toHaveBeenCalledWith(item);
-        expect(actions[0][1].onClick).toHaveBeenCalledWith(item);
-        expect(actions[1][0].onClick).toHaveBeenCalledWith(item);
+        expect(onActionClick).toHaveBeenCalledWith(actions[1][0]);
     });
 });
\ No newline at end of file
diff --git a/src/components/context-menu/context-menu.tsx b/src/components/context-menu/context-menu.tsx
index c86c517..7751be4 100644
--- a/src/components/context-menu/context-menu.tsx
+++ b/src/components/context-menu/context-menu.tsx
@@ -5,27 +5,26 @@ import * as React from "react";
 import { Popover, List, ListItem, ListItemIcon, ListItemText, Divider } from "@material-ui/core";
 import { DefaultTransformOrigin } from "../popover/helpers";
 
-export interface ContextMenuAction<T> {
+export interface ContextMenuAction {
     name: string;
     icon: string;
-    onClick: (item: T) => void;
 }
 
-export type ContextMenuActionGroup<T> = Array<ContextMenuAction<T>>;
+export type ContextMenuActionGroup = ContextMenuAction[];
 
 export interface ContextMenuProps<T> {
     anchorEl?: HTMLElement;
-    item?: T;
+    actions: ContextMenuActionGroup[];
+    onActionClick: (action: ContextMenuAction) => void;
     onClose: () => void;
-    actions: Array<ContextMenuActionGroup<T>>;
 }
 
 export default class ContextMenu<T> extends React.PureComponent<ContextMenuProps<T>> {
     render() {
-        const { anchorEl, onClose, actions, item } = this.props;
+        const { anchorEl, actions, onClose, onActionClick } = this.props;
         return <Popover
             anchorEl={anchorEl}
-            open={Boolean(anchorEl)}
+            open={!!anchorEl}
             onClose={onClose}
             transformOrigin={DefaultTransformOrigin}
             anchorOrigin={DefaultTransformOrigin}>
@@ -36,7 +35,7 @@ export default class ContextMenu<T> extends React.PureComponent<ContextMenuProps
                             <ListItem
                                 button
                                 key={actionIndex}
-                                onClick={() => item && action.onClick(item)}>
+                                onClick={() => onActionClick(action)}>
                                 <ListItemIcon>
                                     <i className={action.icon} />
                                 </ListItemIcon>
diff --git a/src/components/data-explorer/data-explorer-column.tsx b/src/components/data-explorer/data-explorer-column.tsx
deleted file mode 100644
index 62dc747..0000000
--- a/src/components/data-explorer/data-explorer-column.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { SortDirection } from "../../components/data-table/data-column";
-import { DataTableFilterItem } from "../../components/data-table-filters/data-table-filters";
-
-
-export interface DataExplorerColumn<T> {
-    name: string;
-    selected: boolean;
-    configurable?: boolean;
-    sortable?: boolean;
-    sortDirection?: SortDirection;
-    filterable?: boolean;
-    filters?: DataTableFilterItem[];
-    render: (item: T) => React.ReactElement<void>;
-    renderHeader?: () => React.ReactElement<void> | null;
-}
diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index 4fc9fb9..4486880 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -4,22 +4,22 @@
 
 import * as React from 'react';
 import { Grid, Paper, Toolbar } from '@material-ui/core';
-import ContextMenu, { ContextMenuActionGroup } from "../../components/context-menu/context-menu";
+import ContextMenu, { ContextMenuActionGroup, ContextMenuAction } from "../../components/context-menu/context-menu";
 import ColumnSelector from "../../components/column-selector/column-selector";
 import DataTable from "../../components/data-table/data-table";
 import { mockAnchorFromMouseEvent } from "../../components/popover/helpers";
 import { DataColumn, toggleSortDirection } from "../../components/data-table/data-column";
 import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
-import { DataExplorerColumn } from './data-explorer-column';
 
 interface DataExplorerProps<T> {
     items: T[];
-    columns: Array<DataExplorerColumn<T>>;
-    contextActions: Array<ContextMenuActionGroup<T>>;
+    columns: Array<DataColumn<T>>;
+    contextActions: ContextMenuActionGroup[];
     onRowClick: (item: T) => void;
-    onColumnToggle: (column: DataExplorerColumn<T>) => void;
-    onSortingToggle: (column: DataExplorerColumn<T>) => void;
-    onFiltersChange: (columns: DataExplorerColumn<T>) => void;
+    onColumnToggle: (column: DataColumn<T>) => void;
+    onContextAction: (action: ContextMenuAction, item: T) => void;
+    onSortToggle: (column: DataColumn<T>) => void;
+    onFiltersChange: (filters: DataTableFilterItem[], column: DataColumn<T>) => void;
 }
 
 interface DataExplorerState<T> {
@@ -37,63 +37,29 @@ class DataExplorer<T> extends React.Component<DataExplorerProps<T>, DataExplorer
     render() {
         return <Paper>
             <ContextMenu
-                {...this.state.contextMenu}
-                actions={this.contextActions}
+                anchorEl={this.state.contextMenu.anchorEl}
+                actions={this.props.contextActions}
+                onActionClick={this.callAction}
                 onClose={this.closeContextMenu} />
             <Toolbar>
                 <Grid container justify="flex-end">
                     <ColumnSelector
-                        columns={this.columns}
-                        onColumnToggle={this.toggleColumn} />
+                        columns={this.props.columns}
+                        onColumnToggle={this.props.onColumnToggle} />
                 </Grid>
             </Toolbar>
             <DataTable
-                columns={this.columns}
+                columns={this.props.columns}
                 items={this.props.items}
-                onRowClick={(_, row: T) => this.props.onRowClick(row)}
-                onRowContextMenu={this.openItemMenuOnRowClick} />
+                onRowClick={(_, item: T) => this.props.onRowClick(item)}
+                onRowContextMenu={this.openContextMenu}
+                onFiltersChange={this.props.onFiltersChange}
+                onSortToggle={this.props.onSortToggle} />
             <Toolbar />
         </Paper>;
     }
 
-    get columns(): Array<DataColumn<T>> {
-        return this.props.columns.map((column): DataColumn<T> => ({
-            configurable: column.configurable,
-            filters: column.filters,
-            name: column.name,
-            onFiltersChange: column.filterable ? this.changeFilters(column) : undefined,
-            onSortToggle: column.sortable ? this.toggleSort(column) : undefined,
-            render: column.render,
-            renderHeader: column.renderHeader,
-            selected: column.selected,
-            sortDirection: column.sortDirection
-        }));
-    }
-
-    get contextActions() {
-        return this.props.contextActions.map(actionGroup =>
-            actionGroup.map(action => ({
-                ...action,
-                onClick: (item: T) => {
-                    this.closeContextMenu();
-                    action.onClick(item);
-                }
-            })));
-    }
-
-    toggleColumn = (column: DataExplorerColumn<T>) => {
-        this.props.onColumnToggle(column);
-    }
-
-    toggleSort = (column: DataExplorerColumn<T>) => () => {
-        this.props.onSortingToggle(toggleSortDirection(column));
-    }
-
-    changeFilters = (column: DataExplorerColumn<T>) => (filters: DataTableFilterItem[]) => {
-        this.props.onFiltersChange({ ...column, filters });
-    }
-
-    openItemMenuOnRowClick = (event: React.MouseEvent<HTMLElement>, item: T) => {
+    openContextMenu = (event: React.MouseEvent<HTMLElement>, item: T) => {
         event.preventDefault();
         this.setState({
             contextMenu: {
@@ -103,19 +69,18 @@ class DataExplorer<T> extends React.Component<DataExplorerProps<T>, DataExplorer
         });
     }
 
-    openItemMenuOnActionsClick = (event: React.MouseEvent<HTMLElement>, item: T) => {
-        this.setState({
-            contextMenu: {
-                anchorEl: event.currentTarget,
-                item
-            }
-        });
-    }
-
     closeContextMenu = () => {
         this.setState({ contextMenu: {} });
     }
 
+    callAction = (action: ContextMenuAction) => {
+        const { item } = this.state.contextMenu;
+        this.closeContextMenu();
+        if (item) {
+            this.props.onContextAction(action, item);
+        }
+    }
+
 }
 
 export default DataExplorer;
diff --git a/src/components/data-table/data-column.ts b/src/components/data-table/data-column.ts
index 7ac568a..1ef7d98 100644
--- a/src/components/data-table/data-column.ts
+++ b/src/components/data-table/data-column.ts
@@ -10,24 +10,25 @@ export interface DataColumn<T> {
     configurable?: boolean;
     key?: React.Key;
     sortDirection?: SortDirection;
-    onSortToggle?: () => void;
     filters?: DataTableFilterItem[];
-    onFiltersChange?: (filters: DataTableFilterItem[]) => void;
     render: (item: T) => React.ReactElement<void>;
     renderHeader?: () => React.ReactElement<void> | null;
 }
 
-export type SortDirection = "asc" | "desc";
+export type SortDirection = "asc" | "desc" | "none";
 
 export const isColumnConfigurable = <T>(column: DataColumn<T>) => {
     return column.configurable === undefined || column.configurable;
 };
 
 export const toggleSortDirection = <T>(column: DataColumn<T>): DataColumn<T> => {
-    const sortDirection = column.sortDirection === undefined || column.sortDirection === "desc" ? "asc" : "desc";
-    return { ...column, sortDirection };
+    return column.sortDirection
+        ? column.sortDirection === "asc"
+            ? { ...column, sortDirection: "desc" }
+            : { ...column, sortDirection: "asc" }
+        : column;
 };
 
 export const resetSortDirection = <T>(column: DataColumn<T>): DataColumn<T> => {
-    return { ...column, sortDirection: undefined };
+    return column.sortDirection ? { ...column, sortDirection: "none" } : column;
 };
diff --git a/src/components/data-table/data-table.test.tsx b/src/components/data-table/data-table.test.tsx
index ad00280..115ca67 100644
--- a/src/components/data-table/data-table.test.tsx
+++ b/src/components/data-table/data-table.test.tsx
@@ -30,7 +30,13 @@ describe("<DataTable />", () => {
                 selected: false
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const dataTable = mount(<DataTable
+            columns={columns}
+            items={["item 1"]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(TableHead).find(TableCell)).toHaveLength(2);
     });
 
@@ -42,7 +48,13 @@ describe("<DataTable />", () => {
                 selected: true
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const dataTable = mount(<DataTable
+            columns={columns}
+            items={["item 1"]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(TableHead).find(TableCell).text()).toBe("Column 1");
     });
 
@@ -55,7 +67,13 @@ describe("<DataTable />", () => {
                 selected: true
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const dataTable = mount(<DataTable
+            columns={columns}
+            items={["item 1"]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(TableHead).find(TableCell).text()).toBe("Column Header");
     });
 
@@ -68,7 +86,13 @@ describe("<DataTable />", () => {
                 selected: true
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const dataTable = mount(<DataTable
+            columns={columns}
+            items={["item 1"]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(TableHead).find(TableCell).key()).toBe("column-1-key");
         expect(dataTable.find(TableBody).find(TableCell).key()).toBe("column-1-key");
     });
@@ -81,7 +105,13 @@ describe("<DataTable />", () => {
                 selected: true
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={[]} />);
+        const dataTable = mount(<DataTable
+            columns={columns}
+            items={[]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(Typography).text()).toBe("No items");
     });
 
@@ -98,7 +128,13 @@ describe("<DataTable />", () => {
                 selected: true
             }
         ];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const dataTable = mount(<DataTable 
+            columns={columns} 
+            items={["item 1"]}
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={jest.fn()} />);
         expect(dataTable.find(TableBody).find(Typography).text()).toBe("item 1");
         expect(dataTable.find(TableBody).find(Button).text()).toBe("item 1");
     });
@@ -107,14 +143,20 @@ describe("<DataTable />", () => {
         const columns: Array<DataColumn<string>> = [{
             name: "Column 1",
             sortDirection: "asc",
-            onSortToggle: jest.fn(),
             selected: true,
             render: (item) => <Typography>{item}</Typography>
         }];
-        const dataTable = mount(<DataTable columns={columns} items={["item 1"]} />);
+        const onSortToggle = jest.fn();
+        const dataTable = mount(<DataTable 
+            columns={columns} 
+            items={["item 1"]} 
+            onFiltersChange={jest.fn()}
+            onRowClick={jest.fn()}
+            onRowContextMenu={jest.fn()}
+            onSortToggle={onSortToggle}/>);
         expect(dataTable.find(TableSortLabel).prop("active")).toBeTruthy();
         dataTable.find(TableSortLabel).at(0).simulate("click");
-        expect(columns[0].onSortToggle).toHaveBeenCalled();
+        expect(onSortToggle).toHaveBeenCalledWith(columns[0]);
     });
 
 
diff --git a/src/components/data-table/data-table.tsx b/src/components/data-table/data-table.tsx
index 26f6faf..e86113e 100644
--- a/src/components/data-table/data-table.tsx
+++ b/src/components/data-table/data-table.tsx
@@ -4,66 +4,33 @@
 
 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";
+import { DataColumn, SortDirection } from './data-column';
+import DataTableFilters, { DataTableFilterItem } from "../data-table-filters/data-table-filters";
 
 export type DataColumns<T> = Array<DataColumn<T>>;
 
 export interface DataTableProps<T> {
     items: T[];
     columns: DataColumns<T>;
-    onRowClick?: (event: React.MouseEvent<HTMLTableRowElement>, item: T) => void;
-    onRowContextMenu?: (event: React.MouseEvent<HTMLTableRowElement>, item: T) => void;
+    onRowClick: (event: React.MouseEvent<HTMLTableRowElement>, item: T) => void;
+    onRowContextMenu: (event: React.MouseEvent<HTMLTableRowElement>, item: T) => void;
+    onSortToggle: (column: DataColumn<T>) => void;
+    onFiltersChange: (filters: DataTableFilterItem[], column: DataColumn<T>) => void;
 }
 
 class DataTable<T> extends React.Component<DataTableProps<T> & WithStyles<CssRules>> {
     render() {
-        const { items, columns, classes, onRowClick, onRowContextMenu } = this.props;
+        const { items, classes } = this.props;
         return <div className={classes.tableContainer}>
             {items.length > 0 ?
                 <Table>
                     <TableHead>
                         <TableRow>
-                            {columns
-                                .filter(column => column.selected)
-                                .map(({ name, renderHeader, key, sortDirection, onSortToggle, filters, onFiltersChange }, index) =>
-                                    <TableCell key={key || index}>
-                                        {renderHeader ?
-                                            renderHeader() :
-                                            filters ?
-                                                <DataTableFilters
-                                                    name={`${name} filters`}
-                                                    onChange={onFiltersChange}
-                                                    filters={filters}>
-                                                    {name}
-                                                </DataTableFilters> :
-                                                <TableSortLabel
-                                                    active={!!sortDirection}
-                                                    direction={sortDirection}
-                                                    onClick={() => onSortToggle && onSortToggle()}>
-                                                    {name}
-                                                </TableSortLabel>}
-                                    </TableCell>
-                                )}
+                            {this.mapVisibleColumns(this.renderHeadCell)}
                         </TableRow>
                     </TableHead>
                     <TableBody className={classes.tableBody}>
-                        {items
-                            .map((item, index) =>
-                                <TableRow
-                                    hover
-                                    key={index}
-                                    onClick={event => onRowClick && onRowClick(event, item)}
-                                    onContextMenu={event => onRowContextMenu && onRowContextMenu(event, item)}>
-                                    {columns
-                                        .filter(column => column.selected)
-                                        .map((column, index) => (
-                                            <TableCell key={column.key || index}>
-                                                {column.render(item)}
-                                            </TableCell>
-                                        ))}
-                                </TableRow>
-                            )}
+                        {items.map(this.renderBodyRow)}
                     </TableBody>
                 </Table> : <Typography
                     className={classes.noItemsInfo}
@@ -73,6 +40,56 @@ class DataTable<T> extends React.Component<DataTableProps<T> & WithStyles<CssRul
                 </Typography>}
         </div>;
     }
+
+    renderHeadCell = (column: DataColumn<T>, index: number) => {
+        const { name, key, renderHeader, filters, sortDirection } = column;
+        const { onSortToggle, onFiltersChange } = this.props;
+        return <TableCell key={key || index}>
+            {renderHeader ?
+                renderHeader() :
+                filters
+                    ? <DataTableFilters
+                        name={`${name} filters`}
+                        onChange={filters =>
+                            onFiltersChange &&
+                            onFiltersChange(filters, column)}
+                        filters={filters}>
+                        {name}
+                    </DataTableFilters>
+                    : sortDirection
+                        ? <TableSortLabel
+                            active={sortDirection !== "none"}
+                            direction={sortDirection !== "none" ? sortDirection : undefined}
+                            onClick={() =>
+                                onSortToggle &&
+                                onSortToggle(column)}>
+                            {name}
+                        </TableSortLabel>
+                        : <span>
+                            {name}
+                        </span>}
+        </TableCell>;
+    }
+
+    renderBodyRow = (item: T, index: number) => {
+        const { columns, onRowClick, onRowContextMenu } = this.props;
+        return <TableRow
+            hover
+            key={index}
+            onClick={event => onRowClick && onRowClick(event, item)}
+            onContextMenu={event => onRowContextMenu && onRowContextMenu(event, item)}>
+            {this.mapVisibleColumns((column, index) => (
+                <TableCell key={column.key || index}>
+                    {column.render(item)}
+                </TableCell>
+            ))}
+        </TableRow>;
+    }
+
+    mapVisibleColumns = (fn: (column: DataColumn<T>, index: number) => React.ReactElement<any>) => {
+        return this.props.columns.filter(column => column.selected).map(fn);
+    }
+
 }
 
 type CssRules = "tableBody" | "tableContainer" | "noItemsInfo";
diff --git a/src/views-components/project-explorer/project-explorer.tsx b/src/views-components/project-explorer/project-explorer.tsx
index eee0033..3fac6df 100644
--- a/src/views-components/project-explorer/project-explorer.tsx
+++ b/src/views-components/project-explorer/project-explorer.tsx
@@ -3,11 +3,13 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { DataExplorerColumn } from '../../components/data-explorer/data-explorer-column';
 import { ProjectExplorerItem } from './project-explorer-item';
 import { Grid, Typography } from '@material-ui/core';
 import { formatDate, formatFileSize } from '../../common/formatters';
 import DataExplorer from '../../components/data-explorer/data-explorer';
+import { DataColumn, toggleSortDirection, resetSortDirection } from '../../components/data-table/data-column';
+import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
+import { ContextMenuAction } from '../../components/context-menu/context-menu';
 
 export interface ProjectExplorerContextActions {
     onAddToFavourite: (item: ProjectExplorerItem) => void;
@@ -24,7 +26,7 @@ interface ProjectExplorerProps {
 }
 
 interface ProjectExplorerState {
-    columns: Array<DataExplorerColumn<ProjectExplorerItem>>;
+    columns: Array<DataColumn<ProjectExplorerItem>>;
 }
 
 class ProjectExplorer extends React.Component<ProjectExplorerProps, ProjectExplorerState> {
@@ -33,12 +35,10 @@ class ProjectExplorer extends React.Component<ProjectExplorerProps, ProjectExplo
             name: "Name",
             selected: true,
             sortDirection: "asc",
-            sortable: true,
             render: renderName
         }, {
             name: "Status",
             selected: true,
-            filterable: true,
             filters: [{
                 name: "In progress",
                 selected: true
@@ -50,7 +50,6 @@ class ProjectExplorer extends React.Component<ProjectExplorerProps, ProjectExplo
         }, {
             name: "Type",
             selected: true,
-            filterable: true,
             filters: [{
                 name: "Collection",
                 selected: true
@@ -66,43 +65,36 @@ class ProjectExplorer extends React.Component<ProjectExplorerProps, ProjectExplo
         }, {
             name: "File size",
             selected: true,
+            sortDirection: "none",
             render: item => renderFileSize(item.fileSize)
         }, {
             name: "Last modified",
             selected: true,
-            sortable: true,
             render: item => renderDate(item.lastModified)
         }]
     };
 
     contextMenuActions = [[{
         icon: "fas fa-users fa-fw",
-        name: "Share",
-        onClick: console.log
+        name: "Share"
     }, {
         icon: "fas fa-sign-out-alt fa-fw",
-        name: "Move to",
-        onClick: console.log
+        name: "Move to"
     }, {
         icon: "fas fa-star fa-fw",
-        name: "Add to favourite",
-        onClick: console.log
+        name: "Add to favourite"
     }, {
         icon: "fas fa-edit fa-fw",
-        name: "Rename",
-        onClick: console.log
+        name: "Rename"
     }, {
         icon: "fas fa-copy fa-fw",
-        name: "Make a copy",
-        onClick: console.log
+        name: "Make a copy"
     }, {
         icon: "fas fa-download fa-fw",
-        name: "Download",
-        onClick: console.log
+        name: "Download"
     }], [{
         icon: "fas fa-trash-alt fa-fw",
-        name: "Remove",
-        onClick: console.log
+        name: "Remove"
     }
     ]];
 
@@ -111,10 +103,45 @@ class ProjectExplorer extends React.Component<ProjectExplorerProps, ProjectExplo
             items={this.props.items}
             columns={this.state.columns}
             contextActions={this.contextMenuActions}
-            onColumnToggle={console.log}
-            onFiltersChange={console.log}
+            onColumnToggle={this.toggleColumn}
+            onFiltersChange={this.changeFilters}
             onRowClick={console.log}
-            onSortingToggle={console.log} />;
+            onSortToggle={this.toggleSort}
+            onContextAction={this.executeAction} />;
+    }
+
+    toggleColumn = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
+        this.setState({
+            columns: this.state.columns.map(column =>
+                column.name === toggledColumn.name
+                    ? { ...column, selected: !column.selected }
+                    : column
+            )
+        });
+    }
+
+    toggleSort = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
+        this.setState({
+            columns: this.state.columns.map(column =>
+                column.name === toggledColumn.name
+                    ? toggleSortDirection(column)
+                    : resetSortDirection(column)
+            )
+        });
+    }
+
+    changeFilters = (filters: DataTableFilterItem[], updatedColumn: DataColumn<ProjectExplorerItem>) => {
+        this.setState({
+            columns: this.state.columns.map(column =>
+                column.name === updatedColumn.name
+                    ? { ...column, filters }
+                    : column
+            )
+        });
+    }
+
+    executeAction = (action: ContextMenuAction, item: ProjectExplorerItem) => {
+        alert(`Executing ${action.name} on ${item.name}`);
     }
 }
 

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list