Add login in/out handling, fix async validation
authorDaniel Kos <daniel.kos@contractors.roche.com>
Tue, 18 Dec 2018 09:04:26 +0000 (10:04 +0100)
committerDaniel Kos <daniel.kos@contractors.roche.com>
Tue, 18 Dec 2018 09:04:26 +0000 (10:04 +0100)
Feature #14478

Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos@contractors.roche.com>

src/store/auth/auth-action-session.ts
src/views/site-manager-panel/site-manager-panel-root.tsx
src/views/site-manager-panel/site-manager-panel.tsx

index 6ffca6b5220f459135d253c01963bf02bf48ebbc..4a6f56f92d9b4270f5a0e6065d3cf86aa4afe7e9 100644 (file)
@@ -82,9 +82,7 @@ const getSaltedToken = (clusterId: string, tokenUuid: string, token: string) =>
 
 const clusterLogin = async (clusterId: string, baseUrl: string, activeSession: Session): Promise<{user: User, token: string}> => {
     const tokenUuid = await getTokenUuid(activeSession.baseUrl, activeSession.token);
-    console.log(">> Cluster", clusterId);
     const saltedToken = getSaltedToken(clusterId, tokenUuid, activeSession.token);
-    console.log(">> Salted token", saltedToken);
     const user = await getUserDetails(baseUrl, saltedToken);
     return {
         user: {
@@ -111,7 +109,7 @@ export const validateCluster = async (remoteHost: string, clusterId: string, act
 };
 
 export const validateSession = (session: Session, activeSession: Session) =>
-    async (dispatch: Dispatch) => {
+    async (dispatch: Dispatch): Promise<Session> => {
         dispatch(authActions.UPDATE_SESSION({ ...session, status: SessionStatus.BEING_VALIDATED }));
         session.loggedIn = false;
         try {
@@ -156,9 +154,9 @@ export const addSession = (remoteHost: string) =>
                 return Promise.reject("Cluster already exists");
             }
             try {
-                const { baseUrl, user, token } = await dispatch(validateCluster(remoteHost, clusterId, activeSession));
+                const { baseUrl, user, token } = await validateCluster(remoteHost, clusterId, activeSession);
                 const session = {
-                    loggedIn: false,
+                    loggedIn: true,
                     status: SessionStatus.VALIDATED,
                     active: false,
                     email: user.email,
@@ -174,13 +172,29 @@ export const addSession = (remoteHost: string) =>
 
                 return session;
             } catch (e) {
-                console.error(e);
             }
         }
-        debugger;
         return Promise.reject("Could not validate cluster");
     };
 
+export const toggleSession = (session: Session) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        let s = { ...session };
+
+        if (session.loggedIn) {
+            s.loggedIn = false;
+        } else {
+            const sessions = getState().auth.sessions;
+            const activeSession = getActiveSession(sessions);
+            if (activeSession) {
+                s = await dispatch<any>(validateSession(s, activeSession)) as Session;
+            }
+        }
+
+        dispatch(authActions.UPDATE_SESSION(s));
+        services.authService.saveSessions(getState().auth.sessions);
+    };
+
 export const loadSiteManagerPanel = () =>
     async (dispatch: Dispatch<any>) => {
         try {
index a64fdb25ae9b1c737aa4acdd3fd7ee3cfa878bf8..3b8053e7eeeca0e95f6cf39976e467456b8366e5 100644 (file)
@@ -5,7 +5,8 @@
 import * as React from 'react';
 import {
     Card,
-    CardContent, CircularProgress,
+    CardContent,
+    CircularProgress,
     Grid,
     StyleRulesCallback,
     Table,
@@ -26,12 +27,10 @@ import { Field, FormErrors, InjectedFormProps, reduxForm, reset, stopSubmit } fr
 import { TextField } from "~/components/text-field/text-field";
 import { addSession } from "~/store/auth/auth-action-session";
 import { SITE_MANAGER_REMOTE_HOST_VALIDATION } from "~/validators/validators";
-import {
-    RENAME_FILE_DIALOG,
-    RenameFileDialogData
-} from "~/store/collection-panel/collection-panel-files/collection-panel-files-actions";
 
-type CssRules = 'root' | 'link' | 'buttonContainer' | 'table' | 'tableRow' | 'status' | 'remoteSiteInfo' | 'buttonAdd';
+type CssRules = 'root' | 'link' | 'buttonContainer' | 'table' | 'tableRow' |
+    'remoteSiteInfo' | 'buttonAdd' | 'buttonLoggedIn' | 'buttonLoggedOut' |
+    'statusCell';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
@@ -54,12 +53,8 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
             whiteSpace: 'nowrap'
         }
     },
-    status: {
-        width: 100,
-        padding: 5,
-        fontWeight: 'bold',
-        textAlign: 'center',
-        borderRadius: 4
+    statusCell: {
+        minWidth: 160
     },
     remoteSiteInfo: {
         marginTop: 20
@@ -67,10 +62,29 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     buttonAdd: {
         marginLeft: 10,
         marginTop: theme.spacing.unit * 3
+    },
+    buttonLoggedIn: {
+        minHeight: theme.spacing.unit,
+        padding: 5,
+        color: '#fff',
+        backgroundColor: '#009966',
+        '&:hover': {
+            backgroundColor: '#008450',
+        }
+    },
+    buttonLoggedOut: {
+        minHeight: theme.spacing.unit,
+        padding: 5,
+        color: '#000',
+        backgroundColor: '#FFC414',
+        '&:hover': {
+            backgroundColor: '#eaaf14',
+        }
     }
 });
 
 export interface SiteManagerPanelRootActionProps {
+    toggleSession: (session: Session) => void;
 }
 
 export interface SiteManagerPanelRootDataProps {
@@ -84,21 +98,20 @@ const SITE_MANAGER_FORM_NAME = 'siteManagerForm';
 export const SiteManagerPanelRoot = compose(
     reduxForm<{remoteHost: string}>({
         form: SITE_MANAGER_FORM_NAME,
-        onSubmit: async (data, dispatch) => {
-            try {
-                await dispatch(addSession(data.remoteHost));
+        touchOnBlur: false,
+        onSubmit: (data, dispatch) => {
+            dispatch<any>(addSession(data.remoteHost)).then(() => {
                 dispatch(reset(SITE_MANAGER_FORM_NAME));
-            } catch (e) {
+            }).catch((e: any) => {
                 const errors = {
                     remoteHost: e
                 } as FormErrors;
                 dispatch(stopSubmit(SITE_MANAGER_FORM_NAME, errors));
-            }
-
+            });
         }
     }),
     withStyles(styles))
-    (({ classes, sessions, handleSubmit }: SiteManagerPanelRootProps) =>
+    (({ classes, sessions, handleSubmit, toggleSession }: SiteManagerPanelRootProps) =>
         <Card className={classes.root}>
             <CardContent>
                 <Grid container direction="row">
@@ -125,13 +138,13 @@ export const SiteManagerPanelRoot = compose(
                                     <TableCell>{session.clusterId}</TableCell>
                                     <TableCell>{validating ? <CircularProgress size={20}/> : session.username}</TableCell>
                                     <TableCell>{validating ? <CircularProgress size={20}/> : session.email}</TableCell>
-                                    <TableCell>
-                                        <div className={classes.status} style={{
-                                            color: session.loggedIn ? '#fff' : '#000',
-                                            backgroundColor: session.loggedIn ? '#009966' : '#FFC414'
-                                        }}>
-                                            {session.loggedIn ? "Logged in" : "Logged out"}
-                                        </div>
+                                    <TableCell className={classes.statusCell}>
+                                        <Button fullWidth
+                                            disabled={validating || session.status === SessionStatus.INVALIDATED || session.active}
+                                            className={session.loggedIn ? classes.buttonLoggedIn : classes.buttonLoggedOut}
+                                            onClick={() => toggleSession(session)}>
+                                            {validating ? "Validating" : (session.loggedIn ? "Logged in" : "Logged out")}
+                                        </Button>
                                     </TableCell>
                                 </TableRow>;
                             })}
index d7fd398bb3a2d954cbd3588931b483498cfd29c8..8b762108a192fddf2b8c691c827b5de4b0e5efc6 100644 (file)
@@ -9,6 +9,8 @@ import {
     SiteManagerPanelRoot, SiteManagerPanelRootActionProps,
     SiteManagerPanelRootDataProps
 } from "~/views/site-manager-panel/site-manager-panel-root";
+import { Session } from "~/models/session";
+import { toggleSession } from "~/store/auth/auth-action-session";
 
 const mapStateToProps = (state: RootState): SiteManagerPanelRootDataProps => {
     return {
@@ -18,6 +20,9 @@ const mapStateToProps = (state: RootState): SiteManagerPanelRootDataProps => {
 };
 
 const mapDispatchToProps = (dispatch: Dispatch): SiteManagerPanelRootActionProps => ({
+    toggleSession: (session: Session) => {
+        dispatch<any>(toggleSession(session));
+    }
 });
 
 export const SiteManagerPanel = connect(mapStateToProps, mapDispatchToProps)(SiteManagerPanelRoot);