[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