export const USERS_PANEL_ID = 'usersPanel';
export const USER_ATTRIBUTES_DIALOG = 'userAttributesDialog';
export const USER_CREATE_FORM_NAME = 'userCreateFormName';
+export const USER_MANAGE_DIALOG = 'userManageDialog';
+export const SETUP_SHELL_ACCOUNT_DIALOG = 'setupShellAccountDialog';
export interface UserCreateFormDialogData {
email: string;
- identityUrl: string;
virtualMachineName: string;
groupVirtualMachine: string;
}
dispatch(dialogActions.OPEN_DIALOG({ id: USER_ATTRIBUTES_DIALOG, data }));
};
+export const openUserManage = (uuid: string) =>
+ (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const { resources } = getState();
+ const data = getResource<UserResource>(uuid)(resources);
+ dispatch(dialogActions.OPEN_DIALOG({ id: USER_MANAGE_DIALOG, data }));
+ };
+
+export const openSetupShellAccount = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const { resources } = getState();
+ const user = getResource<UserResource>(uuid)(resources);
+ const virtualMachines = await services.virtualMachineService.list();
+ dispatch(dialogActions.OPEN_DIALOG({ id: SETUP_SHELL_ACCOUNT_DIALOG, data: { user, ...virtualMachines } }));
+ };
+
export const openUserCreateDialog = () =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
const userUuid = await services.authService.getUuid();
import { ContextMenuActionSet } from "~/views-components/context-menu/context-menu-action-set";
import { AdvancedIcon, ProjectIcon, AttributesIcon, UserPanelIcon } from "~/components/icon/icon";
import { openAdvancedTabDialog } from '~/store/advanced-tab/advanced-tab';
-import { openUserAttributes, openUserProjects } from "~/store/users/users-actions";
+import { openUserAttributes, openUserProjects, openUserManage } from "~/store/users/users-actions";
export const userActionSet: ContextMenuActionSet = [[{
name: "Attributes",
execute: (dispatch, { uuid }) => {
dispatch<any>(openAdvancedTabDialog(uuid));
}
-},
-{
+}, {
name: "Manage",
icon: UserPanelIcon,
execute: (dispatch, { uuid }) => {
- dispatch<any>(openAdvancedTabDialog(uuid));
+ dispatch<any>(openUserManage(uuid));
}
}]];
import { InjectedFormProps } from 'redux-form';
import { WithDialogProps } from '~/store/dialog/with-dialog';
import { FormDialog } from '~/components/form-dialog/form-dialog';
-import { UserEmailField, UserIdentityUrlField, UserVirtualMachineField, UserGroupsVirtualMachineField } from '~/views-components/form-fields/user-form-fields';
+import { UserEmailField, UserVirtualMachineField, UserGroupsVirtualMachineField } from '~/views-components/form-fields/user-form-fields';
export type DialogUserProps = WithDialogProps<{}> & InjectedFormProps<any>;
const UserAddFields = (props: DialogUserProps) => <span>
<UserEmailField />
- <UserIdentityUrlField />
<UserVirtualMachineField data={props.data}/>
<UserGroupsVirtualMachineField />
</span>;
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+import * as 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 { USER_LENGTH_VALIDATION } from '~/validators/validators';
+import { InputLabel } from '@material-ui/core';
+import { NativeSelectField } from '~/components/select-field/select-field';
+import { SETUP_SHELL_ACCOUNT_DIALOG, createUser } from '~/store/users/users-actions';
+
+interface SetupShellAccountFormDialogData {
+ email: string;
+ virtualMachineName: string;
+ groupVirtualMachine: string;
+}
+
+export const SetupShellAccountDialog = compose(
+ withDialog(SETUP_SHELL_ACCOUNT_DIALOG),
+ reduxForm<SetupShellAccountFormDialogData>({
+ form: SETUP_SHELL_ACCOUNT_DIALOG,
+ onSubmit: (data, dispatch) => {
+ dispatch(createUser(data));
+ }
+ })
+)(
+ (props: SetupShellAccountDialogComponentProps) =>
+ <FormDialog
+ dialogTitle='Setup shell account'
+ formFields={SetupShellAccountFormFields}
+ submitLabel='Submit'
+ {...props}
+ />
+);
+
+const UserEmailField = ({ data }: any) =>
+ <Field
+ name='email'
+ component={TextField}
+ disabled
+ label={data.user.email} />;
+
+const UserVirtualMachineField = ({ data }: any) =>
+ <div style={{ marginBottom: '21px' }}>
+ <InputLabel>Virtual Machine</InputLabel>
+ <Field
+ name='virtualMachine'
+ component={NativeSelectField}
+ validate={USER_LENGTH_VALIDATION}
+ items={getVirtualMachinesList(data.items)} />
+ </div>;
+
+const UserGroupsVirtualMachineField = () =>
+ <Field
+ name='groups'
+ component={TextField}
+ validate={USER_LENGTH_VALIDATION}
+ label="Groups for virtual machine (comma separated list)" />;
+
+const getVirtualMachinesList = (virtualMachines: VirtualMachinesResource[]) => {
+ const mappedVirtualMachines = virtualMachines.map(it => ({ key: it.hostname, value: it.hostname }));
+ return mappedVirtualMachines;
+};
+
+type SetupShellAccountDialogComponentProps = WithDialogProps<{}> & InjectedFormProps<SetupShellAccountFormDialogData>;
+
+const SetupShellAccountFormFields = (props: SetupShellAccountDialogComponentProps) =>
+ <>
+ <UserEmailField data={props.data}/>
+ <UserVirtualMachineField data={props.data} />
+ <UserGroupsVirtualMachineField />
+ </>;
+
+
+
autoFocus={true}
label="Email" />;
-export const UserIdentityUrlField = () =>
- <Field
- name='identityUrl'
- component={TextField}
- validate={USER_LENGTH_VALIDATION}
- label="Identity URL Prefix" />;
-
export const UserVirtualMachineField = ({ data }: any) =>
<div style={{ marginBottom: '21px' }}>
<InputLabel>Virtual Machine</InputLabel>
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+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 { compose, Dispatch } from "redux";
+import { USER_MANAGE_DIALOG, openSetupShellAccount } from "~/store/users/users-actions";
+import { UserResource } from "~/models/user";
+import { connect } from "react-redux";
+
+type CssRules = 'spacing';
+
+const styles = withStyles<CssRules>((theme: ArvadosTheme) => ({
+ spacing: {
+ paddingBottom: theme.spacing.unit * 2,
+ paddingTop: theme.spacing.unit * 2,
+ }
+}));
+
+interface UserManageDataProps {
+ data: UserResource;
+}
+
+interface UserManageActionProps {
+ openSetupShellAccount: (uuid: string) => void;
+}
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+ openSetupShellAccount: (uuid: string) => dispatch<any>(openSetupShellAccount(uuid))
+});
+
+type UserManageProps = UserManageDataProps & UserManageActionProps & WithStyles<CssRules>;
+
+export const UserManageDialog = compose(
+ connect(null, mapDispatchToProps),
+ withDialog(USER_MANAGE_DIALOG),
+ styles)(
+ (props: WithDialogProps<UserManageProps> & UserManageProps) =>
+ <Dialog open={props.open}
+ onClose={props.closeDialog}
+ fullWidth
+ maxWidth="md">
+ <DialogTitle>{`Manage - ${props.data.firstName} ${props.data.lastName}`}</DialogTitle>
+ <DialogContent>
+ <Typography variant="body2" className={props.classes.spacing}>
+ 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.
+ </Typography>
+ <Button variant="contained" color="primary">
+ {`LOG IN AS ${props.data.firstName} ${props.data.lastName}`}
+ </Button>
+ <Typography variant="body2" className={props.classes.spacing}>
+ 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.
+ </Typography>
+ <Button variant="contained" color="primary" onClick={() => props.openSetupShellAccount(props.data.uuid)}>
+ {`SETUP SHELL ACCOUNT FOR ${props.data.firstName} ${props.data.lastName}`}
+ </Button>
+ </DialogContent>
+ <DialogActions>
+ <Button
+ variant='flat'
+ color='primary'
+ onClick={props.closeDialog}>
+ Close
+ </Button>
+ </DialogActions>
+ </Dialog>
+ );
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 { SetupShellAccountDialog } from '~/views-components/dialog-forms/setup-shell-account-dialog';
import { GroupsPanel } from '~/views/groups-panel/groups-panel';
import { CreateGroupDialog } from '~/views-components/dialog-forms/create-group-dialog';
import { RemoveGroupDialog } from '~/views-components/groups-dialog/remove-dialog';
<RepositoryAttributesDialog />
<RepositoriesSampleGitDialog />
<RichTextEditorDialog />
+ <SetupShellAccountDialog />
<SharingDialog />
<Snackbar />
<UpdateCollectionDialog />
<UpdateProcessDialog />
<UpdateProjectDialog />
<UserAttributesDialog />
+ <UserManageDialog />
<VirtualMachineAttributesDialog />
</Grid>
);
\ No newline at end of file