From d83c6fd363307c0255b4f3225f57214f5a608199 Mon Sep 17 00:00:00 2001 From: Michal Klobukowski Date: Tue, 11 Dec 2018 15:26:50 +0100 Subject: [PATCH] Set up data explorer for group details panel Feature #14505 Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski --- src/routes/route-change-handlers.ts | 3 + .../group-details-panel-actions.ts | 20 +++++ .../group-details-panel-middleware-service.ts | 79 +++++++++++++++++++ src/store/store.ts | 6 ++ src/store/workbench/workbench-actions.ts | 8 ++ 5 files changed, 116 insertions(+) create mode 100644 src/store/group-details-panel/group-details-panel-actions.ts create mode 100644 src/store/group-details-panel/group-details-panel-middleware-service.ts diff --git a/src/routes/route-change-handlers.ts b/src/routes/route-change-handlers.ts index cbcc065b..cbfbfd38 100644 --- a/src/routes/route-change-handlers.ts +++ b/src/routes/route-change-handlers.ts @@ -35,6 +35,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => { const myAccountMatch = Routes.matchMyAccountRoute(pathname); const userMatch = Routes.matchUsersRoute(pathname); const groupsMatch = Routes.matchGroupsRoute(pathname); + const groupDetailsMatch = Routes.matchGroupDetailsRoute(pathname); if (projectMatch) { store.dispatch(WorkbenchActions.loadProject(projectMatch.params.id)); @@ -76,5 +77,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => { store.dispatch(WorkbenchActions.loadUsers); } else if (groupsMatch) { store.dispatch(WorkbenchActions.loadGroupsPanel); + } else if (groupDetailsMatch) { + store.dispatch(WorkbenchActions.loadGroupDetailsPanel(groupDetailsMatch.params.id)); } }; diff --git a/src/store/group-details-panel/group-details-panel-actions.ts b/src/store/group-details-panel/group-details-panel-actions.ts new file mode 100644 index 00000000..be134dd5 --- /dev/null +++ b/src/store/group-details-panel/group-details-panel-actions.ts @@ -0,0 +1,20 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { bindDataExplorerActions } from '~/store/data-explorer/data-explorer-action'; +import { Dispatch } from 'redux'; +import { propertiesActions } from '~/store/properties/properties-actions'; +import { getProperty } from '~/store/properties/properties'; + +export const GROUP_DETAILS_PANEL_ID = 'groupDetailsPanel'; + +export const GroupDetailsPanelActions = bindDataExplorerActions(GROUP_DETAILS_PANEL_ID); + +export const loadGroupDetailsPanel = (groupUuid: string) => + (dispatch: Dispatch) => { + dispatch(propertiesActions.SET_PROPERTY({ key: GROUP_DETAILS_PANEL_ID, value: groupUuid })); + dispatch(GroupDetailsPanelActions.REQUEST_ITEMS()); + }; + +export const getCurrentGroupDetailsPanelUuid = getProperty(GROUP_DETAILS_PANEL_ID); diff --git a/src/store/group-details-panel/group-details-panel-middleware-service.ts b/src/store/group-details-panel/group-details-panel-middleware-service.ts new file mode 100644 index 00000000..a318696d --- /dev/null +++ b/src/store/group-details-panel/group-details-panel-middleware-service.ts @@ -0,0 +1,79 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { Dispatch, MiddlewareAPI } from "redux"; +import { DataExplorerMiddlewareService, listResultsToDataExplorerItemsMeta } from "~/store/data-explorer/data-explorer-middleware-service"; +import { RootState } from "~/store/store"; +import { ServiceRepository } from "~/services/services"; +import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions'; +import { getDataExplorer } from "~/store/data-explorer/data-explorer-reducer"; +import { FilterBuilder } from '~/services/api/filter-builder'; +import { updateResources } from '~/store/resources/resources-actions'; +import { getCurrentGroupDetailsPanelUuid, GroupDetailsPanelActions } from '~/store/group-details-panel/group-details-panel-actions'; +import { LinkClass } from '~/models/link'; + +export class GroupDetailsPanelMiddlewareService extends DataExplorerMiddlewareService { + + constructor(private services: ServiceRepository, id: string) { + super(id); + } + + async requestItems(api: MiddlewareAPI) { + + const dataExplorer = getDataExplorer(api.getState().dataExplorer, this.getId()); + const groupUuid = getCurrentGroupDetailsPanelUuid(api.getState().properties); + + if (!dataExplorer || !groupUuid) { + + api.dispatch(groupsDetailsPanelDataExplorerIsNotSet()); + + } else { + + try { + + const permissions = await this.services.permissionService.list({ + + filters: new FilterBuilder() + .addEqual('tailUuid', groupUuid) + .addEqual('linkClass', LinkClass.PERMISSION) + .getFilters() + + }); + + api.dispatch(updateResources(permissions.items)); + + api.dispatch(GroupDetailsPanelActions.SET_ITEMS({ + ...listResultsToDataExplorerItemsMeta(permissions), + items: permissions.items.map(item => item.uuid), + })); + + const users = await this.services.userService.list({ + + filters: new FilterBuilder() + .addIn('uuid', permissions.items.map(item => item.headUuid)) + .getFilters() + + }); + + api.dispatch(updateResources(users.items)); + + } catch (e) { + + api.dispatch(couldNotFetchGroupDetailsContents()); + + } + } + } +} + +const groupsDetailsPanelDataExplorerIsNotSet = () => + snackbarActions.OPEN_SNACKBAR({ + message: 'Group details panel is not ready.' + }); + +const couldNotFetchGroupDetailsContents = () => + snackbarActions.OPEN_SNACKBAR({ + message: 'Could not fetch group details.', + kind: SnackbarKind.ERROR + }); diff --git a/src/store/store.ts b/src/store/store.ts index c04789d7..ad70868e 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -52,6 +52,8 @@ import { computeNodesReducer } from '~/store/compute-nodes/compute-nodes-reducer import { apiClientAuthorizationsReducer } from '~/store/api-client-authorizations/api-client-authorizations-reducer'; import { GroupsPanelMiddlewareService } from '~/store/groups-panel/groups-panel-middleware-service'; import { GROUPS_PANEL_ID } from '~/store/groups-panel/groups-panel-actions'; +import { GroupDetailsPanelMiddlewareService } from '~/store/group-details-panel/group-details-panel-middleware-service'; +import { GROUP_DETAILS_PANEL_ID } from '~/store/group-details-panel/group-details-panel-actions'; const composeEnhancers = (process.env.NODE_ENV === 'development' && @@ -89,6 +91,9 @@ export function configureStore(history: History, services: ServiceRepository): R const groupsPanelMiddleware = dataExplorerMiddleware( new GroupsPanelMiddlewareService(services, GROUPS_PANEL_ID) ); + const groupDetailsPanelMiddleware = dataExplorerMiddleware( + new GroupDetailsPanelMiddlewareService(services, GROUP_DETAILS_PANEL_ID) + ); const middlewares: Middleware[] = [ routerMiddleware(history), @@ -101,6 +106,7 @@ export function configureStore(history: History, services: ServiceRepository): R workflowPanelMiddleware, userPanelMiddleware, groupsPanelMiddleware, + groupDetailsPanelMiddleware, ]; const enhancer = composeEnhancers(applyMiddleware(...middlewares)); return createStore(rootReducer, enhancer); diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts index 2ae59029..1cc058c6 100644 --- a/src/store/workbench/workbench-actions.ts +++ b/src/store/workbench/workbench-actions.ts @@ -64,6 +64,7 @@ import { loadComputeNodesPanel } from '~/store/compute-nodes/compute-nodes-actio import { loadApiClientAuthorizationsPanel } from '~/store/api-client-authorizations/api-client-authorizations-actions'; import * as groupPanelActions from '~/store/groups-panel/groups-panel-actions'; import { groupsPanelColumns } from '~/views/groups-panel/groups-panel'; +import * as groupDetailsPanelActions from '~/store/group-details-panel/group-details-panel-actions'; export const WORKBENCH_LOADING_SCREEN = 'workbenchLoadingScreen'; @@ -454,6 +455,13 @@ export const loadGroupsPanel = handleFirstTimeLoad( dispatch(groupPanelActions.loadGroupsPanel()); }); +export const loadGroupDetailsPanel = (groupUuid: string) => + handleFirstTimeLoad( + (dispatch: Dispatch) => { + dispatch(setBreadcrumbs([{ label: 'Groups' }, { label: groupUuid }])); + dispatch(groupDetailsPanelActions.loadGroupDetailsPanel(groupUuid)); + }); + const finishLoadingProject = (project: GroupContentsResource | string) => async (dispatch: Dispatch) => { const uuid = typeof project === 'string' ? project : project.uuid; -- 2.30.2