X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/2f39812f57c2acbc20a6292964b0a6b3512a9870..50939103cce489919423adcf8292d2f960a180fb:/src/store/tree-picker/tree-picker-actions.ts diff --git a/src/store/tree-picker/tree-picker-actions.ts b/src/store/tree-picker/tree-picker-actions.ts index f0f6bfcd..9ca6184a 100644 --- a/src/store/tree-picker/tree-picker-actions.ts +++ b/src/store/tree-picker/tree-picker-actions.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { unionize, ofType, UnionOf } from "~/common/unionize"; -import { TreeNode, initTreeNode, getNodeDescendants, getNodeDescendantsIds, getNodeValue, TreeNodeStatus } from '~/models/tree'; +import { TreeNode, initTreeNode, getNodeDescendants, getNodeDescendantsIds, getNodeValue, TreeNodeStatus, getNode } from '~/models/tree'; import { Dispatch } from 'redux'; import { RootState } from '~/store/store'; import { ServiceRepository } from '~/services/services'; @@ -12,12 +12,15 @@ import { pipe } from 'lodash/fp'; import { ResourceKind } from '~/models/resource'; import { GroupContentsResource } from '../../services/groups-service/groups-service'; import { CollectionDirectory, CollectionFile } from '../../models/collection-file'; +import { getTreePicker } from './tree-picker'; +import { ProjectsTreePickerItem } from '~/views-components/projects-tree-picker/generic-projects-tree-picker'; export const treePickerActions = unionize({ LOAD_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(), LOAD_TREE_PICKER_NODE_SUCCESS: ofType<{ id: string, nodes: Array>, pickerId: string }>(), TOGGLE_TREE_PICKER_NODE_COLLAPSE: ofType<{ id: string, pickerId: string }>(), ACTIVATE_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(), + DEACTIVATE_TREE_PICKER_NODE: ofType<{ pickerId: string }>(), TOGGLE_TREE_PICKER_NODE_SELECTION: ofType<{ id: string, pickerId: string }>(), EXPAND_TREE_PICKER_NODES: ofType<{ ids: string[], pickerId: string }>(), RESET_TREE_PICKER: ofType<{ pickerId: string }>() @@ -25,6 +28,19 @@ export const treePickerActions = unionize({ export type TreePickerAction = UnionOf; +export const getProjectsTreePickerIds = (pickerId: string) => ({ + home: `${pickerId}_home`, + shared: `${pickerId}_shared`, + favorites: `${pickerId}_favorites`, +}); +export const initProjectsTreePicker = (pickerId: string) => + async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => { + const { home, shared, favorites } = getProjectsTreePickerIds(pickerId); + dispatch(initUserProject(home)); + dispatch(initSharedProject(shared)); + dispatch(initFavoritesProject(favorites)); + }; + interface ReceiveTreePickerDataParams { data: T[]; extractNodeData: (value: T) => { id: string, value: T, status?: TreeNodeStatus }; @@ -42,43 +58,158 @@ export const receiveTreePickerData = (params: ReceiveTreePickerDataParams) dispatch(treePickerActions.TOGGLE_TREE_PICKER_NODE_COLLAPSE({ id, pickerId })); }; -export const loadProject = (id: string, pickerId: string, include?: ResourceKind[]) => +interface LoadProjectParams { + id: string; + pickerId: string; + includeCollections?: boolean; + includeFiles?: boolean; + loadShared?: boolean; +} +export const loadProject = (params: LoadProjectParams) => async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => { + const { id, pickerId, includeCollections = false, includeFiles = false, loadShared = false } = params; + dispatch(treePickerActions.LOAD_TREE_PICKER_NODE({ id, pickerId })); const filters = pipe( - (fb: FilterBuilder) => fb.addEqual('ownerUuid', id), - fb => include ? fb.addIsA('uuid', include) : fb, + (fb: FilterBuilder) => includeCollections + ? fb.addIsA('uuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION]) + : fb.addIsA('uuid', [ResourceKind.PROJECT]), fb => fb.getFilters(), )(new FilterBuilder()); - const { items } = await services.groupsService.contents(id, { filters }); + const { items } = await services.groupsService.contents(loadShared ? '' : id, { filters, excludeHomeProject: loadShared || undefined }); dispatch(receiveTreePickerData({ id, pickerId, data: items, - extractNodeData: item => ({ id: item.uuid, value: item }), + extractNodeData: item => ({ + id: item.uuid, + value: item, + status: item.kind === ResourceKind.PROJECT + ? TreeNodeStatus.INITIAL + : includeFiles + ? TreeNodeStatus.INITIAL + : TreeNodeStatus.LOADED + }), })); }; export const loadCollection = (id: string, pickerId: string) => - async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => { + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { dispatch(treePickerActions.LOAD_TREE_PICKER_NODE({ id, pickerId })); - const files = await services.collectionService.files(id); - const data = getNodeDescendants('')(files).map(node => node.value); + const picker = getTreePicker(pickerId)(getState().treePicker); + if (picker) { - dispatch(receiveTreePickerData({ - id, - pickerId, - data, - extractNodeData: value => { - return { - id: value.id, + const node = getNode(id)(picker); + if (node && 'kind' in node.value && node.value.kind === ResourceKind.COLLECTION) { + + const files = await services.collectionService.files(node.value.portableDataHash); + const data = getNodeDescendants('')(files).map(node => node.value); + + dispatch(receiveTreePickerData({ + id, + pickerId, + data, + extractNodeData: value => ({ + id: value.id, + status: TreeNodeStatus.LOADED, + value, + }), + })); + } + } + }; + + +export const initUserProject = (pickerId: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const uuid = services.authService.getUuid(); + if (uuid) { + dispatch(receiveTreePickerData({ + id: '', + pickerId, + data: [{ uuid, name: 'Projects' }], + extractNodeData: value => ({ + id: value.uuid, + status: TreeNodeStatus.INITIAL, value, - status: TreeNodeStatus.LOADED, - }; - }, + }), + })); + } + }; +export const loadUserProject = (pickerId: string, includeCollections = false, includeFiles = false) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const uuid = services.authService.getUuid(); + if (uuid) { + dispatch(loadProject({ id: uuid, pickerId, includeCollections, includeFiles })); + } + }; + + +export const initSharedProject = (pickerId: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(receiveTreePickerData({ + id: '', + pickerId, + data: [{ uuid: 'Shared with me', name: 'Shared with me' }], + extractNodeData: value => ({ + id: value.uuid, + status: TreeNodeStatus.INITIAL, + value, + }), + })); + }; + +export const initFavoritesProject = (pickerId: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(receiveTreePickerData({ + id: '', + pickerId, + data: [{ uuid: 'Favorites', name: 'Favorites' }], + extractNodeData: value => ({ + id: value.uuid, + status: TreeNodeStatus.INITIAL, + value, + }), })); }; + +interface LoadFavoritesProjectParams { + pickerId: string; + includeCollections?: boolean; + includeFiles?: boolean; +} +export const loadFavoritesProject = (params: LoadFavoritesProjectParams) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const { pickerId, includeCollections = false, includeFiles = false } = params; + const uuid = services.authService.getUuid(); + if (uuid) { + + const filters = pipe( + (fb: FilterBuilder) => includeCollections + ? fb.addIsA('headUuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION]) + : fb.addIsA('headUuid', [ResourceKind.PROJECT]), + fb => fb.getFilters(), + )(new FilterBuilder()); + + const { items } = await services.favoriteService.list(uuid, { filters }); + + dispatch(receiveTreePickerData({ + id: 'Favorites', + pickerId, + data: items, + extractNodeData: item => ({ + id: item.uuid, + value: item, + status: item.kind === ResourceKind.PROJECT + ? TreeNodeStatus.INITIAL + : includeFiles + ? TreeNodeStatus.INITIAL + : TreeNodeStatus.LOADED + }), + })); + } + };