X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/b5dde550c7dd67f0b90841d6b92930e56c625dcd..795e98eac92b86652d3fe9de6657ffffc009d90e:/src/store/resource-type-filters/resource-type-filters.ts?ds=sidebyside diff --git a/src/store/resource-type-filters/resource-type-filters.ts b/src/store/resource-type-filters/resource-type-filters.ts index d95ae5a4..ef1198bc 100644 --- a/src/store/resource-type-filters/resource-type-filters.ts +++ b/src/store/resource-type-filters/resource-type-filters.ts @@ -2,14 +2,25 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { pipe, values, includes, __ } from 'lodash/fp'; -import { createTree, setNode, TreeNodeStatus, TreeNode } from '~/models/tree'; +import { difference, pipe, values, includes, __ } from 'lodash/fp'; +import { createTree, setNode, TreeNodeStatus, TreeNode, Tree } from '~/models/tree'; import { DataTableFilterItem, DataTableFilters } from '~/components/data-table-filters/data-table-filters-tree'; import { ResourceKind } from '~/models/resource'; import { FilterBuilder } from '~/services/api/filter-builder'; import { getSelectedNodes } from '~/models/tree'; import { CollectionType } from '~/models/collection'; import { GroupContentsResourcePrefix } from '~/services/groups-service/groups-service'; +import { ContainerState } from '~/models/container'; + +export enum ProcessStatusFilter { + ALL = 'All', + RUNNING = 'Running', + FAILED = 'Failed', + COMPLETED = 'Completed', + CANCELLED = 'Cancelled', + LOCKED = 'Locked', + QUEUED = 'Queued' +} export enum ObjectTypeFilter { PROJECT = 'Project', @@ -23,29 +34,76 @@ export enum CollectionTypeFilter { LOG_COLLECTION = 'Log', } -const initFilter = (name: string, parent = '') => +export enum ProcessTypeFilter { + MAIN_PROCESS = 'Main', + CHILD_PROCESS = 'Child', +} + +const initFilter = (name: string, parent = '', isSelected?: boolean) => setNode({ id: name, value: { name }, parent, children: [], active: false, - selected: true, + selected: isSelected !== undefined ? isSelected : true, expanded: false, status: TreeNodeStatus.LOADED, }); -export const getInitialResourceTypeFilters = pipe( +export const getSimpleObjectTypeFilters = pipe( (): DataTableFilters => createTree(), initFilter(ObjectTypeFilter.PROJECT), initFilter(ObjectTypeFilter.PROCESS), initFilter(ObjectTypeFilter.COLLECTION), +); + +// Using pipe() with more than 7 arguments makes the return type be 'any', +// causing compile issues. +export const getInitialResourceTypeFilters = pipe( + (): DataTableFilters => createTree(), + initFilter(ObjectTypeFilter.PROJECT), + pipe( + initFilter(ObjectTypeFilter.PROCESS), + initFilter(ProcessTypeFilter.MAIN_PROCESS, ObjectTypeFilter.PROCESS), + initFilter(ProcessTypeFilter.CHILD_PROCESS, ObjectTypeFilter.PROCESS) + ), + pipe( + initFilter(ObjectTypeFilter.COLLECTION), + initFilter(CollectionTypeFilter.GENERAL_COLLECTION, ObjectTypeFilter.COLLECTION), + initFilter(CollectionTypeFilter.OUTPUT_COLLECTION, ObjectTypeFilter.COLLECTION), + initFilter(CollectionTypeFilter.LOG_COLLECTION, ObjectTypeFilter.COLLECTION), + ), +); + +export const getInitialProcessTypeFilters = pipe( + (): DataTableFilters => createTree(), + initFilter(ProcessTypeFilter.MAIN_PROCESS), + initFilter(ProcessTypeFilter.CHILD_PROCESS, '', false) +); + +export const getInitialProcessStatusFilters = pipe( + (): DataTableFilters => createTree(), + pipe( + initFilter(ProcessStatusFilter.ALL, '', true), + initFilter(ProcessStatusFilter.RUNNING, '', false), + initFilter(ProcessStatusFilter.FAILED, '', false), + initFilter(ProcessStatusFilter.COMPLETED, '', false), + initFilter(ProcessStatusFilter.CANCELLED, '', false), + initFilter(ProcessStatusFilter.QUEUED, '', false), + initFilter(ProcessStatusFilter.LOCKED, '', false), + ), +); + +export const getTrashPanelTypeFilters = pipe( + (): DataTableFilters => createTree(), + initFilter(ObjectTypeFilter.PROJECT), + initFilter(ObjectTypeFilter.COLLECTION), initFilter(CollectionTypeFilter.GENERAL_COLLECTION, ObjectTypeFilter.COLLECTION), initFilter(CollectionTypeFilter.OUTPUT_COLLECTION, ObjectTypeFilter.COLLECTION), initFilter(CollectionTypeFilter.LOG_COLLECTION, ObjectTypeFilter.COLLECTION), ); - const createFiltersBuilder = (filters: DataTableFilters) => ({ fb: new FilterBuilder(), selectedFilters: getSelectedNodes(filters) }); @@ -67,11 +125,15 @@ const objectTypeToResourceKind = (type: ObjectTypeFilter) => { const serializeObjectTypeFilters = ({ fb, selectedFilters }: ReturnType) => { const collectionFilters = getMatchingFilters(values(CollectionTypeFilter), selectedFilters); + const processFilters = getMatchingFilters(values(ProcessTypeFilter), selectedFilters); const typeFilters = pipe( () => new Set(getMatchingFilters(values(ObjectTypeFilter), selectedFilters)), set => collectionFilters.length > 0 ? set.add(ObjectTypeFilter.COLLECTION) : set, + set => processFilters.length > 0 + ? set.add(ObjectTypeFilter.PROCESS) + : set, set => Array.from(set) )(); @@ -98,16 +160,104 @@ const serializeCollectionTypeFilters = ({ fb, selectedFilters }: ReturnType getMatchingFilters(values(CollectionTypeFilter), selectedFilters), filters => filters.map(collectionTypeToPropertyValue), mappedFilters => ({ - fb: mappedFilters.length > 0 - ? fb.addIn('type', mappedFilters, `${GroupContentsResourcePrefix.COLLECTION}.properties`) - : fb, + fb: buildCollectionTypeFilters({ fb, filters: mappedFilters }), selectedFilters }) )(); +const COLLECTION_TYPES = values(CollectionType); + +const NON_GENERAL_COLLECTION_TYPES = difference(COLLECTION_TYPES, [CollectionType.GENERAL]); + +const COLLECTION_PROPERTIES_PREFIX = `${GroupContentsResourcePrefix.COLLECTION}.properties`; + +const buildCollectionTypeFilters = ({ fb, filters }: { fb: FilterBuilder, filters: CollectionType[] }) => { + switch (true) { + case filters.length === 0 || filters.length === COLLECTION_TYPES.length: + return fb; + case includes(CollectionType.GENERAL, filters): + return fb.addNotIn('type', difference(NON_GENERAL_COLLECTION_TYPES, filters), COLLECTION_PROPERTIES_PREFIX); + default: + return fb.addIn('type', filters, COLLECTION_PROPERTIES_PREFIX); + } +}; + +const serializeProcessTypeFilters = ({ fb, selectedFilters }: ReturnType) => pipe( + () => getMatchingFilters(values(ProcessTypeFilter), selectedFilters), + filters => filters, + mappedFilters => ({ + fb: buildProcessTypeFilters({ fb, filters: mappedFilters, use_prefix: true }), + selectedFilters + }) +)(); + +const PROCESS_TYPES = values(ProcessTypeFilter); +const PROCESS_PREFIX = GroupContentsResourcePrefix.PROCESS; + +const buildProcessTypeFilters = ({ fb, filters, use_prefix }: { fb: FilterBuilder, filters: string[], use_prefix: boolean }) => { + switch (true) { + case filters.length === 0 || filters.length === PROCESS_TYPES.length: + return fb; + case includes(ProcessTypeFilter.MAIN_PROCESS, filters): + return fb.addEqual('requesting_container_uuid', null, use_prefix ? PROCESS_PREFIX : ''); + case includes(ProcessTypeFilter.CHILD_PROCESS, filters): + return fb.addDistinct('requesting_container_uuid', null, use_prefix ? PROCESS_PREFIX : ''); + default: + return fb; + } +}; + export const serializeResourceTypeFilters = pipe( createFiltersBuilder, serializeObjectTypeFilters, serializeCollectionTypeFilters, + serializeProcessTypeFilters, + ({ fb }) => fb.getFilters(), +); + +export const serializeOnlyProcessTypeFilters = pipe( + createFiltersBuilder, + ({ fb, selectedFilters }: ReturnType) => pipe( + () => getMatchingFilters(values(ProcessTypeFilter), selectedFilters), + filters => filters, + mappedFilters => ({ + fb: buildProcessTypeFilters({ fb, filters: mappedFilters, use_prefix: false }), + selectedFilters + }) + )(), ({ fb }) => fb.getFilters(), ); + +export const serializeSimpleObjectTypeFilters = (filters: Tree) => { + return getSelectedNodes(filters) + .map(f => f.id) + .map(objectTypeToResourceKind); +}; + +export const buildProcessStatusFilters = ( fb:FilterBuilder, activeStatusFilter:string ): FilterBuilder => { + switch (activeStatusFilter) { + case ProcessStatusFilter.COMPLETED: { + fb.addEqual('container.state', ContainerState.COMPLETE); + fb.addEqual('container.exit_code', '0'); + break; + } + case ProcessStatusFilter.FAILED: { + fb.addEqual('container.state', ContainerState.COMPLETE); + fb.addDistinct('container.exit_code', '0'); + break; + } + case ProcessStatusFilter.QUEUED: { + fb.addEqual('container.state', ContainerState.QUEUED); + fb.addDistinct('container.priority', '0'); + break; + } + case ProcessStatusFilter.CANCELLED: + case ProcessStatusFilter.FAILED: + case ProcessStatusFilter.LOCKED: + case ProcessStatusFilter.RUNNING: { + fb.addEqual('container.state', activeStatusFilter); + break; + } + } + return fb; +}; \ No newline at end of file