Replaced getting top project list with more generic version
authorDaniel Kos <daniel.kos@contractors.roche.com>
Tue, 12 Jun 2018 07:13:59 +0000 (09:13 +0200)
committerDaniel Kos <daniel.kos@contractors.roche.com>
Tue, 12 Jun 2018 19:08:27 +0000 (21:08 +0200)
Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos@contractors.roche.com>

12 files changed:
src/common/api/filter-builder.ts [new file with mode: 0644]
src/common/api/server-api.ts [moved from src/common/server-api.ts with 100% similarity]
src/common/api/url-builder.ts [new file with mode: 0644]
src/components/api-token/api-token.tsx
src/index.tsx
src/services/auth-service/auth-service.ts
src/services/project-service/project-service.ts
src/store/auth/auth-reducer.test.ts
src/store/auth/auth-reducer.ts
src/store/project/project-action.ts
src/store/project/project-reducer.test.ts
src/store/project/project-reducer.ts

diff --git a/src/common/api/filter-builder.ts b/src/common/api/filter-builder.ts
new file mode 100644 (file)
index 0000000..c4c29b4
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export enum FilterField {
+    UUID = "uuid"
+}
+
+export default class FilterBuilder {
+    private filters = "";
+
+    private addCondition(field: FilterField, cond: string, value?: string) {
+        if (value) {
+            this.filters += `["${field}","${cond}","${value}"]`;
+        }
+        return this;
+    }
+
+    public addEqual(field: FilterField, value?: string) {
+        return this.addCondition(field, "=", value);
+    }
+
+    public addLike(field: FilterField, value?: string) {
+        return this.addCondition(field, "like", value);
+    }
+
+    public addILike(field: FilterField, value?: string) {
+        return this.addCondition(field, "ilike", value);
+    }
+
+    public get() {
+        return "[" + this.filters + "]";
+    }
+}
diff --git a/src/common/api/url-builder.ts b/src/common/api/url-builder.ts
new file mode 100644 (file)
index 0000000..e5786a2
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export default class UrlBuilder {
+       private url: string = "";
+       private query: string = "";
+
+       constructor(host: string) {
+               this.url = host;
+       }
+
+       public addParam(param: string, value: string) {
+               if (this.query.length === 0) {
+                       this.query += "?";
+               } else {
+                       this.query += "&";
+               }
+               this.query += `${param}=${value}`;
+               return this;
+       }
+
+       public get() {
+               return this.url + this.query;
+       }
+}
index 34e2d64c110ca43a55cba2c7f0f2e11e361c2446..87da39b025e9706c05ebdade6e600f936fae1a89 100644 (file)
@@ -24,7 +24,7 @@ class ApiToken extends React.Component<ApiTokenProps & RouteProps & DispatchProp
         const apiToken = ApiToken.getUrlParameter(search, 'api_token');
         this.props.dispatch(authActions.SAVE_API_TOKEN(apiToken));
         this.props.dispatch(authService.getUserDetails());
