15012: Adds filtering by process type & ordering by name and created_at date.
authorLucas Di Pentima <lucas@di-pentima.com.ar>
Tue, 21 Jan 2020 19:49:21 +0000 (16:49 -0300)
committerLucas Di Pentima <lucas@di-pentima.com.ar>
Tue, 21 Jan 2020 19:49:21 +0000 (16:49 -0300)
Default 'process type' filter status is: show only main processes.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas@di-pentima.com.ar>

src/store/all-processes-panel/all-processes-panel-middleware-service.ts
src/store/resource-type-filters/resource-type-filters.ts
src/views/all-processes-panel/all-processes-panel.tsx

index 43432cfd6edf2180384093fed909ce64784a4247..df4bc74b71d646690b8303ea716bce152583d421 100644 (file)
@@ -11,10 +11,18 @@ import { Dispatch, MiddlewareAPI } from "redux";
 import { resourcesActions } from "~/store/resources/resources-actions";
 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions.ts';
-import { getDataExplorer, DataExplorer } from "~/store/data-explorer/data-explorer-reducer";
+import { getDataExplorer, DataExplorer, getSortColumn } from "~/store/data-explorer/data-explorer-reducer";
 import { loadMissingProcessesInformation } from "~/store/project-panel/project-panel-middleware-service";
 import { DataColumns } from "~/components/data-table/data-table";
-import { ProcessStatusFilter, buildProcessStatusFilters } from "../resource-type-filters/resource-type-filters";
+import {
+    ProcessStatusFilter,
+    buildProcessStatusFilters,
+    serializeOnlyProcessTypeFilters
+} from "../resource-type-filters/resource-type-filters";
+import { AllProcessesPanelColumnNames } from "~/views/all-processes-panel/all-processes-panel";
+import { OrderBuilder, OrderDirection } from "~/services/api/order-builder";
+import { ProcessResource } from "~/models/process";
+import { SortDirection } from "~/components/data-table/data-column";
 
 export class AllProcessesPanelMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -56,6 +64,7 @@ export class AllProcessesPanelMiddlewareService extends DataExplorerMiddlewareSe
 
 const getParams = ( dataExplorer: DataExplorer ) => ({
     ...dataExplorerToListParams(dataExplorer),
+    order: getOrder(dataExplorer),
     filters: getFilters(dataExplorer)
 });
 
@@ -68,13 +77,34 @@ const getFilters = ( dataExplorer: DataExplorer ) => {
 
     const nameFilter = new FilterBuilder().addILike("name", dataExplorer.searchValue).getFilters();
     const statusFilter = buildProcessStatusFilters(new FilterBuilder(), activeStatusFilter).getFilters();
+    const typeFilters = serializeOnlyProcessTypeFilters(getDataExplorerColumnFilters(columns, AllProcessesPanelColumnNames.TYPE));
 
     return joinFilters(
         nameFilter,
-        statusFilter
+        // TODO: When 15019 is merged, this won't be necessary
+        joinFilters(
+            statusFilter,
+            typeFilters)
     );
 };
 
