X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/79ea5270b83bbfef8e7da569a60fcda5ecf34b75..b22b921c05816744f83e2a726d93705b3b8f0599:/src/store/project-panel/project-panel-middleware.ts diff --git a/src/store/project-panel/project-panel-middleware.ts b/src/store/project-panel/project-panel-middleware.ts new file mode 100644 index 00000000..e72b6c1b --- /dev/null +++ b/src/store/project-panel/project-panel-middleware.ts @@ -0,0 +1,128 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { Middleware } from "redux"; +import actions from "../../store/data-explorer/data-explorer-action"; +import { PROJECT_PANEL_ID, columns, ProjectPanelFilter, ProjectPanelColumnNames } from "../../views/project-panel/project-panel"; +import { groupsService } from "../../services/services"; +import { RootState } from "../../store/store"; +import { getDataExplorer, DataExplorerState } from "../../store/data-explorer/data-explorer-reducer"; +import { resourceToDataItem, ProjectPanelItem } from "../../views/project-panel/project-panel-item"; +import FilterBuilder from "../../common/api/filter-builder"; +import { DataColumns } from "../../components/data-table/data-table"; +import { ProcessResource } from "../../models/process"; +import { CollectionResource } from "../../models/collection"; +import OrderBuilder from "../../common/api/order-builder"; +import { GroupContentsResource, GroupContentsResourcePrefix } from "../../services/groups-service/groups-service"; +import { SortDirection } from "../../components/data-table/data-column"; + +export const projectPanelMiddleware: Middleware = store => next => { + next(actions.SET_COLUMNS({ id: PROJECT_PANEL_ID, columns })); + + return action => { + + const handleProjectPanelAction = (handler: (data: T) => void) => + (data: T) => { + next(action); + if (data.id === PROJECT_PANEL_ID) { + handler(data); + } + }; + + actions.match(action, { + SET_PAGE: handleProjectPanelAction(() => { + store.dispatch(actions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + }), + SET_ROWS_PER_PAGE: handleProjectPanelAction(() => { + store.dispatch(actions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + }), + SET_FILTERS: handleProjectPanelAction(() => { + store.dispatch(actions.RESET_PAGINATION({ id: PROJECT_PANEL_ID })); + store.dispatch(actions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + }), + TOGGLE_SORT: handleProjectPanelAction(() => { + store.dispatch(actions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + }), + SET_SEARCH_VALUE: handleProjectPanelAction(() => { + store.dispatch(actions.RESET_PAGINATION({ id: PROJECT_PANEL_ID })); + store.dispatch(actions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + }), + REQUEST_ITEMS: handleProjectPanelAction(() => { + const state = store.getState() as RootState; + const dataExplorer = getDataExplorer(state.dataExplorer, PROJECT_PANEL_ID); + const columns = dataExplorer.columns as DataColumns; + const typeFilters = getColumnFilters(columns, ProjectPanelColumnNames.Type); + const statusFilters = getColumnFilters(columns, ProjectPanelColumnNames.Status); + const sortColumn = dataExplorer.columns.find(({ sortDirection }) => Boolean(sortDirection && sortDirection !== "none")); + const sortDirection = sortColumn && sortColumn.sortDirection === SortDirection.Asc ? SortDirection.Asc : SortDirection.Desc; + if (typeFilters.length > 0) { + 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) + : OrderBuilder.create(), + filters: FilterBuilder + .create() + .concat(FilterBuilder + .create() + .addIsA("uuid", typeFilters.map(f => f.type))) + .concat(FilterBuilder + .create(GroupContentsResourcePrefix.Process) + .addIn("state", statusFilters.map(f => f.type))) + .concat(getSearchFilter(dataExplorer.searchValue)) + }) + .then(response => { + store.dispatch(actions.SET_ITEMS({ + id: PROJECT_PANEL_ID, + items: response.items.map(resourceToDataItem), + itemsAvailable: response.itemsAvailable, + page: Math.floor(response.offset / response.limit), + rowsPerPage: response.limit + })); + }); + } else { + store.dispatch(actions.SET_ITEMS({ + id: PROJECT_PANEL_ID, + items: [], + itemsAvailable: 0, + page: 0, + rowsPerPage: dataExplorer.rowsPerPage + })); + } + }), + default: () => next(action) + }); + }; +}; + +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: SortDirection) => + [ + OrderBuilder.create(GroupContentsResourcePrefix.Collection), + OrderBuilder.create(GroupContentsResourcePrefix.Process), + OrderBuilder.create(GroupContentsResourcePrefix.Project) + ].reduce((acc, b) => + acc.concat(direction === SortDirection.Asc + ? b.addAsc(attribute) + : b.addDesc(attribute)), OrderBuilder.create()); + +const getSearchFilter = (searchValue: string) => + searchValue + ? [ + FilterBuilder.create(GroupContentsResourcePrefix.Collection), + FilterBuilder.create(GroupContentsResourcePrefix.Process), + FilterBuilder.create(GroupContentsResourcePrefix.Project)] + .reduce((acc, b) => + acc.concat(b.addILike("name", searchValue)), FilterBuilder.create()) + : FilterBuilder.create(); + +