From 64ccecc473cee79d6c929a75d97c2411f6b038b3 Mon Sep 17 00:00:00 2001 From: Daniel Kos Date: Wed, 15 Aug 2018 18:26:21 +0200 Subject: [PATCH] Simplify finding sorting columns and filters Arvados-DCO-1.1-Signed-off-by: Daniel Kos --- .../data-explorer/data-explorer.tsx | 14 +-- src/components/data-table/data-column.ts | 6 +- .../data-explorer-middleware-service.ts | 7 ++ .../data-explorer-middleware.test.ts | 5 + .../favorite-panel-middleware-service.ts | 68 ++++++------- .../project-panel-middleware-service.ts | 97 +++++++++---------- src/views/favorite-panel/favorite-panel.tsx | 10 +- src/views/project-panel/project-panel.tsx | 8 ++ 8 files changed, 117 insertions(+), 98 deletions(-) diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx index 2811bd4d..681caa94 100644 --- a/src/components/data-explorer/data-explorer.tsx +++ b/src/components/data-explorer/data-explorer.tsx @@ -7,7 +7,7 @@ import { Grid, Paper, Toolbar, StyleRulesCallback, withStyles, WithStyles, Table import MoreVertIcon from "@material-ui/icons/MoreVert"; import { ColumnSelector } from "../column-selector/column-selector"; import { DataTable, DataColumns } from "../data-table/data-table"; -import { DataColumn } from "../data-table/data-column"; +import { DataColumn, SortDirection } from "../data-table/data-column"; import { DataTableFilterItem } from '../data-table-filters/data-table-filters'; import { SearchInput } from '../search-input/search-input'; import { ArvadosTheme } from "~/common/custom-theme"; @@ -68,10 +68,10 @@ type DataExplorerProps = DataExplorerDataProps & DataExplorerActionProps extends React.Component> { render() { - const { - columns, onContextMenu, onFiltersChange, onSortToggle, extractKey, - rowsPerPage, rowsPerPageOptions, onColumnToggle, searchValue, onSearch, - items, itemsAvailable, onRowClick, onRowDoubleClick, defaultIcon, defaultMessages, classes + const { + columns, onContextMenu, onFiltersChange, onSortToggle, extractKey, + rowsPerPage, rowsPerPageOptions, onColumnToggle, searchValue, onSearch, + items, itemsAvailable, onRowClick, onRowDoubleClick, defaultIcon, defaultMessages, classes } = this.props; return
{ items.length > 0 ? ( @@ -111,7 +111,7 @@ export const DataExplorer = withStyles(styles)( ) : ( - { + key?: React.Key; name: string; selected: boolean; configurable: boolean; - key?: React.Key; - sortDirection?: SortDirection; - filters?: F[]; + sortDirection: SortDirection; + filters: F[]; render: (item: T) => React.ReactElement; renderHeader?: () => React.ReactElement; width?: string; diff --git a/src/store/data-explorer/data-explorer-middleware-service.ts b/src/store/data-explorer/data-explorer-middleware-service.ts index 14be4ea7..7c64020e 100644 --- a/src/store/data-explorer/data-explorer-middleware-service.ts +++ b/src/store/data-explorer/data-explorer-middleware-service.ts @@ -4,6 +4,8 @@ import { Dispatch, MiddlewareAPI } from "redux"; import { RootState } from "../store"; +import { DataColumns } from "~/components/data-table/data-table"; +import { DataTableFilterItem } from "~/components/data-table-filters/data-table-filters"; export abstract class DataExplorerMiddlewareService { protected readonly id: string; @@ -16,5 +18,10 @@ export abstract class DataExplorerMiddlewareService { return this.id; } + public getColumnFilters(columns: DataColumns, columnName: string): F[] { + const column = columns.find(c => c.name === columnName); + return column ? column.filters.filter(f => f.selected) : []; + } + abstract requestItems(api: MiddlewareAPI): void; } diff --git a/src/store/data-explorer/data-explorer-middleware.test.ts b/src/store/data-explorer/data-explorer-middleware.test.ts index d93ccbf4..2a88817c 100644 --- a/src/store/data-explorer/data-explorer-middleware.test.ts +++ b/src/store/data-explorer/data-explorer-middleware.test.ts @@ -7,6 +7,7 @@ import { dataExplorerMiddleware } from "./data-explorer-middleware"; import { MiddlewareAPI } from "redux"; import { DataColumns } from "~/components/data-table/data-table"; import { dataExplorerActions } from "./data-explorer-action"; +import { SortDirection } from "~/components/data-table/data-column"; describe("DataExplorerMiddleware", () => { @@ -18,6 +19,8 @@ describe("DataExplorerMiddleware", () => { name: "Column", selected: true, configurable: false, + sortDirection: SortDirection.NONE, + filters: [], render: jest.fn() }], requestItems: jest.fn(), @@ -44,6 +47,8 @@ describe("DataExplorerMiddleware", () => { name: "Column", selected: true, configurable: false, + sortDirection: SortDirection.NONE, + filters: [], render: jest.fn() }], requestItems: jest.fn(), diff --git a/src/store/favorite-panel/favorite-panel-middleware-service.ts b/src/store/favorite-panel/favorite-panel-middleware-service.ts index 76a10a71..1c2f0622 100644 --- a/src/store/favorite-panel/favorite-panel-middleware-service.ts +++ b/src/store/favorite-panel/favorite-panel-middleware-service.ts @@ -25,10 +25,8 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic requestItems(api: MiddlewareAPI) { const dataExplorer = api.getState().dataExplorer[this.getId()]; const columns = dataExplorer.columns as DataColumns; - const sortColumn = dataExplorer.columns.find( - c => c.sortDirection !== undefined && c.sortDirection !== "none" - ); - const typeFilters = getColumnFilters(columns, FavoritePanelColumnNames.TYPE); + const sortColumn = dataExplorer.columns.find(c => c.sortDirection !== SortDirection.NONE); + const typeFilters = this.getColumnFilters(columns, FavoritePanelColumnNames.TYPE); const linkOrder = new OrderBuilder(); const contentOrder = new OrderBuilder(); @@ -45,39 +43,33 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic .addOrder(direction, "name", GroupContentsResourcePrefix.PROJECT); } - if (typeFilters.length > 0) { - this.services.favoriteService - .list(this.services.authService.getUuid()!, { - limit: dataExplorer.rowsPerPage, - offset: dataExplorer.page * dataExplorer.rowsPerPage, - linkOrder: linkOrder.getOrder(), - contentOrder: contentOrder.getOrder(), - filters: new FilterBuilder() - .addIsA("headUuid", typeFilters.map(filter => filter.type)) - .addILike("name", dataExplorer.searchValue) - .getFilters() - }) - .then(response => { - api.dispatch(favoritePanelActions.SET_ITEMS({ - items: response.items.map(resourceToDataItem), - itemsAvailable: response.itemsAvailable, - page: Math.floor(response.offset / response.limit), - rowsPerPage: response.limit - })); - api.dispatch(checkPresenceInFavorites(response.items.map(item => item.uuid))); - }); - } else { - api.dispatch(favoritePanelActions.SET_ITEMS({ - items: [], - itemsAvailable: 0, - page: 0, - rowsPerPage: dataExplorer.rowsPerPage - })); - } + this.services.favoriteService + .list(this.services.authService.getUuid()!, { + limit: dataExplorer.rowsPerPage, + offset: dataExplorer.page * dataExplorer.rowsPerPage, + linkOrder: linkOrder.getOrder(), + contentOrder: contentOrder.getOrder(), + filters: new FilterBuilder() + .addIsA("headUuid", typeFilters.map(filter => filter.type)) + .addILike("name", dataExplorer.searchValue) + .getFilters() + }) + .then(response => { + api.dispatch(favoritePanelActions.SET_ITEMS({ + items: response.items.map(resourceToDataItem), + itemsAvailable: response.itemsAvailable, + page: Math.floor(response.offset / response.limit), + rowsPerPage: response.limit + })); + api.dispatch(checkPresenceInFavorites(response.items.map(item => item.uuid))); + }) + .catch(() => { + api.dispatch(favoritePanelActions.SET_ITEMS({ + items: [], + itemsAvailable: 0, + page: 0, + rowsPerPage: dataExplorer.rowsPerPage + })); + }); } } - -const getColumnFilters = (columns: DataColumns, columnName: string) => { - const column = columns.find(c => c.name === columnName); - return column && column.filters ? column.filters.filter(f => f.selected) : []; -}; diff --git a/src/store/project-panel/project-panel-middleware-service.ts b/src/store/project-panel/project-panel-middleware-service.ts index e46ef944..663add3e 100644 --- a/src/store/project-panel/project-panel-middleware-service.ts +++ b/src/store/project-panel/project-panel-middleware-service.ts @@ -26,56 +26,53 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService const state = api.getState(); const dataExplorer = state.dataExplorer[this.getId()]; const columns = dataExplorer.columns as DataColumns; - const typeFilters = getColumnFilters(columns, ProjectPanelColumnNames.TYPE); - const statusFilters = getColumnFilters(columns, ProjectPanelColumnNames.STATUS); - const sortColumn = dataExplorer.columns.find(c => c.sortDirection !== undefined && c.sortDirection !== "none"); - const sortDirection = sortColumn && sortColumn.sortDirection === SortDirection.ASC ? OrderDirection.ASC : OrderDirection.DESC; - if (typeFilters.length > 0) { - this.services.groupsService - .contents(state.projects.currentItemId, { - limit: dataExplorer.rowsPerPage, - offset: dataExplorer.page * dataExplorer.rowsPerPage, - order: sortColumn - ? sortColumn.name === ProjectPanelColumnNames.NAME - ? getOrder("name", sortDirection) - : getOrder("createdAt", sortDirection) - : "", - filters: new FilterBuilder() - .addIsA("uuid", typeFilters.map(f => f.type)) - .addIn("state", statusFilters.map(f => f.type), GroupContentsResourcePrefix.PROCESS) - .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.COLLECTION) - .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROCESS) - .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROJECT) - .getFilters() - }) - .then(response => { - api.dispatch(projectPanelActions.SET_ITEMS({ - items: response.items.map(resourceToDataItem), - itemsAvailable: response.itemsAvailable, - page: Math.floor(response.offset / response.limit), - rowsPerPage: response.limit - })); - api.dispatch(checkPresenceInFavorites(response.items.map(item => item.uuid))); - }); - } else { - api.dispatch(projectPanelActions.SET_ITEMS({ - items: [], - itemsAvailable: 0, - page: 0, - rowsPerPage: dataExplorer.rowsPerPage - })); + const typeFilters = this.getColumnFilters(columns, ProjectPanelColumnNames.TYPE); + const statusFilters = this.getColumnFilters(columns, ProjectPanelColumnNames.STATUS); + const sortColumn = dataExplorer.columns.find(c => c.sortDirection !== SortDirection.NONE); + + const order = new OrderBuilder(); + + if (sortColumn) { + const sortDirection = sortColumn && sortColumn.sortDirection === SortDirection.ASC + ? OrderDirection.ASC + : OrderDirection.DESC; + + const columnName = sortColumn && sortColumn.name === ProjectPanelColumnNames.NAME ? "name" : "createdAt"; + order + .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.COLLECTION) + .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.PROCESS) + .addOrder(sortDirection, columnName, GroupContentsResourcePrefix.PROJECT); } + + this.services.groupsService + .contents(state.projects.currentItemId, { + limit: dataExplorer.rowsPerPage, + offset: dataExplorer.page * dataExplorer.rowsPerPage, + order: order.getOrder(), + filters: new FilterBuilder() + .addIsA("uuid", typeFilters.map(f => f.type)) + .addIn("state", statusFilters.map(f => f.type), GroupContentsResourcePrefix.PROCESS) + .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.COLLECTION) + .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROCESS) + .addILike("name", dataExplorer.searchValue, GroupContentsResourcePrefix.PROJECT) + .getFilters() + }) + .then(response => { + api.dispatch(projectPanelActions.SET_ITEMS({ + items: response.items.map(resourceToDataItem), + itemsAvailable: response.itemsAvailable, + page: Math.floor(response.offset / response.limit), + rowsPerPage: response.limit + })); + api.dispatch(checkPresenceInFavorites(response.items.map(item => item.uuid))); + }) + .catch(() => { + api.dispatch(projectPanelActions.SET_ITEMS({ + items: [], + itemsAvailable: 0, + page: 0, + rowsPerPage: dataExplorer.rowsPerPage + })); + }); } } - -const getColumnFilters = (columns: DataColumns, columnName: string) => { - const column = columns.find(c => c.name === columnName); - return column && column.filters ? column.filters.filter(f => f.selected) : []; -}; - -const getOrder = (attribute: "name" | "createdAt", direction: OrderDirection) => - new OrderBuilder() - .addOrder(direction, attribute, GroupContentsResourcePrefix.COLLECTION) - .addOrder(direction, attribute, GroupContentsResourcePrefix.PROCESS) - .addOrder(direction, attribute, GroupContentsResourcePrefix.PROJECT) - .getOrder(); diff --git a/src/views/favorite-panel/favorite-panel.tsx b/src/views/favorite-panel/favorite-panel.tsx index 618f0aba..125ea27d 100644 --- a/src/views/favorite-panel/favorite-panel.tsx +++ b/src/views/favorite-panel/favorite-panel.tsx @@ -51,6 +51,7 @@ export const columns: DataColumns = [ selected: true, configurable: true, sortDirection: SortDirection.ASC, + filters: [], render: renderName, width: "450px" }, @@ -58,6 +59,7 @@ export const columns: DataColumns = [ name: "Status", selected: true, configurable: true, + sortDirection: SortDirection.NONE, filters: [ { name: ContainerRequestState.COMMITTED, @@ -82,6 +84,7 @@ export const columns: DataColumns = [ name: FavoritePanelColumnNames.TYPE, selected: true, configurable: true, + sortDirection: SortDirection.NONE, filters: [ { name: resourceLabel(ResourceKind.COLLECTION), @@ -106,6 +109,8 @@ export const columns: DataColumns = [ name: FavoritePanelColumnNames.OWNER, selected: true, configurable: true, + sortDirection: SortDirection.NONE, + filters: [], render: item => renderOwner(item.owner), width: "200px" }, @@ -113,6 +118,8 @@ export const columns: DataColumns = [ name: FavoritePanelColumnNames.FILE_SIZE, selected: true, configurable: true, + sortDirection: SortDirection.NONE, + filters: [], render: item => renderFileSize(item.fileSize), width: "50px" }, @@ -121,6 +128,7 @@ export const columns: DataColumns = [ selected: true, configurable: true, sortDirection: SortDirection.NONE, + filters: [], render: item => renderDate(item.lastModified), width: "150px" } @@ -151,7 +159,7 @@ export const FavoritePanel = withStyles(styles)( onRowClick={this.props.onItemClick} onRowDoubleClick={this.props.onItemDoubleClick} onContextMenu={this.props.onContextMenu} - extractKey={(item: FavoritePanelItem) => item.uuid} + extractKey={(item: FavoritePanelItem) => item.uuid} defaultIcon={FavoriteIcon} defaultMessages={['Your favorites list is empty.']}/> ; diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index e9179a11..0f958d2c 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -56,6 +56,7 @@ export const columns: DataColumns = [ selected: true, configurable: true, sortDirection: SortDirection.ASC, + filters: [], render: renderName, width: "450px" }, @@ -63,6 +64,7 @@ export const columns: DataColumns = [ name: "Status", selected: true, configurable: true, + sortDirection: SortDirection.NONE, filters: [ { name: ContainerRequestState.COMMITTED, @@ -87,6 +89,7 @@ export const columns: DataColumns = [ name: ProjectPanelColumnNames.TYPE, selected: true, configurable: true, + sortDirection: SortDirection.NONE, filters: [ { name: resourceLabel(ResourceKind.COLLECTION), @@ -111,6 +114,8 @@ export const columns: DataColumns = [ name: ProjectPanelColumnNames.OWNER, selected: true, configurable: true, + sortDirection: SortDirection.NONE, + filters: [], render: item => renderOwner(item.owner), width: "200px" }, @@ -118,6 +123,8 @@ export const columns: DataColumns = [ name: ProjectPanelColumnNames.FILE_SIZE, selected: true, configurable: true, + sortDirection: SortDirection.NONE, + filters: [], render: item => renderFileSize(item.fileSize), width: "50px" }, @@ -126,6 +133,7 @@ export const columns: DataColumns = [ selected: true, configurable: true, sortDirection: SortDirection.NONE, + filters: [], render: item => renderDate(item.lastModified), width: "150px" } -- 2.30.2