20469: Provide select parameter to contents to avoid loading mounts 20469-contents-select
authorPeter Amstutz <peter.amstutz@curii.com>
Wed, 3 May 2023 02:11:29 +0000 (22:11 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Wed, 3 May 2023 02:11:29 +0000 (22:11 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

src/models/container-request.ts
src/models/group.ts
src/services/groups-service/groups-service.ts
src/store/project-panel/project-panel-middleware-service.ts

index aa5e0f799934a935c2266c00f9882cfa4a3b5cad..02a8ea7017b54d6ff099aa9903ca2962a0722a8a 100644 (file)
@@ -8,41 +8,41 @@ import { RuntimeConstraints } from './runtime-constraints';
 import { SchedulingParameters } from './scheduling-parameters';
 
 export enum ContainerRequestState {
-  UNCOMMITTED = 'Uncommitted',
-  COMMITTED = 'Committed',
-  FINAL = 'Final',
+    UNCOMMITTED = 'Uncommitted',
+    COMMITTED = 'Committed',
+    FINAL = 'Final',
 }
 
 export interface ContainerRequestResource
-  extends Resource,
+    extends Resource,
     ResourceWithProperties {
-  command: string[];
-  containerCountMax: number;
-  containerCount: number;
-  containerImage: string;
-  containerUuid: string | null;
-  cumulativeCost: number;
-  cwd: string;
-  description: string;
-  environment: any;
-  expiresAt: string;
-  filters: string;
-  kind: ResourceKind.CONTAINER_REQUEST;
-  logUuid: string | null;
-  mounts: { [path: string]: MountType };
-  name: string;
-  outputName: string;
-  outputPath: string;
-  outputProperties: any;
-  outputStorageClasses: string[];
-  outputTtl: number;
-  outputUuid: string | null;
-  priority: number | null;
-  requestingContainerUuid: string | null;
-  runtimeConstraints: RuntimeConstraints;
-  schedulingParameters: SchedulingParameters;
-  state: ContainerRequestState;
-  useExisting: boolean;
+    command: string[];
+    containerCountMax: number;
+    containerCount: number;
+    containerImage: string;
+    containerUuid: string | null;
+    cumulativeCost: number;
+    cwd: string;
+    description: string;
+    environment: any;
+    expiresAt: string;
+    filters: string;
+    kind: ResourceKind.CONTAINER_REQUEST;
+    logUuid: string | null;
+    mounts: { [path: string]: MountType };
+    name: string;
+    outputName: string;
+    outputPath: string;
+    outputProperties: any;
+    outputStorageClasses: string[];
+    outputTtl: number;
+    outputUuid: string | null;
+    priority: number | null;
+    requestingContainerUuid: string | null;
+    runtimeConstraints: RuntimeConstraints;
+    schedulingParameters: SchedulingParameters;
+    state: ContainerRequestState;
+    useExisting: boolean;
 }
 
 // Until the api supports unselecting fields, we need a list of all other fields to omit mounts
index f6a72c538f9481392aabac0883077cbf2086a6b4..109f38571f97b38f32efe5510967d9c3547e3a8c 100644 (file)
@@ -21,8 +21,8 @@ export interface GroupResource extends TrashableResource, ResourceWithProperties
 
 export enum GroupClass {
     PROJECT = 'project',
-    FILTER  = 'filter',
-    ROLE  = 'role',
+    FILTER = 'filter',
+    ROLE = 'role',
 }
 
 export enum BuiltinGroups {
@@ -40,3 +40,18 @@ export const isBuiltinGroup = (uuid: string) => {
     const parts = match ? match[0].split('-') : [];
     return parts.length === 3 && parts[1] === ResourceObjectType.GROUP && Object.values<string>(BuiltinGroups).includes(parts[2]);
 };
+
+export const selectedFieldsOfGroup = [
+    "uuid",
+    "name",
+    "group_class",
+    "description",
+    "properties",
+    "writable_by",
+    "can_write",
+    "can_manage",
+    "trash_at",
+    "delete_at",
+    "is_trashed",
+    "frozen_by_uuid"
+];
index a36ddba894c84a987f8f672c1a370a627f89b13c..cdbe8bab22dfc3b7cd43c382635a6b768c1445ce 100644 (file)
@@ -6,8 +6,8 @@ import { CancelToken } from 'axios';
 import { snakeCase, camelCase } from "lodash";
 import { CommonResourceService } from 'services/common-service/common-resource-service';
 import {
-  ListResults,
-  ListArguments,
+    ListResults,
+    ListArguments,
 } from 'services/common-service/common-service';
 import { AxiosInstance, AxiosRequestConfig } from 'axios';
 import { CollectionResource } from 'models/collection';
@@ -20,78 +20,85 @@ import { GroupResource } from 'models/group';
 import { Session } from 'models/session';
 
 export interface ContentsArguments {
-  limit?: number;
-  offset?: number;
-  order?: string;
-  filters?: string;
-  recursive?: boolean;
-  includeTrash?: boolean;
-  excludeHomeProject?: boolean;
+    limit?: number;
+    offset?: number;
+    order?: string;
+    filters?: string;
+    recursive?: boolean;
+    includeTrash?: boolean;
+    excludeHomeProject?: boolean;
+    select?: string[];
 }
 
 export interface SharedArguments extends ListArguments {
-  include?: string;
+    include?: string;
 }
 
 export type GroupContentsResource =
-  | CollectionResource
-  | ProjectResource
-  | ProcessResource
-  | WorkflowResource;
+    | CollectionResource
+    | ProjectResource
+    | ProcessResource
+    | WorkflowResource;
 
 export class GroupsService<
-  T extends GroupResource = GroupResource
-> extends TrashableResourceService<T> {
-  constructor(serverApi: AxiosInstance, actions: ApiActions) {
-    super(serverApi, 'groups', actions);
-  }
+    T extends GroupResource = GroupResource
+    > extends TrashableResourceService<T> {
+    constructor(serverApi: AxiosInstance, actions: ApiActions) {
+        super(serverApi, 'groups', actions);
+    }
 
-async contents(uuid: string, args: ContentsArguments = {}, session?: Session, cancelToken?: CancelToken): Promise<ListResults<GroupContentsResource>> {
-    const { filters, order, ...other } = args;
-    const params = {
-        ...other,
-        filters: filters ? `[${filters}]` : undefined,
-        order: order ? order : undefined
-    };
-    const pathUrl = uuid ? `/${uuid}/contents` : '/contents';
-    const cfg: AxiosRequestConfig = {
-      params: CommonResourceService.mapKeys(snakeCase)(params),
-    };
+    async contents(uuid: string, args: ContentsArguments = {}, session?: Session, cancelToken?: CancelToken): Promise<ListResults<GroupContentsResource>> {
+        const { filters, order, select, ...other } = args;
+        const params = {
+            ...other,
+            filters: filters ? `[${filters}]` : undefined,
+            order: order ? order : undefined,
+            select: select
+                ? JSON.stringify(select.map(sel => {
+                    const sp = sel.split(".");
+                    return sp.length == 2 ? (sp[0] + "." + snakeCase(sp[1])) : snakeCase(sel);
+                }))
+                : undefined
+        };
+        const pathUrl = uuid ? `/${uuid}/contents` : '/contents';
+        const cfg: AxiosRequestConfig = {
+            params: CommonResourceService.mapKeys(snakeCase)(params),
+        };
 
-    if (session) {
-      cfg.baseURL = session.baseUrl;
-      cfg.headers = { Authorization: 'Bearer ' + session.token };
-    }
+        if (session) {
+            cfg.baseURL = session.baseUrl;
+            cfg.headers = { Authorization: 'Bearer ' + session.token };
+        }
 
-    if (cancelToken) {
-      cfg.cancelToken = cancelToken;
-    }
+        if (cancelToken) {
+            cfg.cancelToken = cancelToken;
+        }
 
-    const response = await CommonResourceService.defaultResponse(
-      this.serverApi.get(this.resourceType + pathUrl, cfg),
-      this.actions,
-      false
-    );
+        const response = await CommonResourceService.defaultResponse(
+            this.serverApi.get(this.resourceType + pathUrl, cfg),
+            this.actions,
+            false
+        );
 
-    return {
-      ...TrashableResourceService.mapKeys(camelCase)(response),
-      clusterId: session && session.clusterId,
-    };
-  }
+        return {
+            ...TrashableResourceService.mapKeys(camelCase)(response),
+            clusterId: session && session.clusterId,
+        };
+    }
 
-  shared(
-    params: SharedArguments = {}
-  ): Promise<ListResults<GroupContentsResource>> {
-    return CommonResourceService.defaultResponse(
-      this.serverApi.get(this.resourceType + '/shared', { params }),
-      this.actions
-    );
-  }
+    shared(
+        params: SharedArguments = {}
+    ): Promise<ListResults<GroupContentsResource>> {
+        return CommonResourceService.defaultResponse(
+            this.serverApi.get(this.resourceType + '/shared', { params }),
+            this.actions
+        );
+    }
 }
 
 export enum GroupContentsResourcePrefix {
-  COLLECTION = 'collections',
-  PROJECT = 'groups',
-  PROCESS = 'container_requests',
-  WORKFLOW = 'workflows',
+    COLLECTION = 'collections',
+    PROJECT = 'groups',
+    PROCESS = 'container_requests',
+    WORKFLOW = 'workflows',
 }
index 7051d06206ca9d0c6b39eeb061926a5a1bafe1b9..c9aafd52300abb449f12dae82cd295ca185ee3e0 100644 (file)
@@ -38,6 +38,9 @@ import {
     buildProcessStatusFilters
 } from 'store/resource-type-filters/resource-type-filters';
 import { updatePublicFavorites } from 'store/public-favorites/public-favorites-actions';
+import { selectedFieldsOfGroup } from 'models/group';
+import { defaultCollectionSelectedFields } from 'models/collection';
+import { containerRequestFieldsNoMounts } from 'models/container-request';
 
 export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -82,8 +85,8 @@ export const loadMissingProcessesInformation = (resources: GroupContentsResource
     async (dispatch: Dispatch) => {
         const containerUuids = resources.reduce((uuids, resource) => {
             return resource.kind === ResourceKind.CONTAINER_REQUEST &&
-                    resource.containerUuid &&
-                    !uuids.includes(resource.containerUuid)
+                resource.containerUuid &&
+                !uuids.includes(resource.containerUuid)
                 ? [...uuids, resource.containerUuid]
                 : uuids;
         }, [] as string[]);
@@ -105,7 +108,8 @@ export const getParams = (dataExplorer: DataExplorer, isProjectTrashed: boolean)
     ...dataExplorerToListParams(dataExplorer),
     order: getOrder(dataExplorer),
     filters: getFilters(dataExplorer),
-    includeTrash: isProjectTrashed
+    includeTrash: isProjectTrashed,
+    select: selectedFieldsOfGroup.concat(defaultCollectionSelectedFields, containerRequestFieldsNoMounts)
 });
 
 export const getFilters = (dataExplorer: DataExplorer) => {