X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/692582f3b80fa8f886d4ddb37055d71b3c3db14d..3c7e3cdc547ad5468421e1c049daa94b0d4b8bc0:/src/services/common-service/common-service.ts diff --git a/src/services/common-service/common-service.ts b/src/services/common-service/common-service.ts index 212f2f4d..c19c1978 100644 --- a/src/services/common-service/common-service.ts +++ b/src/services/common-service/common-service.ts @@ -2,12 +2,14 @@ // // SPDX-License-Identifier: AGPL-3.0 -import * as _ from "lodash"; +import { camelCase, isPlainObject, isArray, snakeCase } from "lodash"; import { AxiosInstance, AxiosPromise } from "axios"; -import * as uuid from "uuid/v4"; -import { ApiActions } from "~/services/api/api-actions"; +import uuid from "uuid/v4"; +import { ApiActions } from "services/api/api-actions"; +import QueryString from "query-string"; interface Errors { + status: number; errors: string[]; errorToken: string; } @@ -20,6 +22,7 @@ export interface ListArguments { select?: string[]; distinct?: boolean; count?: string; + includeOldVersions?: boolean; } export interface ListResults { @@ -35,20 +38,22 @@ export class CommonService { protected serverApi: AxiosInstance; protected resourceType: string; protected actions: ApiActions; + protected readOnlyFields: string[]; - constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions) { + constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) { this.serverApi = serverApi; - this.resourceType = '/' + resourceType + '/'; + this.resourceType = resourceType; this.actions = actions; + this.readOnlyFields = readOnlyFields; } static mapResponseKeys = (response: { data: any }) => - CommonService.mapKeys(_.camelCase)(response.data) + CommonService.mapKeys(camelCase)(response.data) static mapKeys = (mapFn: (key: string) => string) => (value: any): any => { switch (true) { - case _.isPlainObject(value): + case isPlainObject(value): return Object .keys(value) .map(key => [key, mapFn(key)]) @@ -56,14 +61,20 @@ export class CommonService { ...newValue, [newKey]: (key === 'items') ? CommonService.mapKeys(mapFn)(value[key]) : value[key] }), {}); - case _.isArray(value): + case isArray(value): return value.map(CommonService.mapKeys(mapFn)); default: return value; } } - static defaultResponse(promise: AxiosPromise, actions: ApiActions, mapKeys = true): Promise { + private validateUuid(uuid: string) { + if (uuid === "") { + throw new Error('UUID cannot be empty string'); + } + } + + static defaultResponse(promise: AxiosPromise, actions: ApiActions, mapKeys = true, showErrors = true): Promise { const reqId = uuid(); actions.progressFn(reqId, true); return promise @@ -77,55 +88,80 @@ export class CommonService { .catch(({ response }) => { actions.progressFn(reqId, false); const errors = CommonService.mapResponseKeys(response) as Errors; - actions.errorFn(reqId, errors); + errors.status = response.status; + actions.errorFn(reqId, errors, showErrors); throw errors; }); } - create(data?: Partial) { + create(data?: Partial, showErrors?: boolean) { return CommonService.defaultResponse( this.serverApi - .post(this.resourceType, data && CommonService.mapKeys(_.snakeCase)(data)), - this.actions + .post(`/${this.resourceType}`, data && CommonService.mapKeys(snakeCase)(data)), + this.actions, + true, // mapKeys + showErrors ); } delete(uuid: string): Promise { + this.validateUuid(uuid); return CommonService.defaultResponse( this.serverApi - .delete(this.resourceType + uuid), + .delete(`/${this.resourceType}/${uuid}`), this.actions ); } - get(uuid: string) { + get(uuid: string, showErrors?: boolean) { + this.validateUuid(uuid); return CommonService.defaultResponse( this.serverApi - .get(this.resourceType + uuid), - this.actions + .get(`/${this.resourceType}/${uuid}`), + this.actions, + true, // mapKeys + showErrors ); } list(args: ListArguments = {}): Promise> { const { filters, order, ...other } = args; const params = { - ...other, + ...CommonService.mapKeys(snakeCase)(other), filters: filters ? `[${filters}]` : undefined, order: order ? order : undefined }; - return CommonService.defaultResponse( - this.serverApi - .get(this.resourceType, { - params: CommonService.mapKeys(_.snakeCase)(params) + + if (QueryString.stringify(params).length <= 1500) { + return CommonService.defaultResponse( + this.serverApi.get(`/${this.resourceType}`, { params }), + this.actions + ); + } else { + // Using the POST special case to avoid URI length 414 errors. + const formData = new FormData(); + formData.append("_method", "GET"); + Object.keys(params).map(key => { + if (params[key] !== undefined) { + formData.append(key, params[key]); + } + }); + return CommonService.defaultResponse( + this.serverApi.post(`/${this.resourceType}`, formData, { + params: { + _method: 'GET' + } }), - this.actions - ); + this.actions + ); + } } update(uuid: string, data: Partial) { + this.validateUuid(uuid); return CommonService.defaultResponse( this.serverApi - .put(this.resourceType + uuid, data && CommonService.mapKeys(_.snakeCase)(data)), + .put(`/${this.resourceType}/${uuid}`, data && CommonService.mapKeys(snakeCase)(data)), this.actions ); }