-        this.props.dispatch(projectService.getTopProjectList());
+        this.props.dispatch(projectService.getProjectList());
     }
     render() {
         return <Redirect to="/"/>
index 67de95fb3af108699e853dee79f84ee623678b6a..0cb67f1d82771a985d0b0637078c7d8dbb62463d 100644 (file)
@@ -29,7 +29,7 @@ const store = configureStore({
 }, history);
 
 store.dispatch(authActions.INIT());
-store.dispatch<any>(projectService.getTopProjectList());
+store.dispatch<any>(projectService.getProjectList());
 
 const App = () =>
     <Provider store={store}>
index 80d13e3c64676b3be8ef21604420f01b34abe1c7..da593c2dfb7a44fad7d88b29ef8ebff70febffc7 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { API_HOST, serverApi } from "../../common/server-api";
+import { API_HOST, serverApi } from "../../common/api/server-api";
 import { User } from "../../models/user";
 import { Dispatch } from "redux";
 import actions from "../../store/auth/auth-action";
index f35ca9cd4102e7d5a97b515b910ab4c737301430..87272d424e6f7a09a280689332bf388cf6f928fa 100644 (file)
@@ -2,10 +2,12 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { serverApi } from "../../common/server-api";
+import { serverApi } from "../../common/api/server-api";
 import { Dispatch } from "redux";
 import actions from "../../store/project/project-action";
 import { Project } from "../../models/project";
+import UrlBuilder from "../../common/api/url-builder";
+import FilterBuilder, { FilterField } from "../../common/api/filter-builder";
 
 interface GroupsResponse {
     offset: number;
@@ -31,9 +33,15 @@ interface GroupsResponse {
 }
 
 export default class ProjectService {
-    public getTopProjectList = () => (dispatch: Dispatch) => {
-        dispatch(actions.TOP_PROJECTS_REQUEST());
-        serverApi.get<GroupsResponse>('/groups').then(groups => {
+    public getProjectList = (parentUuid?: string) => (dispatch: Dispatch) => {
+        dispatch(actions.PROJECTS_REQUEST());
+
+        const ub = new UrlBuilder('/groups');
+        const fb = new FilterBuilder();
+        fb.addEqual(FilterField.UUID, parentUuid);
+        const url = ub.addParam('filter', fb.get()).get();
+
+        serverApi.get<GroupsResponse>(url).then(groups => {
             const projects = groups.data.items.map(g => ({
                 name: g.name,
                 createdAt: g.created_at,
@@ -42,7 +50,7 @@ export default class ProjectService {
                 uuid: g.uuid,
                 ownerUuid: g.owner_uuid
             } as Project));
-            dispatch(actions.TOP_PROJECTS_SUCCESS(projects));
+            dispatch(actions.PROJECTS_SUCCESS(projects));
         });
-    }
+    };
 }
index f2e20baa8971c93f2b036f2a762697e4f7fc7161..17bd42175f8df6647a98d847f6c0a48d79ee4b1d 100644 (file)
@@ -10,7 +10,7 @@ import {
     USER_FIRST_NAME_KEY,
     USER_LAST_NAME_KEY
 } from "../../services/auth-service/auth-service";
-import { API_HOST } from "../../common/server-api";
+import { API_HOST } from "../../common/api/server-api";
 
 import 'jest-localstorage-mock';
 
index 3fad4cf7569019b3ecbc1ed0d7b8d047e5f2c219..57a17ae53cfbb45f9c69529ad34d866771b0f215 100644 (file)
@@ -5,7 +5,7 @@
 import actions, { AuthAction } from "./auth-action";
 import { User } from "../../models/user";
 import { authService } from "../../services/services";
-import { removeServerApiAuthorizationHeader, setServerApiAuthorizationHeader } from "../../common/server-api";
+import { removeServerApiAuthorizationHeader, setServerApiAuthorizationHeader } from "../../common/api/server-api";
 import { UserDetailsResponse } from "../../services/auth-service/auth-service";
 
 export interface AuthState {
index 7c91cc551a521fdb97db5879ab7f089fb6f85250..c88edb60df8d0c764563ee48c027289859214567 100644 (file)
@@ -8,8 +8,8 @@ import { default as unionize, ofType, UnionOf } from "unionize";
 const actions = unionize({
     CREATE_PROJECT: ofType<Project>(),
     REMOVE_PROJECT: ofType<string>(),
-    TOP_PROJECTS_REQUEST: {},
-    TOP_PROJECTS_SUCCESS: ofType<Project[]>()
+    PROJECTS_REQUEST: {},
+    PROJECTS_SUCCESS: ofType<Project[]>()
 }, {
     tag: 'type',
     value: 'payload'
index e5f5c27532ebb71a02039aa961cd125968d769ec..0bcf9428a1e18d505cf70db21357f13c0b03c8ac 100644 (file)
@@ -32,8 +32,8 @@ describe('project-reducer', () => {
             uuid: 'test123'
         };
 
-        const topProjects = [project, project];
-        const state = projectsReducer(initialState, actions.TOP_PROJECTS_SUCCESS(topProjects));
-        expect(state).toEqual(topProjects);
+        const projects = [project, project];
+        const state = projectsReducer(initialState, actions.PROJECTS_SUCCESS(projects));
+        expect(state).toEqual(projects);
     });
 });
index 64e7925522614ca08c80d4a3912dee646cb2c3cb..477cb1e4688e309e243d78cece928313f6215146 100644 (file)
@@ -11,8 +11,8 @@ const projectsReducer = (state: ProjectState = [], action: ProjectAction) => {
     return actions.match(action, {
         CREATE_PROJECT: project => [...state, project],
         REMOVE_PROJECT: () => state,
-        TOP_PROJECTS_REQUEST: () => state,
-        TOP_PROJECTS_SUCCESS: projects => {
+        PROJECTS_REQUEST: () => state,
+        PROJECTS_SUCCESS: projects => {
             return projects;
         },
         default: () => state