[ARVADOS-WORKBENCH2] created: 1.1.4-280-g0ce21e3
Git user
git at public.curoverse.com
Thu Jul 12 08:34:32 EDT 2018
at 0ce21e3487078a53f1b653446b5e615cd6dda709 (commit)
commit 0ce21e3487078a53f1b653446b5e615cd6dda709
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Thu Jul 12 14:34:21 2018 +0200
Unify use of Collection and Project resource types
Feature #13798
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --git a/src/models/collection.ts b/src/models/collection.ts
index cf5b4e6..8effd8e 100644
--- a/src/models/collection.ts
+++ b/src/models/collection.ts
@@ -2,13 +2,9 @@
//
// SPDX-License-Identifier: AGPL-3.0
-import { Resource as R } from "./resource";
import { Resource } from "../common/api/common-resource-service";
import { ResourceKind } from "./kinds";
-export interface Collection extends R {
-}
-
export interface CollectionResource extends Resource {
kind: ResourceKind.Collection;
name: string;
diff --git a/src/models/project.ts b/src/models/project.ts
index c44c8cc..1373ca7 100644
--- a/src/models/project.ts
+++ b/src/models/project.ts
@@ -2,12 +2,8 @@
//
// SPDX-License-Identifier: AGPL-3.0
-import { Resource as R } from "./resource";
import { GroupResource, GroupClass } from "./group";
-export interface Project extends R {
-}
-
export interface ProjectResource extends GroupResource {
groupClass: GroupClass.Project;
}
diff --git a/src/models/test-utils.ts b/src/models/test-utils.ts
new file mode 100644
index 0000000..aa8d96b
--- /dev/null
+++ b/src/models/test-utils.ts
@@ -0,0 +1,50 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { GroupClass, GroupResource } from "./group";
+import { ResourceKind } from "./kinds";
+import { Resource } from "../common/api/common-resource-service";
+
+type ResourceUnion = GroupResource;
+
+export const mockResource = (kind: ResourceKind, data: Partial<Exclude<ResourceUnion, "kind">>) => {
+ switch (kind) {
+ case ResourceKind.Group:
+ return mockGroupResource({ ...data, kind });
+ default:
+ return mockCommonResource({ ...data, kind });
+ }
+};
+
+export const mockGroupResource = (data: Partial<Exclude<GroupResource, "kind">>): GroupResource => ({
+ createdAt: "",
+ deleteAt: "",
+ description: "",
+ etag: "",
+ groupClass: null,
+ href: "",
+ isTrashed: false,
+ kind: ResourceKind.Group,
+ modifiedAt: "",
+ modifiedByClientUuid: "",
+ modifiedByUserUuid: "",
+ name: "",
+ ownerUuid: "",
+ properties: "",
+ trashAt: "",
+ uuid: "",
+ writeableBy: []
+});
+
+const mockCommonResource = <T extends Resource>(data: Partial<T> & { kind: ResourceKind }): Resource => ({
+ createdAt: "",
+ etag: "",
+ href: "",
+ kind: data.kind,
+ modifiedAt: "",
+ modifiedByClientUuid: "",
+ modifiedByUserUuid: "",
+ ownerUuid: "",
+ uuid: ""
+});
diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts
deleted file mode 100644
index 8412dea..0000000
--- a/src/services/collection-service/collection-service.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { serverApi } from "../../common/api/server-api";
-import FilterBuilder from "../../common/api/filter-builder";
-import { ArvadosResource } from "../response";
-import { Collection } from "../../models/collection";
-import { getResourceKind } from "../../models/resource";
-
-interface CollectionResource extends ArvadosResource {
- name: string;
- description: string;
- properties: any;
- portable_data_hash: string;
- manifest_text: string;
- replication_desired: number;
- replication_confirmed: number;
- replication_confirmed_at: string;
- trash_at: string;
- delete_at: string;
- is_trashed: boolean;
-}
-
-interface CollectionsResponse {
- offset: number;
- limit: number;
- items: CollectionResource[];
-}
-
-export default class CollectionService {
- public getCollectionList = (parentUuid?: string): Promise<Collection[]> => {
- if (parentUuid) {
- const fb = new FilterBuilder();
- fb.addLike("ownerUuid", parentUuid);
- return serverApi.get<CollectionsResponse>('/collections', { params: {
- filters: fb.serialize()
- }}).then(resp => {
- const collections = resp.data.items.map(g => ({
- name: g.name,
- createdAt: g.created_at,
- modifiedAt: g.modified_at,
- href: g.href,
- uuid: g.uuid,
- ownerUuid: g.owner_uuid,
- kind: getResourceKind(g.kind)
- } as Collection));
- return collections;
- });
- } else {
- return Promise.resolve([]);
- }
- }
-}
diff --git a/src/services/services.ts b/src/services/services.ts
index 1e9a74d..143e97b 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -3,12 +3,10 @@
// SPDX-License-Identifier: AGPL-3.0
import AuthService from "./auth-service/auth-service";
-import CollectionService from "./collection-service/collection-service";
import GroupsService from "./groups-service/groups-service";
import { serverApi } from "../common/api/server-api";
import ProjectService from "./project-service/project-service";
export const authService = new AuthService();
-export const collectionService = new CollectionService();
export const groupsService = new GroupsService(serverApi);
export const projectService = new ProjectService(serverApi);
diff --git a/src/store/collection/collection-action.ts b/src/store/collection/collection-action.ts
deleted file mode 100644
index f50e645..0000000
--- a/src/store/collection/collection-action.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { Collection } from "../../models/collection";
-import { default as unionize, ofType, UnionOf } from "unionize";
-import { Dispatch } from "redux";
-import { collectionService } from "../../services/services";
-
-const actions = unionize({
- CREATE_COLLECTION: ofType<Collection>(),
- REMOVE_COLLECTION: ofType<string>(),
- COLLECTIONS_REQUEST: ofType<any>(),
- COLLECTIONS_SUCCESS: ofType<{ collections: Collection[] }>(),
-}, {
- tag: 'type',
- value: 'payload'
-});
-
-export const getCollectionList = (parentUuid?: string) => (dispatch: Dispatch): Promise<Collection[]> => {
- dispatch(actions.COLLECTIONS_REQUEST());
- return collectionService.getCollectionList(parentUuid).then(collections => {
- dispatch(actions.COLLECTIONS_SUCCESS({collections}));
- return collections;
- });
-};
-
-export type CollectionAction = UnionOf<typeof actions>;
-export default actions;
diff --git a/src/store/collection/collection-reducer.test.ts b/src/store/collection/collection-reducer.test.ts
deleted file mode 100644
index 7bc1aec..0000000
--- a/src/store/collection/collection-reducer.test.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import collectionsReducer from "./collection-reducer";
-import actions from "./collection-action";
-import { ResourceKind } from "../../models/resource";
-
-describe('collection-reducer', () => {
- it('should add new collection to the list', () => {
- const initialState = undefined;
- const collection = {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.COLLECTION
- };
-
- const state = collectionsReducer(initialState, actions.CREATE_COLLECTION(collection));
- expect(state).toEqual([collection]);
- });
-
- it('should load collections', () => {
- const initialState = undefined;
- const collection = {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.COLLECTION
- };
-
- const collections = [collection, collection];
- const state = collectionsReducer(initialState, actions.COLLECTIONS_SUCCESS({ collections }));
- expect(state).toEqual([collection, collection]);
- });
-});
diff --git a/src/store/collection/collection-reducer.ts b/src/store/collection/collection-reducer.ts
deleted file mode 100644
index 5c257ea..0000000
--- a/src/store/collection/collection-reducer.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import actions, { CollectionAction } from "./collection-action";
-import { Collection } from "../../models/collection";
-
-export type CollectionState = Collection[];
-
-
-const collectionsReducer = (state: CollectionState = [], action: CollectionAction) => {
- return actions.match(action, {
- CREATE_COLLECTION: collection => [...state, collection],
- REMOVE_COLLECTION: () => state,
- COLLECTIONS_REQUEST: () => {
- return [];
- },
- COLLECTIONS_SUCCESS: ({ collections }) => {
- return collections;
- },
- default: () => state
- });
-};
-
-export default collectionsReducer;
diff --git a/src/store/navigation/navigation-action.ts b/src/store/navigation/navigation-action.ts
index 7ba245a..25cc003 100644
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@ -7,20 +7,17 @@ import projectActions, { getProjectList } from "../project/project-action";
import { push } from "react-router-redux";
import { TreeItemStatus } from "../../components/tree/tree";
import { findTreeItem } from "../project/project-reducer";
-import { Resource, ResourceKind as R } from "../../models/resource";
-import sidePanelActions from "../side-panel/side-panel-action";
import dataExplorerActions from "../data-explorer/data-explorer-action";
import { PROJECT_PANEL_ID } from "../../views/project-panel/project-panel";
import { RootState } from "../store";
-import { sidePanelData } from "../side-panel/side-panel-reducer";
-import { loadDetails } from "../details-panel/details-panel-action";
+import { Resource } from "../../common/api/common-resource-service";
import { ResourceKind } from "../../models/kinds";
-export const getResourceUrl = (resource: Resource): string => {
+export const getResourceUrl = <T extends Resource>(resource: T): string => {
switch (resource.kind) {
- case R.PROJECT: return `/projects/${resource.uuid}`;
- case R.COLLECTION: return `/collections/${resource.uuid}`;
- default: return "";
+ case ResourceKind.Project: return `/projects/${resource.uuid}`;
+ case ResourceKind.Collection: return `/collections/${resource.uuid}`;
+ default: return resource.href;
}
};
@@ -32,7 +29,7 @@ export enum ItemMode {
export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
(dispatch: Dispatch, getState: () => RootState) => {
- const { projects, router, sidePanel } = getState();
+ const { projects, router } = getState();
const treeItem = findTreeItem(projects.items, itemId);
if (treeItem) {
@@ -41,7 +38,7 @@ export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(treeItem.data.uuid));
}
- const resourceUrl = getResourceUrl({ ...treeItem.data });
+ const resourceUrl = getResourceUrl(treeItem.data);
if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
if (router.location && !router.location.pathname.includes(resourceUrl)) {
diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts
index c1a002f..3acf091 100644
--- a/src/store/project/project-action.ts
+++ b/src/store/project/project-action.ts
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: AGPL-3.0
import { default as unionize, ofType, UnionOf } from "unionize";
-import { Project, ProjectResource } from "../../models/project";
+import { ProjectResource } from "../../models/project";
import { projectService } from "../../services/services";
import { Dispatch } from "redux";
import { getResourceKind } from "../../models/resource";
@@ -19,7 +19,7 @@ const actions = unionize({
CREATE_PROJECT_ERROR: ofType<string>(),
REMOVE_PROJECT: ofType<string>(),
PROJECTS_REQUEST: ofType<string>(),
- PROJECTS_SUCCESS: ofType<{ projects: Project[], parentItemId?: string }>(),
+ PROJECTS_SUCCESS: ofType<{ projects: ProjectResource[], parentItemId?: string }>(),
TOGGLE_PROJECT_TREE_ITEM_OPEN: ofType<string>(),
TOGGLE_PROJECT_TREE_ITEM_ACTIVE: ofType<string>(),
RESET_PROJECT_TREE_ACTIVITY: ofType<string>()
@@ -34,11 +34,7 @@ export const getProjectList = (parentUuid: string = '') => (dispatch: Dispatch)
filters: FilterBuilder
.create<ProjectResource>()
.addEqual("ownerUuid", parentUuid)
- }).then(listResults => {
- const projects = listResults.items.map(item => ({
- ...item,
- kind: getResourceKind(item.kind)
- }));
+ }).then(({ items: projects }) => {
dispatch(actions.PROJECTS_SUCCESS({ projects, parentItemId: parentUuid }));
return projects;
});
diff --git a/src/store/project/project-reducer.test.ts b/src/store/project/project-reducer.test.ts
index f14ee9a..b2def81 100644
--- a/src/store/project/project-reducer.test.ts
+++ b/src/store/project/project-reducer.test.ts
@@ -5,21 +5,16 @@
import projectsReducer, { getTreePath } from "./project-reducer";
import actions from "./project-action";
import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
-import { ResourceKind } from "../../models/resource";
+import { ResourceKind } from "../../models/kinds";
+import { mockResource } from "../../models/test-utils";
+import { ProjectResource } from "../../models/project";
+import { GroupClass } from "../../models/group";
describe('project-reducer', () => {
it('should load projects', () => {
const initialState = undefined;
- const project = {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- };
+ const project = mockProject({ ownerUuid: "test123" });
const projects = [project, project];
const state = projectsReducer(initialState, actions.PROJECTS_SUCCESS({ projects, parentItemId: undefined }));
@@ -52,15 +47,7 @@ describe('project-reducer', () => {
it('should remove activity on projects list', () => {
const initialState = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- },
+ data: mockProject(),
id: "1",
open: true,
active: true,
@@ -71,15 +58,7 @@ describe('project-reducer', () => {
};
const project = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- },
+ data: { ...initialState.items[0] },
id: "1",
open: true,
active: false,
@@ -96,15 +75,7 @@ describe('project-reducer', () => {
it('should toggle project tree item activity', () => {
const initialState = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- },
+ data: mockProject(),
id: "1",
open: true,
active: false,
@@ -115,15 +86,7 @@ describe('project-reducer', () => {
};
const project = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT,
- },
+ data: { ...initialState.items[0] },
id: "1",
open: true,
active: true,
@@ -142,15 +105,7 @@ describe('project-reducer', () => {
it('should close project tree item ', () => {
const initialState = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- },
+ data: mockProject(),
id: "1",
open: true,
active: false,
@@ -162,15 +117,7 @@ describe('project-reducer', () => {
};
const project = {
items: [{
- data: {
- name: 'test',
- href: 'href',
- createdAt: '2018-01-01',
- modifiedAt: '2018-01-01',
- ownerUuid: 'owner-test123',
- uuid: 'test123',
- kind: ResourceKind.PROJECT
- },
+ data: { ...initialState.items[0] },
id: "1",
open: false,
active: false,
@@ -234,3 +181,5 @@ describe("findTreeBranch", () => {
});
});
+
+const mockProject = (data: Partial<ProjectResource> = {}) => mockResource(ResourceKind.Group, { ...data, groupClass: GroupClass.Project }) as ProjectResource;
diff --git a/src/store/project/project-reducer.ts b/src/store/project/project-reducer.ts
index 5693fb6..c008370 100644
--- a/src/store/project/project-reducer.ts
+++ b/src/store/project/project-reducer.ts
@@ -4,12 +4,12 @@
import * as _ from "lodash";
-import { Project } from "../../models/project";
import actions, { ProjectAction } from "./project-action";
import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
+import { ProjectResource } from "../../models/project";
export type ProjectState = {
- items: Array<TreeItem<Project>>,
+ items: Array<TreeItem<ProjectResource>>,
currentItemId: string,
creator: ProjectCreator
};
@@ -67,7 +67,7 @@ function resetTreeActivity<T>(tree: Array<TreeItem<T>>) {
}
}
-function updateProjectTree(tree: Array<TreeItem<Project>>, projects: Project[], parentItemId?: string): Array<TreeItem<Project>> {
+function updateProjectTree(tree: Array<TreeItem<ProjectResource>>, projects: ProjectResource[], parentItemId?: string): Array<TreeItem<ProjectResource>> {
let treeItem;
if (parentItemId) {
treeItem = findTreeItem(tree, parentItemId);
@@ -82,7 +82,7 @@ function updateProjectTree(tree: Array<TreeItem<Project>>, projects: Project[],
status: TreeItemStatus.Initial,
data: p,
items: []
- } as TreeItem<Project>));
+ } as TreeItem<ProjectResource>));
if (treeItem) {
treeItem.items = items;
diff --git a/src/store/store.ts b/src/store/store.ts
index f74b877..36f9203 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -11,7 +11,6 @@ import projectsReducer, { ProjectState } from "./project/project-reducer";
import sidePanelReducer, { SidePanelState } from './side-panel/side-panel-reducer';
import authReducer, { AuthState } from "./auth/auth-reducer";
import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer';
-import collectionsReducer, { CollectionState } from "./collection/collection-reducer";
import { projectPanelMiddleware } from '../store/project-panel/project-panel-middleware';
import detailsPanelReducer, { DetailsPanelState } from './details-panel/details-panel-reducer';
@@ -23,7 +22,6 @@ const composeEnhancers =
export interface RootState {
auth: AuthState;
projects: ProjectState;
- collections: CollectionState;
router: RouterState;
dataExplorer: DataExplorerState;
sidePanel: SidePanelState;
@@ -33,7 +31,6 @@ export interface RootState {
const rootReducer = combineReducers({
auth: authReducer,
projects: projectsReducer,
- collections: collectionsReducer,
router: routerReducer,
dataExplorer: dataExplorerReducer,
sidePanel: sidePanelReducer,
diff --git a/src/views-components/project-tree/project-tree.tsx b/src/views-components/project-tree/project-tree.tsx
index 511cbbb..17592a7 100644
--- a/src/views-components/project-tree/project-tree.tsx
+++ b/src/views-components/project-tree/project-tree.tsx
@@ -10,13 +10,13 @@ import ListItemIcon from '@material-ui/core/ListItemIcon';
import Typography from '@material-ui/core/Typography';
import Tree, { TreeItem, TreeItemStatus } from '../../components/tree/tree';
-import { Project } from '../../models/project';
+import { ProjectResource } from '../../models/project';
export interface ProjectTreeProps {
- projects: Array<TreeItem<Project>>;
+ projects: Array<TreeItem<ProjectResource>>;
toggleOpen: (id: string, status: TreeItemStatus) => void;
toggleActive: (id: string, status: TreeItemStatus) => void;
- onContextMenu: (event: React.MouseEvent<HTMLElement>, item: TreeItem<Project>) => void;
+ onContextMenu: (event: React.MouseEvent<HTMLElement>, item: TreeItem<ProjectResource>) => void;
}
class ProjectTree<T> extends React.Component<ProjectTreeProps & WithStyles<CssRules>> {
@@ -29,7 +29,7 @@ class ProjectTree<T> extends React.Component<ProjectTreeProps & WithStyles<CssRu
onContextMenu={onContextMenu}
toggleItemOpen={toggleOpen}
toggleItemActive={toggleActive}
- render={(project: TreeItem<Project>) =>
+ render={(project: TreeItem<ProjectResource>) =>
<span className={row}>
<ListItemIcon className={project.active ? active : ''}>
<i className="fas fa-folder" />
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index e7a8ae3..75cc336 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -18,7 +18,6 @@ import { Breadcrumb } from '../../components/breadcrumbs/breadcrumbs';
import { push } from 'react-router-redux';
import ProjectTree from '../../views-components/project-tree/project-tree';
import { TreeItem } from "../../components/tree/tree";
-import { Project } from "../../models/project";
import { getTreePath } from '../../store/project/project-reducer';
import sidePanelActions from '../../store/side-panel/side-panel-action';
import SidePanel, { SidePanelItem } from '../../components/side-panel/side-panel';
@@ -35,6 +34,7 @@ import { authService } from '../../services/services';
import detailsPanelActions, { loadDetails } from "../../store/details-panel/details-panel-action";
import { ResourceKind } from '../../models/kinds';
import { SidePanelIdentifiers } from '../../store/side-panel/side-panel-reducer';
+import { ProjectResource } from '../../models/project';
const drawerWidth = 240;
const appBarHeight = 100;
@@ -78,7 +78,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
});
interface WorkbenchDataProps {
- projects: Array<TreeItem<Project>>;
+ projects: Array<TreeItem<ProjectResource>>;
currentProjectId: string;
user?: User;
sidePanelItems: SidePanelItem[];
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list