[ARVADOS-WORKBENCH2] updated: 1.2.0-376-g6f8e509
Git user
git at public.curoverse.com
Sun Sep 16 15:57:04 EDT 2018
Summary of changes:
package.json | 4 ++-
src/index.tsx | 6 ++--
.../empty.ts => services/api/api-progress.ts} | 5 +--
src/services/api/url-builder.test.ts | 36 +++++++++++++++++++
src/services/api/url-builder.ts | 21 ++++++++++++
src/services/auth-service/auth-service.ts | 28 ++++++++++-----
.../collection-service/collection-service.ts | 5 +--
.../common-service/common-resource-service.test.ts | 17 +++++----
.../common-service/common-resource-service.ts | 40 +++++++++++++++++-----
.../common-service/trashable-resource-service.ts | 25 ++++++++------
.../container-request-service.ts | 7 ++--
.../container-service/container-service.ts | 7 ++--
src/services/favorite-service/favorite-service.ts | 2 +-
src/services/groups-service/groups-service.test.ts | 2 +-
src/services/groups-service/groups-service.ts | 17 +++++----
src/services/keep-service/keep-service.ts | 5 +--
src/services/link-service/link-service.ts | 5 +--
src/services/log-service/log-service.ts | 5 +--
.../project-service/project-service.test.ts | 4 +--
src/services/services.ts | 30 ++++++++--------
src/services/user-service/user-service.ts | 5 +--
src/store/auth/auth-actions.test.ts | 5 +--
src/store/auth/auth-reducer.test.ts | 3 +-
.../progress-indicator-actions.ts | 7 ++--
.../progress-indicator-reducer.ts | 38 +++++---------------
src/store/progress-indicator/with-progress.ts | 38 ++++++++++----------
.../side-panel-tree/side-panel-tree-actions.ts | 2 --
src/views-components/main-app-bar/main-app-bar.tsx | 5 ++-
src/views-components/progress/content-progress.tsx | 24 ++++++-------
.../progress/side-panel-progress.tsx | 24 ++++++-------
src/views-components/side-panel/side-panel.tsx | 6 ++--
src/views/workbench/workbench.tsx | 25 +++++++-------
tslint.json | 3 +-
yarn.lock | 14 +++++---
34 files changed, 283 insertions(+), 187 deletions(-)
copy src/{models/empty.ts => services/api/api-progress.ts} (57%)
create mode 100644 src/services/api/url-builder.test.ts
via 6f8e509988756deb7e05a760e718d1ade164fd19 (commit)
from 8e6af2106e745285c5cda437d5856a99111686f8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 6f8e509988756deb7e05a760e718d1ade164fd19
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date: Sun Sep 16 21:55:57 2018 +0200
Add progress indicator for services
Feature #14186
Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>
diff --git a/package.json b/package.json
index 84d1510..dd16eea 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,8 @@
"react-transition-group": "2.4.0",
"redux": "4.0.0",
"redux-thunk": "2.3.0",
- "unionize": "2.1.2"
+ "unionize": "2.1.2",
+ "uuid": "3.3.2"
},
"scripts": {
"start": "react-scripts-ts start",
@@ -47,6 +48,7 @@
"@types/react-router-redux": "5.0.15",
"@types/redux-devtools": "3.0.44",
"@types/redux-form": "7.4.5",
+ "@types/uuid": "3.4.4",
"axios-mock-adapter": "1.15.0",
"enzyme": "3.4.4",
"enzyme-adapter-react-16": "1.2.0",
diff --git a/src/index.tsx b/src/index.tsx
index a070685..2fb236d 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -38,7 +38,6 @@ import { addRouteChangeHandlers } from './routes/route-change-handlers';
import { setCurrentTokenDialogApiHost } from '~/store/current-token-dialog/current-token-dialog-actions';
import { processResourceActionSet } from './views-components/context-menu/action-sets/process-resource-action-set';
import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions';
-import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
const getBuildNumber = () => "BN-" + (process.env.REACT_APP_BUILD_NUMBER || "dev");
const getGitCommit = () => "GIT-" + (process.env.REACT_APP_GIT_COMMIT || "latest").substr(0, 7);
@@ -63,13 +62,14 @@ addMenuActionSet(ContextMenuKind.TRASH, trashActionSet);
fetchConfig()
.then(({ config, apiHost }) => {
const history = createBrowserHistory();
- const services = createServices(config);
+ const services = createServices(config, (id, working) => {
+ store.dispatch(progressIndicatorActions.TOGGLE({ id, working }));
+ });
const store = configureStore(history, services);
store.subscribe(initListener(history, store, services, config));
store.dispatch(initAuth());
store.dispatch(setCurrentTokenDialogApiHost(apiHost));
- store.dispatch(progressIndicatorActions.START_SUBMIT({ id: ProgressIndicatorData.SIDE_PANEL_PROGRESS }));
const TokenComponent = (props: any) => <ApiToken authService={services.authService} {...props} />;
const WorkbenchComponent = (props: any) => <Workbench authService={services.authService} buildInfo={buildInfo} {...props} />;
diff --git a/src/services/api/api-progress.ts b/src/services/api/api-progress.ts
new file mode 100644
index 0000000..14dc584
--- /dev/null
+++ b/src/services/api/api-progress.ts
@@ -0,0 +1,5 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export type ProgressFn = (id: string, working: boolean) => void;
diff --git a/src/services/api/url-builder.test.ts b/src/services/api/url-builder.test.ts
new file mode 100644
index 0000000..2b48940
--- /dev/null
+++ b/src/services/api/url-builder.test.ts
@@ -0,0 +1,36 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { OrderBuilder } from "./order-builder";
+import { joinUrls } from "~/services/api/url-builder";
+
+describe("UrlBuilder", () => {
+ it("should join urls properly 1", () => {
+ expect(joinUrls('http://localhost:3000', '/main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 2", () => {
+ expect(joinUrls('http://localhost:3000/', '/main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 3", () => {
+ expect(joinUrls('http://localhost:3000//', '/main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 4", () => {
+ expect(joinUrls('http://localhost:3000', '//main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 5", () => {
+ expect(joinUrls('http://localhost:3000///', 'main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 6", () => {
+ expect(joinUrls('http://localhost:3000///', '//main')).toEqual('http://localhost:3000/main');
+ });
+ it("should join urls properly 7", () => {
+ expect(joinUrls(undefined, '//main')).toEqual('/main');
+ });
+ it("should join urls properly 8", () => {
+ expect(joinUrls(undefined, 'main')).toEqual('/main');
+ });
+ it("should join urls properly 9", () => {
+ expect(joinUrls('http://localhost:3000///', undefined)).toEqual('http://localhost:3000');
+ });
+});
diff --git a/src/services/api/url-builder.ts b/src/services/api/url-builder.ts
index 0587c83..32039a5 100644
--- a/src/services/api/url-builder.ts
+++ b/src/services/api/url-builder.ts
@@ -24,3 +24,24 @@ export class UrlBuilder {
return this.url + this.query;
}
}
+
+export function joinUrls(url0?: string, url1?: string) {
+ let u0 = "";
+ if (url0) {
+ let idx0 = url0.length - 1;
+ while (url0[idx0] === '/') { --idx0; }
+ u0 = url0.substr(0, idx0 + 1);
+ }
+ let u1 = "";
+ if (url1) {
+ let idx1 = 0;
+ while (url1[idx1] === '/') { ++idx1; }
+ u1 = url1.substr(idx1);
+ }
+ let url = u0;
+ if (u1.length > 0) {
+ url += '/';
+ }
+ url += u1;
+ return url;
+}
diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts
index 57915f7..89545c1 100644
--- a/src/services/auth-service/auth-service.ts
+++ b/src/services/auth-service/auth-service.ts
@@ -4,6 +4,8 @@
import { User } from "~/models/user";
import { AxiosInstance } from "axios";
+import { ProgressFn } from "~/services/api/api-progress";
+import * as uuid from "uuid/v4";
export const API_TOKEN_KEY = 'apiToken';
export const USER_EMAIL_KEY = 'userEmail';
@@ -25,7 +27,8 @@ export class AuthService {
constructor(
protected apiClient: AxiosInstance,
- protected baseUrl: string) { }
+ protected baseUrl: string,
+ protected progressFn: ProgressFn) { }
public saveApiToken(token: string) {
localStorage.setItem(API_TOKEN_KEY, token);
@@ -86,15 +89,24 @@ export class AuthService {
}
public getUserDetails = (): Promise<User> => {
+ const reqId = uuid();
+ this.progressFn(reqId, true);
return this.apiClient
.get<UserDetailsResponse>('/users/current')
- .then(resp => ({
- email: resp.data.email,
- firstName: resp.data.first_name,
- lastName: resp.data.last_name,
- uuid: resp.data.uuid,
- ownerUuid: resp.data.owner_uuid
- }));
+ .then(resp => {
+ this.progressFn(reqId, false);
+ return {
+ email: resp.data.email,
+ firstName: resp.data.first_name,
+ lastName: resp.data.last_name,
+ uuid: resp.data.uuid,
+ ownerUuid: resp.data.owner_uuid
+ };
+ })
+ .catch(e => {
+ this.progressFn(reqId, false);
+ throw e;
+ });
}
public getRootUuid() {
diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts
index 6e6f2a9..6a60ebf 100644
--- a/src/services/collection-service/collection-service.ts
+++ b/src/services/collection-service/collection-service.ts
@@ -11,12 +11,13 @@ import { mapTreeValues } from "~/models/tree";
import { parseFilesResponse } from "./collection-service-files-response";
import { fileToArrayBuffer } from "~/common/file";
import { TrashableResourceService } from "~/services/common-service/trashable-resource-service";
+import { ProgressFn } from "~/services/api/api-progress";
export type UploadProgress = (fileId: number, loaded: number, total: number, currentTime: number) => void;
export class CollectionService extends TrashableResourceService<CollectionResource> {
- constructor(serverApi: AxiosInstance, private webdavClient: WebDAV, private authService: AuthService) {
- super(serverApi, "collections");
+ constructor(serverApi: AxiosInstance, private webdavClient: WebDAV, private authService: AuthService, progressFn: ProgressFn) {
+ super(serverApi, "collections", progressFn);
}
async files(uuid: string) {
diff --git a/src/services/common-service/common-resource-service.test.ts b/src/services/common-service/common-resource-service.test.ts
index d67d5db..385485d 100644
--- a/src/services/common-service/common-resource-service.test.ts
+++ b/src/services/common-service/common-resource-service.test.ts
@@ -6,11 +6,13 @@ import { CommonResourceService } from "./common-resource-service";
import axios, { AxiosInstance } from "axios";
import MockAdapter from "axios-mock-adapter";
import { Resource } from "src/models/resource";
+import { ProgressFn } from "~/services/api/api-progress";
-export const mockResourceService = <R extends Resource, C extends CommonResourceService<R>>(Service: new (client: AxiosInstance) => C) => {
+export const mockResourceService = <R extends Resource, C extends CommonResourceService<R>>(
+ Service: new (client: AxiosInstance, progressFn: ProgressFn) => C) => {
const axiosInstance = axios.create();
const axiosMock = new MockAdapter(axiosInstance);
- const service = new Service(axiosInstance);
+ const service = new Service(axiosInstance, (id, working) => {});
Object.keys(service).map(key => service[key] = jest.fn());
return service;
};
@@ -18,6 +20,7 @@ export const mockResourceService = <R extends Resource, C extends CommonResource
describe("CommonResourceService", () => {
const axiosInstance = axios.create();
const axiosMock = new MockAdapter(axiosInstance);
+ const progressFn = (id: string, working: boolean) => {};
beforeEach(() => {
axiosMock.reset();
@@ -28,14 +31,14 @@ describe("CommonResourceService", () => {
.onPost("/resource/")
.reply(200, { owner_uuid: "ownerUuidValue" });
- const commonResourceService = new CommonResourceService(axiosInstance, "resource");
+ const commonResourceService = new CommonResourceService(axiosInstance, "resource", progressFn);
const resource = await commonResourceService.create({ ownerUuid: "ownerUuidValue" });
expect(resource).toEqual({ ownerUuid: "ownerUuidValue" });
});
it("#create maps request params to snake case", async () => {
axiosInstance.post = jest.fn(() => Promise.resolve({data: {}}));
- const commonResourceService = new CommonResourceService(axiosInstance, "resource");
+ const commonResourceService = new CommonResourceService(axiosInstance, "resource", progressFn);
await commonResourceService.create({ ownerUuid: "ownerUuidValue" });
expect(axiosInstance.post).toHaveBeenCalledWith("/resource/", {owner_uuid: "ownerUuidValue"});
});
@@ -45,7 +48,7 @@ describe("CommonResourceService", () => {
.onDelete("/resource/uuid")
.reply(200, { deleted_at: "now" });
- const commonResourceService = new CommonResourceService(axiosInstance, "resource");
+ const commonResourceService = new CommonResourceService(axiosInstance, "resource", progressFn);
const resource = await commonResourceService.delete("uuid");
expect(resource).toEqual({ deletedAt: "now" });
});
@@ -55,7 +58,7 @@ describe("CommonResourceService", () => {
.onGet("/resource/uuid")
.reply(200, { modified_at: "now" });
- const commonResourceService = new CommonResourceService(axiosInstance, "resource");
+ const commonResourceService = new CommonResourceService(axiosInstance, "resource", progressFn);
const resource = await commonResourceService.get("uuid");
expect(resource).toEqual({ modifiedAt: "now" });
});
@@ -73,7 +76,7 @@ describe("CommonResourceService", () => {
items_available: 20
});
- const commonResourceService = new CommonResourceService(axiosInstance, "resource");
+ const commonResourceService = new CommonResourceService(axiosInstance, "resource", progressFn);
const resource = await commonResourceService.list({ limit: 10, offset: 1 });
expect(resource).toEqual({
kind: "kind",
diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts
index 09e034f..0ad6fbc 100644
--- a/src/services/common-service/common-resource-service.ts
+++ b/src/services/common-service/common-resource-service.ts
@@ -5,6 +5,8 @@
import * as _ from "lodash";
import { AxiosInstance, AxiosPromise } from "axios";
import { Resource } from "src/models/resource";
+import * as uuid from "uuid/v4";
+import { ProgressFn } from "~/services/api/api-progress";
export interface ListArguments {
limit?: number;
@@ -60,36 +62,53 @@ export class CommonResourceService<T extends Resource> {
}
}
- static defaultResponse<R>(promise: AxiosPromise<R>): Promise<R> {
+ static defaultResponse<R>(promise: AxiosPromise<R>, progressFn: ProgressFn): Promise<R> {
+ const reqId = uuid();
+ progressFn(reqId, true);
return promise
+ .then(data => {
+ progressFn(reqId, false);
+ return data;
+ })
.then(CommonResourceService.mapResponseKeys)
- .catch(({ response }) => Promise.reject<Errors>(CommonResourceService.mapResponseKeys(response)));
+ .catch(({ response }) => {
+ progressFn(reqId, false);
+ Promise.reject<Errors>(CommonResourceService.mapResponseKeys(response));
+ });
}
protected serverApi: AxiosInstance;
protected resourceType: string;
+ protected progressFn: ProgressFn;
- constructor(serverApi: AxiosInstance, resourceType: string) {
+ constructor(serverApi: AxiosInstance, resourceType: string, onProgress: ProgressFn) {
this.serverApi = serverApi;
this.resourceType = '/' + resourceType + '/';
+ this.progressFn = onProgress;
}
create(data?: Partial<T> | any) {
return CommonResourceService.defaultResponse(
this.serverApi
- .post<T>(this.resourceType, data && CommonResourceService.mapKeys(_.snakeCase)(data)));
+ .post<T>(this.resourceType, data && CommonResourceService.mapKeys(_.snakeCase)(data)),
+ this.progressFn
+ );
}
delete(uuid: string): Promise<T> {
return CommonResourceService.defaultResponse(
this.serverApi
- .delete(this.resourceType + uuid));
+ .delete(this.resourceType + uuid),
+ this.progressFn
+ );
}
get(uuid: string) {
return CommonResourceService.defaultResponse(
this.serverApi
- .get<T>(this.resourceType + uuid));
+ .get<T>(this.resourceType + uuid),
+ this.progressFn
+ );
}
list(args: ListArguments = {}): Promise<ListResults<T>> {
@@ -103,14 +122,17 @@ export class CommonResourceService<T extends Resource> {
this.serverApi
.get(this.resourceType, {
params: CommonResourceService.mapKeys(_.snakeCase)(params)
- }));
+ }),
+ this.progressFn
+ );
}
update(uuid: string, data: Partial<T>) {
return CommonResourceService.defaultResponse(
this.serverApi
- .put<T>(this.resourceType + uuid, data && CommonResourceService.mapKeys(_.snakeCase)(data)));
-
+ .put<T>(this.resourceType + uuid, data && CommonResourceService.mapKeys(_.snakeCase)(data)),
+ this.progressFn
+ );
}
}
diff --git a/src/services/common-service/trashable-resource-service.ts b/src/services/common-service/trashable-resource-service.ts
index 23e7366..92e0273 100644
--- a/src/services/common-service/trashable-resource-service.ts
+++ b/src/services/common-service/trashable-resource-service.ts
@@ -6,27 +6,32 @@ import * as _ from "lodash";
import { AxiosInstance } from "axios";
import { TrashableResource } from "src/models/resource";
import { CommonResourceService } from "~/services/common-service/common-resource-service";
+import { ProgressFn } from "~/services/api/api-progress";
export class TrashableResourceService<T extends TrashableResource> extends CommonResourceService<T> {
- constructor(serverApi: AxiosInstance, resourceType: string) {
- super(serverApi, resourceType);
+ constructor(serverApi: AxiosInstance, resourceType: string, progressFn: ProgressFn) {
+ super(serverApi, resourceType, progressFn);
}
trash(uuid: string): Promise<T> {
- return this.serverApi
- .post(this.resourceType + `${uuid}/trash`)
- .then(CommonResourceService.mapResponseKeys);
+ return CommonResourceService.defaultResponse(
+ this.serverApi
+ .post(this.resourceType + `${uuid}/trash`),
+ this.progressFn
+ );
}
untrash(uuid: string): Promise<T> {
const params = {
ensure_unique_name: true
};
- return this.serverApi
- .post(this.resourceType + `${uuid}/untrash`, {
- params: CommonResourceService.mapKeys(_.snakeCase)(params)
- })
- .then(CommonResourceService.mapResponseKeys);
+ return CommonResourceService.defaultResponse(
+ this.serverApi
+ .post(this.resourceType + `${uuid}/untrash`, {
+ params: CommonResourceService.mapKeys(_.snakeCase)(params)
+ }),
+ this.progressFn
+ );
}
}
diff --git a/src/services/container-request-service/container-request-service.ts b/src/services/container-request-service/container-request-service.ts
index 01805ff..6ee44d2 100644
--- a/src/services/container-request-service/container-request-service.ts
+++ b/src/services/container-request-service/container-request-service.ts
@@ -4,10 +4,11 @@
import { CommonResourceService } from "~/services/common-service/common-resource-service";
import { AxiosInstance } from "axios";
-import { ContainerRequestResource } from '../../models/container-request';
+import { ContainerRequestResource } from '~/models/container-request';
+import { ProgressFn } from "~/services/api/api-progress";
export class ContainerRequestService extends CommonResourceService<ContainerRequestResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "container_requests");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "container_requests", progressFn);
}
}
diff --git a/src/services/container-service/container-service.ts b/src/services/container-service/container-service.ts
index 0ace1f6..2f5b712 100644
--- a/src/services/container-service/container-service.ts
+++ b/src/services/container-service/container-service.ts
@@ -4,10 +4,11 @@
import { CommonResourceService } from "~/services/common-service/common-resource-service";
import { AxiosInstance } from "axios";
-import { ContainerResource } from '../../models/container';
+import { ContainerResource } from '~/models/container';
+import { ProgressFn } from "~/services/api/api-progress";
export class ContainerService extends CommonResourceService<ContainerResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "containers");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "containers", progressFn);
}
}
diff --git a/src/services/favorite-service/favorite-service.ts b/src/services/favorite-service/favorite-service.ts
index 4601054..92b0713 100644
--- a/src/services/favorite-service/favorite-service.ts
+++ b/src/services/favorite-service/favorite-service.ts
@@ -19,7 +19,7 @@ export interface FavoriteListArguments {
export class FavoriteService {
constructor(
private linkService: LinkService,
- private groupsService: GroupsService
+ private groupsService: GroupsService,
) {}
create(data: { userUuid: string; resource: { uuid: string; name: string } }) {
diff --git a/src/services/groups-service/groups-service.test.ts b/src/services/groups-service/groups-service.test.ts
index e1157f4..d88b3c5 100644
--- a/src/services/groups-service/groups-service.test.ts
+++ b/src/services/groups-service/groups-service.test.ts
@@ -27,7 +27,7 @@ describe("GroupsService", () => {
items_available: 20
});
- const groupsService = new GroupsService(axios);
+ const groupsService = new GroupsService(axios, (id, working) => {});
const resource = await groupsService.contents("1", { limit: 10, offset: 1 });
expect(resource).toEqual({
kind: "kind",
diff --git a/src/services/groups-service/groups-service.ts b/src/services/groups-service/groups-service.ts
index b285e92..fe337ef 100644
--- a/src/services/groups-service/groups-service.ts
+++ b/src/services/groups-service/groups-service.ts
@@ -10,6 +10,7 @@ import { ProjectResource } from "~/models/project";
import { ProcessResource } from "~/models/process";
import { TrashableResource } from "~/models/resource";
import { TrashableResourceService } from "~/services/common-service/trashable-resource-service";
+import { ProgressFn } from "~/services/api/api-progress";
export interface ContentsArguments {
limit?: number;
@@ -27,8 +28,8 @@ export type GroupContentsResource =
export class GroupsService<T extends TrashableResource = TrashableResource> extends TrashableResourceService<T> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "groups");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "groups", progressFn);
}
contents(uuid: string, args: ContentsArguments = {}): Promise<ListResults<GroupContentsResource>> {
@@ -38,11 +39,13 @@ export class GroupsService<T extends TrashableResource = TrashableResource> exte
filters: filters ? `[${filters}]` : undefined,
order: order ? order : undefined
};
- return this.serverApi
- .get(this.resourceType + `${uuid}/contents`, {
- params: CommonResourceService.mapKeys(_.snakeCase)(params)
- })
- .then(CommonResourceService.mapResponseKeys);
+ return CommonResourceService.defaultResponse(
+ this.serverApi
+ .get(this.resourceType + `${uuid}/contents`, {
+ params: CommonResourceService.mapKeys(_.snakeCase)(params)
+ }),
+ this.progressFn
+ );
}
}
diff --git a/src/services/keep-service/keep-service.ts b/src/services/keep-service/keep-service.ts
index 77d06d9..f28629f 100644
--- a/src/services/keep-service/keep-service.ts
+++ b/src/services/keep-service/keep-service.ts
@@ -5,9 +5,10 @@
import { CommonResourceService } from "~/services/common-service/common-resource-service";
import { AxiosInstance } from "axios";
import { KeepResource } from "~/models/keep";
+import { ProgressFn } from "~/services/api/api-progress";
export class KeepService extends CommonResourceService<KeepResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "keep_services");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "keep_services", progressFn);
}
}
diff --git a/src/services/link-service/link-service.ts b/src/services/link-service/link-service.ts
index c77def5..67c1a87 100644
--- a/src/services/link-service/link-service.ts
+++ b/src/services/link-service/link-service.ts
@@ -5,9 +5,10 @@
import { CommonResourceService } from "~/services/common-service/common-resource-service";
import { LinkResource } from "~/models/link";
import { AxiosInstance } from "axios";
+import { ProgressFn } from "~/services/api/api-progress";
export class LinkService extends CommonResourceService<LinkResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "links");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "links", progressFn);
}
}
diff --git a/src/services/log-service/log-service.ts b/src/services/log-service/log-service.ts
index 8f6c66c..7f78d95 100644
--- a/src/services/log-service/log-service.ts
+++ b/src/services/log-service/log-service.ts
@@ -5,9 +5,10 @@
import { AxiosInstance } from "axios";
import { LogResource } from '~/models/log';
import { CommonResourceService } from "~/services/common-service/common-resource-service";
+import { ProgressFn } from "~/services/api/api-progress";
export class LogService extends CommonResourceService<LogResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "logs");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "logs", progressFn);
}
}
diff --git a/src/services/project-service/project-service.test.ts b/src/services/project-service/project-service.test.ts
index 11c2f61..5647ded 100644
--- a/src/services/project-service/project-service.test.ts
+++ b/src/services/project-service/project-service.test.ts
@@ -11,7 +11,7 @@ describe("CommonResourceService", () => {
it(`#create has groupClass set to "project"`, async () => {
axiosInstance.post = jest.fn(() => Promise.resolve({ data: {} }));
- const projectService = new ProjectService(axiosInstance);
+ const projectService = new ProjectService(axiosInstance, (id, working) => {});
const resource = await projectService.create({ name: "nameValue" });
expect(axiosInstance.post).toHaveBeenCalledWith("/groups/", {
name: "nameValue",
@@ -21,7 +21,7 @@ describe("CommonResourceService", () => {
it("#list has groupClass filter set by default", async () => {
axiosInstance.get = jest.fn(() => Promise.resolve({ data: {} }));
- const projectService = new ProjectService(axiosInstance);
+ const projectService = new ProjectService(axiosInstance, (id, working) => {});
const resource = await projectService.list();
expect(axiosInstance.get).toHaveBeenCalledWith("/groups/", {
params: {
diff --git a/src/services/services.ts b/src/services/services.ts
index 53721dd..bd73c74 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -12,8 +12,8 @@ import { CollectionService } from "./collection-service/collection-service";
import { TagService } from "./tag-service/tag-service";
import { CollectionFilesService } from "./collection-files-service/collection-files-service";
import { KeepService } from "./keep-service/keep-service";
-import { WebDAV } from "../common/webdav";
-import { Config } from "../common/config";
+import { WebDAV } from "~/common/webdav";
+import { Config } from "~/common/config";
import { UserService } from './user-service/user-service';
import { AncestorService } from "~/services/ancestors-service/ancestors-service";
import { ResourceKind } from "~/models/resource";
@@ -23,25 +23,25 @@ import { LogService } from './log-service/log-service';
export type ServiceRepository = ReturnType<typeof createServices>;
-export const createServices = (config: Config) => {
+export const createServices = (config: Config, progressFn: (id: string, working: boolean) => void) => {
const apiClient = Axios.create();
apiClient.defaults.baseURL = config.baseUrl;
const webdavClient = new WebDAV();
webdavClient.defaults.baseURL = config.keepWebServiceUrl;
- const containerRequestService = new ContainerRequestService(apiClient);
- const containerService = new ContainerService(apiClient);
- const groupsService = new GroupsService(apiClient);
- const keepService = new KeepService(apiClient);
- const linkService = new LinkService(apiClient);
- const logService = new LogService(apiClient);
- const projectService = new ProjectService(apiClient);
- const userService = new UserService(apiClient);
-
+ const containerRequestService = new ContainerRequestService(apiClient, progressFn);
+ const containerService = new ContainerService(apiClient, progressFn);
+ const groupsService = new GroupsService(apiClient, progressFn);
+ const keepService = new KeepService(apiClient, progressFn);
+ const linkService = new LinkService(apiClient, progressFn);
+ const logService = new LogService(apiClient, progressFn);
+ const projectService = new ProjectService(apiClient, progressFn);
+ const userService = new UserService(apiClient, progressFn);
+
const ancestorsService = new AncestorService(groupsService, userService);
- const authService = new AuthService(apiClient, config.rootUrl);
- const collectionService = new CollectionService(apiClient, webdavClient, authService);
+ const authService = new AuthService(apiClient, config.rootUrl, progressFn);
+ const collectionService = new CollectionService(apiClient, webdavClient, authService, progressFn);
const collectionFilesService = new CollectionFilesService(collectionService);
const favoriteService = new FavoriteService(linkService, groupsService);
const tagService = new TagService(linkService);
@@ -77,4 +77,4 @@ export const getResourceService = (kind?: ResourceKind) => (serviceRepository: S
default:
return undefined;
}
-};
\ No newline at end of file
+};
diff --git a/src/services/user-service/user-service.ts b/src/services/user-service/user-service.ts
index 31cc4bb..cd8b6a4 100644
--- a/src/services/user-service/user-service.ts
+++ b/src/services/user-service/user-service.ts
@@ -5,9 +5,10 @@
import { AxiosInstance } from "axios";
import { CommonResourceService } from "~/services/common-service/common-resource-service";
import { UserResource } from "~/models/user";
+import { ProgressFn } from "~/services/api/api-progress";
export class UserService extends CommonResourceService<UserResource> {
- constructor(serverApi: AxiosInstance) {
- super(serverApi, "users");
+ constructor(serverApi: AxiosInstance, progressFn: ProgressFn) {
+ super(serverApi, "users", progressFn);
}
}
diff --git a/src/store/auth/auth-actions.test.ts b/src/store/auth/auth-actions.test.ts
index 4ac48a0..46d2835 100644
--- a/src/store/auth/auth-actions.test.ts
+++ b/src/store/auth/auth-actions.test.ts
@@ -22,11 +22,12 @@ import { mockConfig } from '~/common/config';
describe('auth-actions', () => {
let reducer: (state: AuthState | undefined, action: AuthAction) => any;
let store: RootStore;
+ const progressFn = (id: string, working: boolean) => {};
beforeEach(() => {
- store = configureStore(createBrowserHistory(), createServices(mockConfig({})));
+ store = configureStore(createBrowserHistory(), createServices(mockConfig({}), progressFn));
localStorage.clear();
- reducer = authReducer(createServices(mockConfig({})));
+ reducer = authReducer(createServices(mockConfig({}), progressFn));
});
it('should initialise state with user and api token from local storage', () => {
diff --git a/src/store/auth/auth-reducer.test.ts b/src/store/auth/auth-reducer.test.ts
index 2b1920a..c8e2ccb 100644
--- a/src/store/auth/auth-reducer.test.ts
+++ b/src/store/auth/auth-reducer.test.ts
@@ -11,10 +11,11 @@ import { mockConfig } from '~/common/config';
describe('auth-reducer', () => {
let reducer: (state: AuthState | undefined, action: AuthAction) => any;
+ const progressFn = (id: string, working: boolean) => {};
beforeAll(() => {
localStorage.clear();
- reducer = authReducer(createServices(mockConfig({})));
+ reducer = authReducer(createServices(mockConfig({}), progressFn));
});
it('should correctly initialise state', () => {
diff --git a/src/store/progress-indicator/progress-indicator-actions.ts b/src/store/progress-indicator/progress-indicator-actions.ts
index 5f824e4..3712e41 100644
--- a/src/store/progress-indicator/progress-indicator-actions.ts
+++ b/src/store/progress-indicator/progress-indicator-actions.ts
@@ -5,8 +5,9 @@
import { unionize, ofType, UnionOf } from "~/common/unionize";
export const progressIndicatorActions = unionize({
- START_SUBMIT: ofType<{ id: string }>(),
- STOP_SUBMIT: ofType<{ id: string }>()
+ START: ofType<string>(),
+ STOP: ofType<string>(),
+ TOGGLE: ofType<{ id: string, working: boolean }>()
});
-export type ProgressIndicatorAction = UnionOf<typeof progressIndicatorActions>;
\ No newline at end of file
+export type ProgressIndicatorAction = UnionOf<typeof progressIndicatorActions>;
diff --git a/src/store/progress-indicator/progress-indicator-reducer.ts b/src/store/progress-indicator/progress-indicator-reducer.ts
index daacdb7..190ad13 100644
--- a/src/store/progress-indicator/progress-indicator-reducer.ts
+++ b/src/store/progress-indicator/progress-indicator-reducer.ts
@@ -3,45 +3,25 @@
// SPDX-License-Identifier: AGPL-3.0
import { ProgressIndicatorAction, progressIndicatorActions } from "~/store/progress-indicator/progress-indicator-actions";
-import { Dispatch } from 'redux';
-import { RootState } from '~/store/store';
-import { ServiceRepository } from '~/services/services';
export interface ProgressIndicatorState {
- 'sidePanelProgress': { started: boolean };
- 'contentProgress': { started: boolean };
- // 'workbenchProgress': { started: boolean };
+ [key: string]: {
+ working: boolean
+ };
}
const initialState: ProgressIndicatorState = {
- 'sidePanelProgress': { started: false },
- 'contentProgress': { started: false },
- // 'workbenchProgress': { started: false }
};
-export enum ProgressIndicatorData {
- SIDE_PANEL_PROGRESS = 'sidePanelProgress',
- CONTENT_PROGRESS = 'contentProgress',
- // WORKBENCH_PROGRESS = 'workbenchProgress',
-}
-
export const progressIndicatorReducer = (state: ProgressIndicatorState = initialState, action: ProgressIndicatorAction) => {
return progressIndicatorActions.match(action, {
- START_SUBMIT: ({ id }) => ({ ...state, [id]: { started: true } }),
- STOP_SUBMIT: ({ id }) => ({
- ...state,
- [id]: state[id] ? { ...state[id], started: false } : { started: false }
- }),
+ START: id => ({ ...state, [id]: { working: true } }),
+ STOP: id => ({ ...state, [id]: { working: false } }),
+ TOGGLE: ({ id, working }) => ({ ...state, [id]: { working }}),
default: () => state,
});
};
-// export const getProgress = () =>
-// (dispatch: Dispatch, getState: () => RootState) => {
-// const progress = getState().progressIndicator;
-// if (progress.sidePanelProgress.started || progress.contentProgress.started) {
-// dispatch(progressIndicatorActions.START_SUBMIT({ id: ProgressIndicatorData.WORKBENCH_PROGRESS }));
-// } else {
-// dispatch(progressIndicatorActions.STOP_SUBMIT({ id: ProgressIndicatorData.WORKBENCH_PROGRESS }));
-// }
-// };
+export function isSystemWorking(state: ProgressIndicatorState): boolean {
+ return Object.keys(state).reduce((working, k) => working ? true : state[k].working, false);
+}
diff --git a/src/store/progress-indicator/with-progress.ts b/src/store/progress-indicator/with-progress.ts
index b91c05d..976f757 100644
--- a/src/store/progress-indicator/with-progress.ts
+++ b/src/store/progress-indicator/with-progress.ts
@@ -1,20 +1,20 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
+// // Copyright (C) The Arvados Authors. All rights reserved.
+// //
+// // SPDX-License-Identifier: AGPL-3.0
//
-// SPDX-License-Identifier: AGPL-3.0
-
-import * as React from 'react';
-import { connect } from 'react-redux';
-import { RootState } from '~/store/store';
-
-export type WithProgressStateProps = {
- started: boolean;
-};
-
-export const withProgress = (id: string) =>
- (component: React.ComponentType<WithProgressStateProps>) =>
- connect(mapStateToProps(id))(component);
-
-export const mapStateToProps = (id: string) => (state: RootState): WithProgressStateProps => {
- const progress = state.progressIndicator[id];
- return progress;
-};
\ No newline at end of file
+// import * as React from 'react';
+// import { connect } from 'react-redux';
+// import { RootState } from '~/store/store';
+//
+// export type WithProgressStateProps = {
+// started: boolean;
+// };
+//
+// export const withProgress = (id: string) =>
+// (component: React.ComponentType<WithProgressStateProps>) =>
+// connect(mapStateToProps(id))(component);
+//
+// export const mapStateToProps = (id: string) => (state: RootState): WithProgressStateProps => {
+// const progress = state.progressIndicator[id];
+// return progress;
+// };
diff --git a/src/store/side-panel-tree/side-panel-tree-actions.ts b/src/store/side-panel-tree/side-panel-tree-actions.ts
index c7ad91b..561df1d 100644
--- a/src/store/side-panel-tree/side-panel-tree-actions.ts
+++ b/src/store/side-panel-tree/side-panel-tree-actions.ts
@@ -14,7 +14,6 @@ import { TreeItemStatus } from "~/components/tree/tree";
import { getNodeAncestors, getNodeValue, getNodeAncestorsIds, getNode } from '~/models/tree';
import { ProjectResource } from '~/models/project';
import { progressIndicatorActions } from '../progress-indicator/progress-indicator-actions';
-import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
export enum SidePanelTreeCategory {
PROJECTS = 'Projects',
@@ -101,7 +100,6 @@ export const activateSidePanelTreeItem = (nodeId: string) =>
if (!isSidePanelTreeCategory(nodeId)) {
await dispatch<any>(activateSidePanelTreeProject(nodeId));
}
- dispatch(progressIndicatorActions.STOP_SUBMIT({ id: ProgressIndicatorData.SIDE_PANEL_PROGRESS }));
};
export const activateSidePanelTreeProject = (nodeId: string) =>
diff --git a/src/views-components/main-app-bar/main-app-bar.tsx b/src/views-components/main-app-bar/main-app-bar.tsx
index ec2a511..93cf496 100644
--- a/src/views-components/main-app-bar/main-app-bar.tsx
+++ b/src/views-components/main-app-bar/main-app-bar.tsx
@@ -13,6 +13,7 @@ import { NotificationsMenu } from "~/views-components/main-app-bar/notifications
import { AccountMenu } from "~/views-components/main-app-bar/account-menu";
import { AnonymousMenu } from "~/views-components/main-app-bar/anonymous-menu";
import { HelpMenu } from './help-menu';
+import { ReactNode } from "react";
type CssRules = 'toolbar' | 'link';
@@ -31,6 +32,7 @@ interface MainAppBarDataProps {
searchDebounce?: number;
user?: User;
buildInfo?: string;
+ children?: ReactNode;
}
export interface MainAppBarActionProps {
@@ -41,7 +43,7 @@ export type MainAppBarProps = MainAppBarDataProps & MainAppBarActionProps & With
export const MainAppBar = withStyles(styles)(
(props: MainAppBarProps) => {
- return <AppBar position="static">
+ return <AppBar position="absolute">
<Toolbar className={props.classes.toolbar}>
<Grid container justify="space-between">
<Grid container item xs={3} direction="column" justify="center">
@@ -80,6 +82,7 @@ export const MainAppBar = withStyles(styles)(
</Grid>
</Grid>
</Toolbar>
+ {props.children}
</AppBar>;
}
);
diff --git a/src/views-components/progress/content-progress.tsx b/src/views-components/progress/content-progress.tsx
index 0d291f4..fa2cad5 100644
--- a/src/views-components/progress/content-progress.tsx
+++ b/src/views-components/progress/content-progress.tsx
@@ -1,13 +1,13 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
+// // Copyright (C) The Arvados Authors. All rights reserved.
+// //
+// // SPDX-License-Identifier: AGPL-3.0
//
-// SPDX-License-Identifier: AGPL-3.0
-
-import * as React from 'react';
-import { CircularProgress } from '@material-ui/core';
-import { withProgress } from '~/store/progress-indicator/with-progress';
-import { WithProgressStateProps } from '~/store/progress-indicator/with-progress';
-import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
-
-export const ContentProgress = withProgress(ProgressIndicatorData.CONTENT_PROGRESS)((props: WithProgressStateProps) =>
- props.started ? <CircularProgress /> : null
-);
+// import * as React from 'react';
+// import { CircularProgress } from '@material-ui/core';
+// import { withProgress } from '~/store/progress-indicator/with-progress';
+// import { WithProgressStateProps } from '~/store/progress-indicator/with-progress';
+// import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
+//
+// export const ContentProgress = withProgress(ProgressIndicatorData.CONTENT_PROGRESS)((props: WithProgressStateProps) =>
+// props.started ? <CircularProgress /> : null
+// );
diff --git a/src/views-components/progress/side-panel-progress.tsx b/src/views-components/progress/side-panel-progress.tsx
index b3bc0db..2d832a5 100644
--- a/src/views-components/progress/side-panel-progress.tsx
+++ b/src/views-components/progress/side-panel-progress.tsx
@@ -1,13 +1,13 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
+// // Copyright (C) The Arvados Authors. All rights reserved.
+// //
+// // SPDX-License-Identifier: AGPL-3.0
//
-// SPDX-License-Identifier: AGPL-3.0
-
-import * as React from 'react';
-import { CircularProgress } from '@material-ui/core';
-import { withProgress } from '~/store/progress-indicator/with-progress';
-import { WithProgressStateProps } from '~/store/progress-indicator/with-progress';
-import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
-
-export const SidePanelProgress = withProgress(ProgressIndicatorData.SIDE_PANEL_PROGRESS)((props: WithProgressStateProps) =>
- props.started ? <span style={{ display: 'flex', justifyContent: 'center', marginTop: "40px" }}><CircularProgress /></span> : null
-);
+// import * as React from 'react';
+// import { CircularProgress } from '@material-ui/core';
+// import { withProgress } from '~/store/progress-indicator/with-progress';
+// import { WithProgressStateProps } from '~/store/progress-indicator/with-progress';
+// import { ProgressIndicatorData } from '~/store/progress-indicator/progress-indicator-reducer';
+//
+// export const SidePanelProgress = withProgress(ProgressIndicatorData.SIDE_PANEL_PROGRESS)((props: WithProgressStateProps) =>
+// props.started ? <span style={{ display: 'flex', justifyContent: 'center', marginTop: "40px" }}><CircularProgress /></span> : null
+// );
diff --git a/src/views-components/side-panel/side-panel.tsx b/src/views-components/side-panel/side-panel.tsx
index 780ecc7..739e9ea 100644
--- a/src/views-components/side-panel/side-panel.tsx
+++ b/src/views-components/side-panel/side-panel.tsx
@@ -12,7 +12,6 @@ import { navigateFromSidePanel } from '../../store/side-panel/side-panel-action'
import { Grid } from '@material-ui/core';
import { SidePanelButton } from '~/views-components/side-panel-button/side-panel-button';
import { RootState } from '~/store/store';
-import { SidePanelProgress } from '~/views-components/progress/side-panel-progress';
const DRAWER_WITDH = 240;
@@ -35,7 +34,6 @@ const mapDispatchToProps = (dispatch: Dispatch): SidePanelTreeProps => ({
});
const mapStateToProps = (state: RootState) => ({
- sidePanelProgress: state.progressIndicator.sidePanelProgress.started
});
export const SidePanel = compose(
@@ -44,5 +42,5 @@ export const SidePanel = compose(
)(({ classes, ...props }: WithStyles<CssRules> & SidePanelTreeProps) =>
<Grid item xs>
<SidePanelButton />
- {props.sidePanelProgress ? <SidePanelProgress /> : <SidePanelTree {...props} />}
- </Grid>);
\ No newline at end of file
+ <SidePanelTree {...props} />
+ </Grid>);
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index c5cb983..c22dde2 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -43,6 +43,7 @@ import { TrashPanel } from "~/views/trash-panel/trash-panel";
import { MainContentBar } from '~/views-components/main-content-bar/main-content-bar';
import { Grid, LinearProgress } from '@material-ui/core';
import { ProcessCommandDialog } from '~/views-components/process-command-dialog/process-command-dialog';
+import { isSystemWorking } from "~/store/progress-indicator/progress-indicator-reducer";
type CssRules = 'root' | 'asidePanel' | 'contentWrapper' | 'content' | 'appBar';
@@ -50,7 +51,8 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
root: {
overflow: 'hidden',
width: '100vw',
- height: '100vh'
+ height: '100vh',
+ paddingTop: theme.spacing.unit * 8
},
asidePanel: {
maxWidth: '240px',
@@ -74,8 +76,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
interface WorkbenchDataProps {
user?: User;
currentToken?: string;
- loadingSidePanel: boolean;
- loadingContent: boolean;
+ working: boolean;
}
interface WorkbenchGeneralProps {
@@ -94,8 +95,7 @@ export const Workbench = withStyles(styles)(
(state: RootState) => ({
user: state.auth.user,
currentToken: state.auth.apiToken,
- loadingSidePanel: state.progressIndicator.sidePanelProgress.started,
- loadingContent: state.progressIndicator.contentProgress.started
+ working: isSystemWorking(state.progressIndicator)
})
)(
class extends React.Component<WorkbenchProps, WorkbenchState> {
@@ -105,15 +105,14 @@ export const Workbench = withStyles(styles)(
render() {
const { classes } = this.props;
return <>
+ <MainAppBar
+ searchText={this.state.searchText}
+ user={this.props.user}
+ onSearch={this.onSearch}
+ buildInfo={this.props.buildInfo}>
+ {this.props.working ? <LinearProgress color="secondary" /> : null}
+ </MainAppBar>
<Grid container direction="column" className={classes.root}>
- <Grid className={classes.appBar}>
- <MainAppBar
- searchText={this.state.searchText}
- user={this.props.user}
- onSearch={this.onSearch}
- buildInfo={this.props.buildInfo} />
- </Grid>
- {this.props.loadingContent || this.props.loadingSidePanel ? <LinearProgress color="secondary" /> : null}
{this.props.user &&
<Grid container item xs alignItems="stretch" wrap="nowrap">
<Grid container item xs component='aside' direction='column' className={classes.asidePanel}>
diff --git a/tslint.json b/tslint.json
index 85b4369..f9b81ca 100644
--- a/tslint.json
+++ b/tslint.json
@@ -14,7 +14,8 @@
"no-shadowed-variable": false,
"semicolon": true,
"array-type": false,
- "interface-over-type-literal": false
+ "interface-over-type-literal": false,
+ "no-empty": false
},
"linterOptions": {
"exclude": [
diff --git a/yarn.lock b/yarn.lock
index 3599271..45c879f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -199,6 +199,12 @@
"@types/react" "*"
redux "^3.6.0 || ^4.0.0"
+"@types/uuid at 3.4.4":
+ version "3.4.4"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5"
+ dependencies:
+ "@types/node" "*"
+
abab@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
@@ -7808,14 +7814,14 @@ utils-merge at 1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+uuid at 3.3.2, uuid@^3.1.0:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
+
uuid@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
-uuid@^3.1.0:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
-
validate-npm-package-license@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338"
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list