[ARVADOS-WORKBENCH2] updated: 7e58fd10a7abc133b32a5084796c2b061e03ecd8

Git user git at public.curoverse.com
Wed Jun 6 02:15:10 EDT 2018


Summary of changes:
 package.json                                 |  7 +++--
 src/{models/project.ts => common/actions.ts} |  5 ----
 src/common/server-api.ts                     |  7 ++---
 src/components/api-token/api-token.tsx       | 18 ++++++-----
 src/components/tree/tree.tsx                 |  2 +-
 src/index.tsx                                |  1 +
 src/models/user.ts                           |  4 +--
 src/services/auth-service/auth-service.ts    |  2 +-
 src/store/auth-action.ts                     | 42 +++++++++++++++++++++-----
 src/store/auth-reducer.ts                    | 45 ++++++++++++++++------------
 src/store/project-action.ts                  | 15 ++++++----
 src/store/project-reducer.ts                 | 15 ++++------
 src/store/root-reducer.ts                    | 15 ++++++----
 src/store/store.ts                           |  4 ++-
 src/views/workbench/workbench.tsx            | 16 ++++------
 yarn.lock                                    | 12 +++++---
 16 files changed, 123 insertions(+), 87 deletions(-)
 copy src/{models/project.ts => common/actions.ts} (58%)

       via  7e58fd10a7abc133b32a5084796c2b061e03ecd8 (commit)
      from  6e6ef73c3a75b2cfb6d0ee11827630ca46266982 (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 7e58fd10a7abc133b32a5084796c2b061e03ecd8
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date:   Wed Jun 6 08:14:11 2018 +0200

    Replace typesafe-actions with unionize, add fetching user details action
    
    Feature #13563
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>:

diff --git a/package.json b/package.json
index 9f4197c..9a31c4e 100644
--- a/package.json
+++ b/package.json
@@ -14,8 +14,8 @@
     "react-router-redux": "5.0.0-alpha.9",
     "react-scripts-ts": "2.16.0",
     "redux": "4.0.0",
-    "redux-devtools": "3.4.1",
-    "typesafe-actions": "2.0.4"
+    "redux-thunk": "2.3.0",
+    "unionize": "2.1.2"
   },
   "scripts": {
     "start": "react-scripts-ts start",
@@ -34,7 +34,8 @@
     "@types/react-router-dom": "4.2.7",
     "@types/react-router-redux": "5.0.15",
     "@types/redux-devtools": "3.0.44",
-    "typescript": "2.9.1"
+    "typescript": "2.9.1",
+    "redux-devtools": "3.4.1"
   },
   "moduleNameMapper": {
     "^~/(.*)$": "<rootDir>/src/$1"
diff --git a/src/models/user.ts b/src/common/actions.ts
similarity index 52%
copy from src/models/user.ts
copy to src/common/actions.ts
index 514402d..6a5f410 100644
--- a/src/models/user.ts
+++ b/src/common/actions.ts
@@ -1,9 +1,3 @@
 // Copyright (C) The Arvados Authors. All rights reserved.
 //
 // SPDX-License-Identifier: AGPL-3.0
-
-export interface User {
-    email: string;
-    apiToken: string;
-    apiHost: string;
-}
diff --git a/src/common/server-api.ts b/src/common/server-api.ts
index 9078b73..2e676dd 100644
--- a/src/common/server-api.ts
+++ b/src/common/server-api.ts
@@ -4,17 +4,16 @@
 
 import Axios, { AxiosInstance } from "axios";
 
-export const API_HOST = 'https://qr1hi.arvadosapi.com/arvados/v1';
+export const API_HOST = 'https://qr1hi.arvadosapi.com';
 
 export const serverApi: AxiosInstance = Axios.create({
-    baseURL: API_HOST
+    baseURL: API_HOST + '/arvados/v1'
 });
 
 export function setServerApiAuthorizationHeader(token: string) {
     serverApi.defaults.headers.common = {
         'Authorization': `OAuth2 ${token}`
-    };
-}
+    };}
 
 export function removeServerApiAuthorizationHeader() {
     delete serverApi.defaults.headers.common.Authorization;
diff --git a/src/components/api-token/api-token.tsx b/src/components/api-token/api-token.tsx
index 91ef4e9..bc0caf5 100644
--- a/src/components/api-token/api-token.tsx
+++ b/src/components/api-token/api-token.tsx
@@ -1,13 +1,16 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
 import { Redirect, RouteProps } from "react-router";
 import * as React from "react";
-import { connect } from "react-redux";
-import authActions from "../../store/auth-action";
+import { connect, DispatchProp } from "react-redux";
+import authActions, { getUserDetails } from "../../store/auth-action";
 
 interface ApiTokenProps {
-    saveApiToken: (token: string) => void;
 }
 
-class ApiToken extends React.Component<ApiTokenProps & RouteProps, {}> {
+class ApiToken extends React.Component<ApiTokenProps & RouteProps & DispatchProp<any>, {}> {
     static getUrlParameter(search: string, name: string) {
         const safeName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
         const regex = new RegExp('[\\?&]' + safeName + '=([^&#]*)');
@@ -18,13 +21,12 @@ class ApiToken extends React.Component<ApiTokenProps & RouteProps, {}> {
     componentDidMount() {
         const search = this.props.location ? this.props.location.search : "";
         const apiToken = ApiToken.getUrlParameter(search, 'api_token');
-        this.props.saveApiToken(apiToken);
+        this.props.dispatch(authActions.SAVE_API_TOKEN(apiToken));
+        this.props.dispatch(getUserDetails());
     }
     render() {
         return <Redirect to="/"/>
     }
 }
 
-export default connect<ApiTokenProps>(null, {
-    saveApiToken: authActions.saveApiToken
-})(ApiToken);
+export default connect()(ApiToken);
diff --git a/src/components/tree/tree.tsx b/src/components/tree/tree.tsx
index 0c99db8..12369d5 100644
--- a/src/components/tree/tree.tsx
+++ b/src/components/tree/tree.tsx
@@ -15,7 +15,7 @@ interface TreeProps<T> {
 class Tree<T> extends React.Component<TreeProps<T>, {}> {
     render() {
         return <List>
-            {this.props.items.map((it: T, idx: number) =>
+            {this.props.items && this.props.items.map((it: T, idx: number) =>
                 <ListItem key={`item/${idx}`} button>
                     {this.props.render(it)}
                 </ListItem>
diff --git a/src/index.tsx b/src/index.tsx
index 8935470..ae5395f 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -25,6 +25,7 @@ const store = configureStore({
         location: null
     },
     auth: {
+        user: undefined
     }
 }, history);
 
diff --git a/src/models/user.ts b/src/models/user.ts
index 514402d..f1780d5 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -4,6 +4,6 @@
 
 export interface User {
     email: string;
-    apiToken: string;
-    apiHost: string;
+    firstName: string;
+    lastName: string;
 }
diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts
index 672a619..cedf3c6 100644
--- a/src/services/auth-service/auth-service.ts
+++ b/src/services/auth-service/auth-service.ts
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import Axios from "axios";
-import { API_HOST, serverApi } from "../../common/server-api";
+import { API_HOST } from "../../common/server-api";
 
 const API_TOKEN_KEY = 'api_token';
 
diff --git a/src/store/auth-action.ts b/src/store/auth-action.ts
index 02fdcac..719cb81 100644
--- a/src/store/auth-action.ts
+++ b/src/store/auth-action.ts
@@ -2,14 +2,40 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { ActionType, createStandardAction } from "typesafe-actions";
+import { serverApi } from "../common/server-api";
+import { ofType, default as unionize, UnionOf } from "unionize";
+import { Dispatch } from "redux";
 
-const actions = {
-    saveApiToken: createStandardAction('@@auth/saveApiToken')<string>(),
-    getUserTokenDetails: createStandardAction('@@auth/userTokenDetails')(),
-    login: createStandardAction('@@auth/login')(),
-    logout: createStandardAction('@@auth/logout')()
-};
+export interface UserDetailsResponse {
+    email: string;
+    first_name: string;
+    last_name: string;
+    is_admin: boolean;
+}
+
+const actions = unionize({
+    SAVE_API_TOKEN: ofType<string>(),
+    LOGIN: {},
+    LOGOUT: {},
+    USER_DETAILS_REQUEST: {},
+    USER_DETAILS_SUCCESS: ofType<UserDetailsResponse>()
+}, {
+    tag: 'type',
+    value: 'payload'
+});
 
-export type AuthAction = ActionType<typeof actions>;
+export type AuthAction = UnionOf<typeof actions>;
 export default actions;
+
+export const getUserDetails = () => (dispatch: Dispatch) => {
+    dispatch(actions.USER_DETAILS_REQUEST());
+    serverApi
+        .get<UserDetailsResponse>('/users/current')
+        .then(resp => {
+            dispatch(actions.USER_DETAILS_SUCCESS(resp.data));
+        })
+        // .catch(err => {
+        // });
+};
+
+
diff --git a/src/store/auth-reducer.ts b/src/store/auth-reducer.ts
index 8e9eb4f..0d1f730 100644
--- a/src/store/auth-reducer.ts
+++ b/src/store/auth-reducer.ts
@@ -2,35 +2,42 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { getType } from "typesafe-actions";
-import actions, { AuthAction } from "./auth-action";
+import actions, { AuthAction, UserDetailsResponse } from "./auth-action";
 import { User } from "../models/user";
 import { authService } from "../services/services";
-import { removeServerApiAuthorizationHeader, serverApi, setServerApiAuthorizationHeader } from "../common/server-api";
+import { removeServerApiAuthorizationHeader, setServerApiAuthorizationHeader } from "../common/server-api";
 
-type AuthState = User | {};
+export interface AuthState {
+    user?: User;
+    apiToken?: string;
+};
 
 const authReducer = (state: AuthState = {}, action: AuthAction) => {
-    switch (action.type) {
-        case getType(actions.saveApiToken): {
-            authService.saveApiToken(action.payload);
-            setServerApiAuthorizationHeader(action.payload);
-            serverApi.get('/users/current');
-            return {...state, apiToken: action.payload};
-        }
-        case getType(actions.login): {
+    return actions.match(action, {
+        SAVE_API_TOKEN: (token: string) => {
+            authService.saveApiToken(token);
+            setServerApiAuthorizationHeader(token);
+            return {...state, apiToken: token};
+        },
+        LOGIN: () => {
             authService.login();
             return state;
-        }
-        case getType(actions.logout): {
+        },
+        LOGOUT: () => {
             authService.removeApiToken();
             removeServerApiAuthorizationHeader();
             authService.logout();
-            return {...state, apiToken: null };
-        }
-        default:
-            return state;
-    }
+            return {...state, apiToken: undefined};
+        },
+        USER_DETAILS_SUCCESS: (ud: UserDetailsResponse) => {
+            return {...state, user: {
+                email: ud.email,
+                firstName: ud.first_name,
+                lastName: ud.last_name
+            }}
+        },
+        default: () => state
+    });
 };
 
 export default authReducer;
diff --git a/src/store/project-action.ts b/src/store/project-action.ts
index 568de2b..904a34d 100644
--- a/src/store/project-action.ts
+++ b/src/store/project-action.ts
@@ -2,13 +2,16 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { ActionType, createStandardAction } from "typesafe-actions";
 import { Project } from "../models/project";
+import { default as unionize, ofType, UnionOf } from "unionize";
 
-const actions = {
-    createProject: createStandardAction('@@project/create')<Project>(),
-    removeProject: createStandardAction('@@project/remove')<string>()
-};
+const actions = unionize({
+    CREATE_PROJECT: ofType<Project>(),
+    REMOVE_PROJECT: ofType<string>()
+}, {
+    tag: 'type',
+    value: 'payload'
+});
 
-export type ProjectAction = ActionType<typeof actions>;
+export type ProjectAction = UnionOf<typeof actions>;
 export default actions;
diff --git a/src/store/project-reducer.ts b/src/store/project-reducer.ts
index 1614ed9..a321265 100644
--- a/src/store/project-reducer.ts
+++ b/src/store/project-reducer.ts
@@ -2,20 +2,17 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { getType } from "typesafe-actions";
 import { Project } from "../models/project";
 import actions, { ProjectAction } from "./project-action";
 
-type ProjectState = Project[];
+export type ProjectState = Project[];
 
 const projectsReducer = (state: ProjectState = [], action: ProjectAction) => {
-    switch (action.type) {
-        case getType(actions.createProject): {
-            return [...state, action.payload];
-        }
-        default:
-            return state;
-    }
+    return actions.match(action, {
+        CREATE_PROJECT: (project) => [...state, project],
+        REMOVE_PROJECT: () => state,
+        default: () => state
+    });
 };
 
 export default projectsReducer;
diff --git a/src/store/root-reducer.ts b/src/store/root-reducer.ts
index b514ecf..380bd53 100644
--- a/src/store/root-reducer.ts
+++ b/src/store/root-reducer.ts
@@ -3,10 +3,15 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { combineReducers } from "redux";
-import { StateType } from "typesafe-actions";
-import { routerReducer } from "react-router-redux";
-import authReducer from "./auth-reducer";
-import projectsReducer from "./project-reducer";
+import { routerReducer, RouterState } from "react-router-redux";
+import authReducer, { AuthState } from "./auth-reducer";
+import projectsReducer, { ProjectState } from "./project-reducer";
+
+export interface RootState {
+    auth: AuthState,
+    projects: ProjectState,
+    router: RouterState
+}
 
 const rootReducer = combineReducers({
     auth: authReducer,
@@ -14,6 +19,4 @@ const rootReducer = combineReducers({
     router: routerReducer
 });
 
-export type RootState = StateType<typeof rootReducer>;
-
 export default rootReducer;
diff --git a/src/store/store.ts b/src/store/store.ts
index 975debe..d3646e6 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -5,6 +5,7 @@
 import { createStore, applyMiddleware, compose, Middleware } from 'redux';
 import { default as rootReducer, RootState } from "./root-reducer";
 import { routerMiddleware } from "react-router-redux";
+import thunkMiddleware from 'redux-thunk';
 import { History } from "history";
 
 const composeEnhancers =
@@ -14,7 +15,8 @@ const composeEnhancers =
 
 export default function configureStore(initialState: RootState, history: History) {
     const middlewares: Middleware[] = [
-        routerMiddleware(history)
+        routerMiddleware(history),
+        thunkMiddleware
     ];
     const enhancer = composeEnhancers(applyMiddleware(...middlewares));
     return createStore(rootReducer, initialState!, enhancer);
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 3e22385..8f0562b 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -9,7 +9,7 @@ import Drawer from '@material-ui/core/Drawer';
 import AppBar from '@material-ui/core/AppBar';
 import Toolbar from '@material-ui/core/Toolbar';
 import Typography from '@material-ui/core/Typography';
-import { connect } from "react-redux";
+import { connect, DispatchProp } from "react-redux";
 import Tree from "../../components/tree/tree";
 import { Project } from "../../models/project";
 import { RootState } from "../../store/root-reducer";
@@ -23,6 +23,7 @@ import IconButton from "@material-ui/core/IconButton/IconButton";
 import Menu from "@material-ui/core/Menu/Menu";
 import MenuItem from "@material-ui/core/MenuItem/MenuItem";
 import { AccountCircle } from "@material-ui/icons";
+import { AnyAction } from "redux";
 
 const drawerWidth = 240;
 
@@ -61,11 +62,9 @@ interface WorkbenchDataProps {
 }
 
 interface WorkbenchActionProps {
-    login?: () => void;
-    logout?: () => void;
 }
 
-type WorkbenchProps = WorkbenchDataProps & WorkbenchActionProps & WithStyles<CssRules>;
+type WorkbenchProps = WorkbenchDataProps & WorkbenchActionProps & DispatchProp & WithStyles<CssRules>;
 
 interface WorkbenchState {
     anchorEl: any;
@@ -80,12 +79,12 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
     }
 
     login = () => {
-        this.props.login!();
+        this.props.dispatch(authActions.LOGIN() as AnyAction);
     };
 
     logout = () => {
         this.handleClose();
-        this.props.logout!();
+        this.props.dispatch(authActions.LOGOUT() as AnyAction);
     };
 
     handleOpenMenu = (event: React.MouseEvent<any>) => {
@@ -166,10 +165,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
 export default connect<WorkbenchDataProps>(
     (state: RootState) => ({
         projects: state.projects
-    }), {
-        login: authActions.login,
-        logout: authActions.logout
-    }
+    })
 )(
     withStyles(styles)(Workbench)
 );
diff --git a/yarn.lock b/yarn.lock
index 8b71529..eace7b6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6140,6 +6140,10 @@ redux-devtools at 3.4.1:
     prop-types "^15.5.7"
     redux-devtools-instrument "^1.0.1"
 
+redux-thunk@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
+
 redux at 4.0.0, "redux@>= 3.7.2", redux@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03"
@@ -7248,10 +7252,6 @@ typedarray@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
 
-typesafe-actions at 2.0.4:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/typesafe-actions/-/typesafe-actions-2.0.4.tgz#31c8f8df3566d549eb52edb64a75997e970c17d0"
-
 typescript at 2.9.1:
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961"
@@ -7324,6 +7324,10 @@ union-value@^1.0.0:
     is-extendable "^0.1.1"
     set-value "^0.4.3"
 
+unionize@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/unionize/-/unionize-2.1.2.tgz#2513b148de515bec93f045d1685bd88eab62b608"
+
 uniq@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list