+const getOrder = (dataExplorer: DataExplorer) => {
+    const sortColumn = getSortColumn(dataExplorer);
+    const order = new OrderBuilder<ProcessResource>();
+    if (sortColumn) {
+        const sortDirection = sortColumn && sortColumn.sortDirection === SortDirection.ASC
+            ? OrderDirection.ASC
+            : OrderDirection.DESC;
+
+        const columnName = sortColumn && sortColumn.name === AllProcessesPanelColumnNames.NAME ? "name" : "createdAt";
+        return order
+            .addOrder(sortDirection, columnName)
+            .getOrder();
+    } else {
+        return order.getOrder();
+    }
+};
+
 const allProcessesPanelDataExplorerIsNotSet = () =>
     snackbarActions.OPEN_SNACKBAR({
         message: 'All Processes panel is not ready.',
index 6766bfca10eb2a075fe97b88b40970bd5f65fb3f..1cc547ec76c07e1a01dd29afa6f2c699963ed667 100644 (file)
@@ -57,7 +57,7 @@ export const getSimpleObjectTypeFilters = pipe(
     initFilter(ObjectTypeFilter.COLLECTION),
 );
 
-// Using pipe() with more tha 7 arguments makes the return type be 'any',
+// Using pipe() with more than 7 arguments makes the return type be 'any',
 // causing compile issues.
 export const getInitialResourceTypeFilters = pipe(
     (): DataTableFilters => createTree<DataTableFilterItem>(),
@@ -75,6 +75,12 @@ export const getInitialResourceTypeFilters = pipe(
     ),
 );
 
+export const getInitialProcessTypeFilters = pipe(
+    (): DataTableFilters => createTree<DataTableFilterItem>(),
+    initFilter(ProcessTypeFilter.MAIN_PROCESS),
+    initFilter(ProcessTypeFilter.CHILD_PROCESS, '', false)
+);
+
 export const getInitialProcessStatusFilters = pipe(
     (): DataTableFilters => createTree<DataTableFilterItem>(),
     pipe(
@@ -179,7 +185,7 @@ const serializeProcessTypeFilters = ({ fb, selectedFilters }: ReturnType<typeof
     () => getMatchingFilters(values(ProcessTypeFilter), selectedFilters),
     filters => filters,
     mappedFilters => ({
-        fb: buildProcessTypeFilters({ fb, filters: mappedFilters }),
+        fb: buildProcessTypeFilters({ fb, filters: mappedFilters, use_prefix: true }),
         selectedFilters
     })
 )();
@@ -187,14 +193,14 @@ const serializeProcessTypeFilters = ({ fb, selectedFilters }: ReturnType<typeof
 const PROCESS_TYPES = values(ProcessTypeFilter);
 const PROCESS_PREFIX = GroupContentsResourcePrefix.PROCESS;
 
-const buildProcessTypeFilters = ({ fb, filters }: { fb: FilterBuilder, filters: string[] }) => {
+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, PROCESS_PREFIX);
+            return fb.addEqual('requesting_container_uuid', null, use_prefix ? PROCESS_PREFIX : '');
         case includes(ProcessTypeFilter.CHILD_PROCESS, filters):
-            return fb.addDistinct('requesting_container_uuid', null, PROCESS_PREFIX);
+            return fb.addDistinct('requesting_container_uuid', null, use_prefix ? PROCESS_PREFIX : '');
         default:
             return fb;
     }
@@ -208,6 +214,19 @@ export const serializeResourceTypeFilters = pipe(
     ({ fb }) => fb.getFilters(),
 );
 
+export const serializeOnlyProcessTypeFilters = pipe(
+    createFiltersBuilder,
+    ({ fb, selectedFilters }: ReturnType<typeof createFiltersBuilder>) => 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<DataTableFilterItem>) => {
     return getSelectedNodes(filters)
         .map(f => f.id)
index 79575c74626455579ee60d44c75e420209b2c6ef..723cf75b8f497acbea8b2576a984c6adc0582414 100644 (file)
@@ -15,10 +15,10 @@ import { ArvadosTheme } from '~/common/custom-theme';
 import { ALL_PROCESSES_PANEL_ID } from '~/store/all-processes-panel/all-processes-panel-action';
 import {
     ProcessStatus,
-    ResourceLastModifiedDate,
     ResourceName,
     ResourceOwner,
-    ResourceType
+    ResourceType,
+    ResourceCreatedAtDate
 } from '~/views-components/data-explorer/renderers';
 import { ProcessIcon } from '~/components/icon/icon';
 import { openContextMenu, resourceKindToContextMenuKind } from '~/store/context-menu/context-menu-actions';
@@ -28,7 +28,7 @@ import { ContainerRequestState } from "~/models/container-request";
 import { RootState } from '~/store/store';
 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
 import { createTree } from '~/models/tree';
-import { getSimpleObjectTypeFilters, getInitialProcessStatusFilters } from '~/store/resource-type-filters/resource-type-filters';
+import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from '~/store/resource-type-filters/resource-type-filters';
 
 type CssRules = "toolbar" | "button";
 
@@ -47,7 +47,7 @@ export enum AllProcessesPanelColumnNames {
     STATUS = "Status",
     TYPE = "Type",
     OWNER = "Owner",
-    LAST_MODIFIED = "Last modified"
+    CREATED_AT = "Started at"
 }
 
 export interface AllProcessesPanelFilter extends DataTableFilterItem {
@@ -75,8 +75,7 @@ export const allProcessesPanelColumns: DataColumns<string> = [
         name: AllProcessesPanelColumnNames.TYPE,
         selected: true,
         configurable: true,
-        // TODO: Only filter by process type (main, subprocess)
-        filters: getSimpleObjectTypeFilters(),
+        filters: getInitialProcessTypeFilters(),
         render: uuid => <ResourceType uuid={uuid} />
     },
     {
@@ -87,12 +86,12 @@ export const allProcessesPanelColumns: DataColumns<string> = [
         render: uuid => <ResourceOwner uuid={uuid} />
     },
     {
-        name: AllProcessesPanelColumnNames.LAST_MODIFIED,
+        name: AllProcessesPanelColumnNames.CREATED_AT,
         selected: true,
         configurable: true,
         sortDirection: SortDirection.DESC,
         filters: createTree(),
-        render: uuid => <ResourceLastModifiedDate uuid={uuid} />
+        render: uuid => <ResourceCreatedAtDate uuid={uuid} />
     }
 ];
 
@@ -147,7 +146,7 @@ export const AllProcessesPanel = withStyles(styles)(
                     dataTableDefaultView={
                         <DataTableDefaultView
                             icon={ProcessIcon}
-                            messages={['All Processes list empty.']}
+                            messages={['Processes list empty.']}
                             />
                     } />;
             }