From: Stephen Smith Date: Thu, 24 Mar 2022 19:07:27 +0000 (-0400) Subject: 18559: Replace setup vm dialog with setup confirmation dialog X-Git-Tag: 2.4.0~1^2~20 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/7e9513099881d63a99a70c69ddd71c5d83567fa4 18559: Replace setup vm dialog with setup confirmation dialog Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- diff --git a/src/store/user-profile/user-profile-actions.ts b/src/store/user-profile/user-profile-actions.ts index 0c6341f2..6042efa9 100644 --- a/src/store/user-profile/user-profile-actions.ts +++ b/src/store/user-profile/user-profile-actions.ts @@ -15,6 +15,7 @@ import { dialogActions } from "store/dialog/dialog-actions"; export const USER_PROFILE_PANEL_ID = 'userProfilePanel'; export const USER_PROFILE_FORM = 'userProfileForm'; export const DEACTIVATE_DIALOG = 'deactivateDialog'; +export const SETUP_DIALOG = 'setupDialog'; export const UserProfileGroupsActions = bindDataExplorerActions(USER_PROFILE_PANEL_ID); @@ -61,6 +62,34 @@ export const openDeactivateDialog = (uuid: string) => })); } +export const openSetupDialog = (uuid: string) => + (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(dialogActions.OPEN_DIALOG({ + id: SETUP_DIALOG, + data: { + title: 'Setup user', + text: 'Are you sure you want to setup this user?', + confirmButtonLabel: 'Confirm', + uuid + } + })); +} + + +export const setup = (uuid: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + try { + const resources = await services.userService.setup(uuid); + dispatch(updateResources(resources.items)); + dispatch(snackbarActions.OPEN_SNACKBAR({ message: "User has been setup", hideDuration: 2000, kind: SnackbarKind.SUCCESS })); + } catch (e) { + dispatch(snackbarActions.OPEN_SNACKBAR({ message: e.message, hideDuration: 2000, kind: SnackbarKind.ERROR })); + } finally { + dispatch(dialogActions.CLOSE_DIALOG({ id: SETUP_DIALOG })); + } + + }; + export const unsetup = (uuid: string) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { try { diff --git a/src/store/users/users-actions.ts b/src/store/users/users-actions.ts index 425a2d56..b5d47d70 100644 --- a/src/store/users/users-actions.ts +++ b/src/store/users/users-actions.ts @@ -8,14 +8,14 @@ import { RootState } from 'store/store'; import { getUserUuid } from "common/getuser"; import { ServiceRepository } from "services/services"; import { dialogActions } from 'store/dialog/dialog-actions'; -import { startSubmit, reset, initialize, stopSubmit } from "redux-form"; +import { startSubmit, reset, stopSubmit } from "redux-form"; import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; import { UserResource } from "models/user"; import { getResource } from 'store/resources/resources'; import { navigateTo, navigateToUsers, navigateToRootProject } from "store/navigation/navigation-action"; import { authActions } from 'store/auth/auth-action'; import { getTokenV2 } from "models/api-client-authorization"; -import { AddLoginFormData, VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD, VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD, VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD } from "store/virtual-machines/virtual-machines-actions"; +import { VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD, VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD } from "store/virtual-machines/virtual-machines-actions"; import { PermissionLevel } from "models/permission"; import { updateResources } from "store/resources/resources-actions"; @@ -23,7 +23,6 @@ export const USERS_PANEL_ID = 'usersPanel'; export const USER_ATTRIBUTES_DIALOG = 'userAttributesDialog'; export const USER_CREATE_FORM_NAME = 'userCreateFormName'; export const USER_MANAGEMENT_DIALOG = 'userManageDialog'; -export const SETUP_SHELL_ACCOUNT_DIALOG = 'setupShellAccountDialog'; export interface UserCreateFormDialogData { email: string; @@ -47,15 +46,6 @@ export const openUserManagement = (uuid: string) => dispatch(dialogActions.OPEN_DIALOG({ id: USER_MANAGEMENT_DIALOG, data })); }; -export const openSetupShellAccount = (uuid: string) => - async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - const { resources } = getState(); - const user = getResource(uuid)(resources); - const virtualMachines = await services.virtualMachineService.list(); - dispatch(initialize(SETUP_SHELL_ACCOUNT_DIALOG, {[VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD]: user, [VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD]: []})); - dispatch(dialogActions.OPEN_DIALOG({ id: SETUP_SHELL_ACCOUNT_DIALOG, data: virtualMachines })); - }; - export const loginAs = (uuid: string) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { const { resources } = getState(); @@ -118,35 +108,6 @@ export const createUser = (data: UserCreateFormDialogData) => } }; -export const setupUserVM = (setupData: AddLoginFormData) => - async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - dispatch(startSubmit(SETUP_SHELL_ACCOUNT_DIALOG)); - try { - const userResource = await services.userService.get(setupData.user.uuid); - - const resources = await services.userService.setup(setupData.user.uuid); - dispatch(updateResources(resources.items)); - - const permission = await services.permissionService.create({ - headUuid: setupData.vmUuid, - tailUuid: userResource.uuid, - name: PermissionLevel.CAN_LOGIN, - properties: { - username: userResource.username, - groups: setupData.groups, - } - }); - dispatch(updateResources([permission])); - - dispatch(dialogActions.CLOSE_DIALOG({ id: SETUP_SHELL_ACCOUNT_DIALOG })); - dispatch(reset(SETUP_SHELL_ACCOUNT_DIALOG)); - dispatch(snackbarActions.OPEN_SNACKBAR({ message: "User has been added to VM.", hideDuration: 2000, kind: SnackbarKind.SUCCESS })); - } catch (e) { - dispatch(stopSubmit(SETUP_SHELL_ACCOUNT_DIALOG)); - dispatch(snackbarActions.OPEN_SNACKBAR({ message: e.message, hideDuration: 2000, kind: SnackbarKind.ERROR })); - } - }; - export const openUserPanel = () => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { const user = getState().auth.user; diff --git a/src/views-components/dialog-forms/setup-shell-account-dialog.tsx b/src/views-components/dialog-forms/setup-shell-account-dialog.tsx deleted file mode 100644 index 04eae126..00000000 --- a/src/views-components/dialog-forms/setup-shell-account-dialog.tsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 -import React from 'react'; -import { compose } from "redux"; -import { reduxForm, InjectedFormProps, Field } from 'redux-form'; -import { withDialog, WithDialogProps } from "store/dialog/with-dialog"; -import { FormDialog } from 'components/form-dialog/form-dialog'; -import { TextField } from 'components/text-field/text-field'; -import { VirtualMachinesResource } from 'models/virtual-machines'; -import { InputLabel } from '@material-ui/core'; -import { SETUP_SHELL_ACCOUNT_DIALOG, setupUserVM } from 'store/users/users-actions'; -import { UserResource } from 'models/user'; -import { VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD, AddLoginFormData } from 'store/virtual-machines/virtual-machines-actions'; -import { UserGroupsVirtualMachineField, RequiredUserVirtualMachineField } from 'views-components/form-fields/user-form-fields'; - -export const SetupShellAccountDialog = compose( - withDialog(SETUP_SHELL_ACCOUNT_DIALOG), - reduxForm({ - form: SETUP_SHELL_ACCOUNT_DIALOG, - onSubmit: (data, dispatch) => { - dispatch(setupUserVM(data)); - } - }) -)( - (props: SetupShellAccountDialogComponentProps) => - -); - -interface DataProps { - user: UserResource; - items: VirtualMachinesResource[]; -} - -const UserNameField = () => - - VM Login - - ; - -type SetupShellAccountDialogComponentProps = WithDialogProps<{}> & InjectedFormProps; - -const SetupShellAccountFormFields = (props: SetupShellAccountDialogComponentProps) => - <> - - - - ; diff --git a/src/views-components/user-dialog/manage-dialog.tsx b/src/views-components/user-dialog/manage-dialog.tsx deleted file mode 100644 index a62e1a21..00000000 --- a/src/views-components/user-dialog/manage-dialog.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import React from "react"; -import { compose, Dispatch } from "redux"; -import { connect } from "react-redux"; -import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from "@material-ui/core"; -import { WithDialogProps } from "store/dialog/with-dialog"; -import { withDialog } from 'store/dialog/with-dialog'; -import { WithStyles, withStyles } from '@material-ui/core/styles'; -import { ArvadosTheme } from 'common/custom-theme'; -import { USER_MANAGEMENT_DIALOG } from "store/users/users-actions"; -import { openSetupShellAccount, loginAs } from 'store/users/users-actions'; -import { getUserDisplayName } from "models/user"; - -type CssRules = 'spacing'; - -const styles = withStyles((theme: ArvadosTheme) => ({ - spacing: { - paddingBottom: theme.spacing.unit * 2, - paddingTop: theme.spacing.unit * 2, - } -})); - -interface UserManageDataProps { - data: any; -} - -interface UserManageActionProps { - openSetupShellAccount: (uuid: string) => void; - loginAs: (uuid: string) => void; -} - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - openSetupShellAccount: (uuid: string) => dispatch(openSetupShellAccount(uuid)), - loginAs: (uuid: string) => dispatch(loginAs(uuid)) -}); - -type UserManageProps = UserManageDataProps & UserManageActionProps & WithStyles; - -export const UserManageDialog = compose( - connect(null, mapDispatchToProps), - withDialog(USER_MANAGEMENT_DIALOG), - styles)( - (props: WithDialogProps & UserManageProps) => - - {props.data && - - {`Manage - ${getUserDisplayName(props.data)}`} - - - As an admin, you can log in as this user. When you’ve finished, you will need to log out and log in again with your own account. - - - - As an admin, you can setup a shell account for this user. The login name is automatically generated from the user's e-mail address. - - - } - - - - - - ); diff --git a/src/views-components/user-dialog/setup-dialog.tsx b/src/views-components/user-dialog/setup-dialog.tsx new file mode 100644 index 00000000..3a2fd355 --- /dev/null +++ b/src/views-components/user-dialog/setup-dialog.tsx @@ -0,0 +1,21 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { Dispatch, compose } from 'redux'; +import { connect } from "react-redux"; +import { ConfirmationDialog } from "components/confirmation-dialog/confirmation-dialog"; +import { withDialog, WithDialogProps } from "store/dialog/with-dialog"; +import { setup, SETUP_DIALOG } from 'store/user-profile/user-profile-actions'; + +const mapDispatchToProps = (dispatch: Dispatch, props: WithDialogProps) => ({ + onConfirm: () => { + props.closeDialog(); + dispatch(setup(props.data.uuid)); + } +}); + +export const SetupDialog = compose( + withDialog(SETUP_DIALOG), + connect(null, mapDispatchToProps) +)(ConfirmationDialog); diff --git a/src/views/user-profile-panel/user-profile-panel-root.tsx b/src/views/user-profile-panel/user-profile-panel-root.tsx index 4572a352..febe0ab9 100644 --- a/src/views/user-profile-panel/user-profile-panel-root.tsx +++ b/src/views/user-profile-panel/user-profile-panel-root.tsx @@ -69,7 +69,7 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ }); export interface UserProfilePanelRootActionProps { - openSetupShellAccount: (uuid: string) => void; + openSetupDialog: (uuid: string) => void; loginAs: (uuid: string) => void; openDeactivateDialog: (uuid: string) => void; } @@ -305,7 +305,7 @@ export const UserProfilePanelRoot = withStyles(styles)( diff --git a/src/views/user-profile-panel/user-profile-panel.tsx b/src/views/user-profile-panel/user-profile-panel.tsx index 2bafd9fa..e23b8bce 100644 --- a/src/views/user-profile-panel/user-profile-panel.tsx +++ b/src/views/user-profile-panel/user-profile-panel.tsx @@ -8,11 +8,11 @@ import { reduxForm, isPristine, isValid } from 'redux-form'; import { connect } from 'react-redux'; import { saveEditedUser } from 'store/user-profile/user-profile-actions'; import { UserProfilePanelRoot, UserProfilePanelRootDataProps } from 'views/user-profile-panel/user-profile-panel-root'; -import { openDeactivateDialog, USER_PROFILE_FORM } from "store/user-profile/user-profile-actions"; +import { openSetupDialog, openDeactivateDialog, USER_PROFILE_FORM } from "store/user-profile/user-profile-actions"; import { matchUserProfileRoute } from 'routes/routes'; import { UserResource } from 'models/user'; import { getResource } from 'store/resources/resources'; -import { openSetupShellAccount, loginAs } from 'store/users/users-actions'; +import { loginAs } from 'store/users/users-actions'; const mapStateToProps = (state: RootState): UserProfilePanelRootDataProps => { const pathname = state.router.location ? state.router.location.pathname : ''; @@ -32,7 +32,7 @@ const mapStateToProps = (state: RootState): UserProfilePanelRootDataProps => { }}; const mapDispatchToProps = (dispatch: Dispatch) => ({ - openSetupShellAccount: (uuid: string) => dispatch(openSetupShellAccount(uuid)), + openSetupDialog: (uuid: string) => dispatch(openSetupDialog(uuid)), loginAs: (uuid: string) => dispatch(loginAs(uuid)), openDeactivateDialog: (uuid: string) => dispatch(openDeactivateDialog(uuid)), }); diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index 1202529c..11e038f5 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -80,9 +80,8 @@ import { UserPanel } from 'views/user-panel/user-panel'; import { UserAttributesDialog } from 'views-components/user-dialog/attributes-dialog'; import { CreateUserDialog } from 'views-components/dialog-forms/create-user-dialog'; import { HelpApiClientAuthorizationDialog } from 'views-components/api-client-authorizations-dialog/help-dialog'; -import { UserManageDialog } from 'views-components/user-dialog/manage-dialog'; import { DeactivateDialog } from 'views-components/user-dialog/deactivate-dialog'; -import { SetupShellAccountDialog } from 'views-components/dialog-forms/setup-shell-account-dialog'; +import { SetupDialog } from 'views-components/user-dialog/setup-dialog'; import { GroupsPanel } from 'views/groups-panel/groups-panel'; import { RemoveGroupDialog } from 'views-components/groups-dialog/remove-dialog'; import { GroupAttributesDialog } from 'views-components/groups-dialog/attributes-dialog'; @@ -261,7 +260,6 @@ export const WorkbenchPanel = - @@ -269,8 +267,8 @@ export const WorkbenchPanel = - +