X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/c276ce4c8dd3cf27ad6d17eca9af473f353fda55..HEAD:/src/services/common-service/common-resource-service.ts?ds=sidebyside diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts index 7b36b71c..907f0081 100644 --- a/src/services/common-service/common-resource-service.ts +++ b/src/services/common-service/common-resource-service.ts @@ -2,130 +2,83 @@ // // SPDX-License-Identifier: AGPL-3.0 -import * as _ from "lodash"; -import { AxiosInstance, AxiosPromise } from "axios"; -import { Resource } from "src/models/resource"; - -export interface ListArguments { - limit?: number; - offset?: number; - filters?: string; - order?: string; - select?: string[]; - distinct?: boolean; - count?: string; -} - -export interface ListResults { - kind: string; - offset: number; - limit: number; - items: T[]; - itemsAvailable: number; -} - -export interface Errors { - errors: string[]; - errorToken: string; -} +import { AxiosInstance } from "axios"; +import { snakeCase } from "lodash"; +import { Resource } from "models/resource"; +import { ApiActions } from "services/api/api-actions"; +import { CommonService } from "services/common-service/common-service"; export enum CommonResourceServiceError { - UNIQUE_VIOLATION = 'UniqueViolation', + UNIQUE_NAME_VIOLATION = 'UniqueNameViolation', OWNERSHIP_CYCLE = 'OwnershipCycle', + MODIFYING_CONTAINER_REQUEST_FINAL_STATE = 'ModifyingContainerRequestFinalState', + NAME_HAS_ALREADY_BEEN_TAKEN = 'NameHasAlreadyBeenTaken', + PERMISSION_ERROR_FORBIDDEN = 'PermissionErrorForbidden', + SOURCE_DESTINATION_CANNOT_BE_SAME = 'SourceDestinationCannotBeSame', UNKNOWN = 'Unknown', NONE = 'None' } -export class CommonResourceService { - - static mapResponseKeys = (response: { data: any }): Promise => - CommonResourceService.mapKeys(_.camelCase)(response.data) - - static mapKeys = (mapFn: (key: string) => string) => - (value: any): any => { - switch (true) { - case _.isPlainObject(value): - return Object - .keys(value) - .map(key => [key, mapFn(key)]) - .reduce((newValue, [key, newKey]) => ({ - ...newValue, - [newKey]: CommonResourceService.mapKeys(mapFn)(value[key]) - }), {}); - case _.isArray(value): - return value.map(CommonResourceService.mapKeys(mapFn)); - default: - return value; - } - } - - static defaultResponse(promise: AxiosPromise): Promise { - return promise - .then(CommonResourceService.mapResponseKeys) - .catch(({ response }) => Promise.reject(CommonResourceService.mapResponseKeys(response))); - } - - protected serverApi: AxiosInstance; - protected resourceType: string; - - constructor(serverApi: AxiosInstance, resourceType: string) { - this.serverApi = serverApi; - this.resourceType = '/' + resourceType + '/'; - } - - create(data?: Partial | any) { - return CommonResourceService.defaultResponse( - this.serverApi - .post(this.resourceType, data && CommonResourceService.mapKeys(_.snakeCase)(data))); - } - - delete(uuid: string): Promise { - return CommonResourceService.defaultResponse( - this.serverApi - .delete(this.resourceType + uuid)); - } - - get(uuid: string) { - return CommonResourceService.defaultResponse( - this.serverApi - .get(this.resourceType + uuid)); +export class CommonResourceService extends CommonService { + constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) { + super(serverApi, resourceType, actions, readOnlyFields.concat([ + 'uuid', + 'etag', + 'kind', + 'canWrite', + 'canManage', + 'createdAt', + 'modifiedAt', + 'modifiedByClientUuid', + 'modifiedByUserUuid' + ])); } - list(args: ListArguments = {}): Promise> { - const { filters, order, ...other } = args; - const params = { - ...other, - filters: filters ? `[${filters}]` : undefined, - order: order ? order : undefined - }; - return CommonResourceService.defaultResponse( - this.serverApi - .get(this.resourceType, { - params: CommonResourceService.mapKeys(_.snakeCase)(params) - })); + create(data?: Partial, showErrors?: boolean) { + let payload: any; + if (data !== undefined) { + this.readOnlyFields.forEach(field => delete data[field]); + payload = { + [this.resourceType.slice(0, -1)]: CommonService.mapKeys(snakeCase)(data), + }; + } + return super.create(payload, showErrors); } - update(uuid: string, data: Partial) { - return CommonResourceService.defaultResponse( - this.serverApi - .put(this.resourceType + uuid, data && CommonResourceService.mapKeys(_.snakeCase)(data))); - + update(uuid: string, data: Partial, showErrors?: boolean, select?: string[]) { + let payload: any; + if (data !== undefined) { + this.readOnlyFields.forEach(field => delete data[field]); + payload = { + [this.resourceType.slice(0, -1)]: CommonService.mapKeys(snakeCase)(data), + }; + if (select !== undefined && select.length > 0) { + payload.select = ['uuid', ...select.map(field => snakeCase(field))]; + }; + } + return super.update(uuid, payload, showErrors); } } export const getCommonResourceServiceError = (errorResponse: any) => { - if ('errors' in errorResponse && 'errorToken' in errorResponse) { + if (errorResponse && 'errors' in errorResponse) { const error = errorResponse.errors.join(''); switch (true) { case /UniqueViolation/.test(error): - return CommonResourceServiceError.UNIQUE_VIOLATION; + return CommonResourceServiceError.UNIQUE_NAME_VIOLATION; case /ownership cycle/.test(error): return CommonResourceServiceError.OWNERSHIP_CYCLE; + case /Mounts cannot be modified in state 'Final'/.test(error): + return CommonResourceServiceError.MODIFYING_CONTAINER_REQUEST_FINAL_STATE; + case /Name has already been taken/.test(error): + return CommonResourceServiceError.NAME_HAS_ALREADY_BEEN_TAKEN; + case /403 Forbidden/.test(error): + return CommonResourceServiceError.PERMISSION_ERROR_FORBIDDEN; + case new RegExp(CommonResourceServiceError.SOURCE_DESTINATION_CANNOT_BE_SAME).test(error): + return CommonResourceServiceError.SOURCE_DESTINATION_CANNOT_BE_SAME; default: return CommonResourceServiceError.UNKNOWN; } } return CommonResourceServiceError.NONE; }; - -