[ARVADOS-WORKBENCH2] updated: 1.3.0-18-gfc3370a
Git user
git at public.curoverse.com
Wed Dec 5 05:46:51 EST 2018
Summary of changes:
src/components/data-explorer/data-explorer.tsx | 10 ++--
src/index.tsx | 42 ++++++++--------
src/store/advanced-tab/advanced-tab.ts | 57 ++++++++++++++++++++--
src/store/users/users-actions.ts | 6 ++-
...al-machine-action-set.ts => user-action-set.ts} | 23 ++++++---
src/views-components/context-menu/context-menu.tsx | 3 +-
.../attributes-dialog.tsx | 34 ++++++++-----
src/views/user-panel/user-panel.tsx | 3 +-
src/views/workbench/workbench.tsx | 2 +
9 files changed, 126 insertions(+), 54 deletions(-)
copy src/views-components/context-menu/action-sets/{virtual-machine-action-set.ts => user-action-set.ts} (53%)
copy src/views-components/{virtual-machines-dialog => user-dialog}/attributes-dialog.tsx (70%)
via fc3370a1203ae0b83a13ef6a958219cc722cfe75 (commit)
from dc95b803fa84b3c9ef7c11a4f81dd0d86077d779 (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 fc3370a1203ae0b83a13ef6a958219cc722cfe75
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date: Wed Dec 5 11:46:34 2018 +0100
context-menu-for-user-data-explorer
Feature #14504
Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index 3b09b5b..69f93dd 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -4,13 +4,13 @@
import * as React from 'react';
import { Grid, Paper, Toolbar, StyleRulesCallback, withStyles, WithStyles, TablePagination, IconButton, Tooltip } from '@material-ui/core';
-import { ColumnSelector } from "../column-selector/column-selector";
-import { DataTable, DataColumns } from "../data-table/data-table";
-import { DataColumn, SortDirection } from "../data-table/data-column";
-import { SearchInput } from '../search-input/search-input';
+import { ColumnSelector } from "~/components/column-selector/column-selector";
+import { DataTable, DataColumns } from "~/components/data-table/data-table";
+import { DataColumn, SortDirection } from "~/components/data-table/data-column";
+import { SearchInput } from '~/components/search-input/search-input';
import { ArvadosTheme } from "~/common/custom-theme";
import { createTree } from '~/models/tree';
-import { DataTableFilters } from '../data-table-filters/data-table-filters-tree';
+import { DataTableFilters } from '~/components/data-table-filters/data-table-filters-tree';
import { MoreOptionsIcon } from '~/components/icon/icon';
type CssRules = 'searchBox' | "toolbar" | "footer" | "root" | 'moreOptionsButton';
diff --git a/src/index.tsx b/src/index.tsx
index d838596..96df16c 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -5,31 +5,31 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from "react-redux";
-import { MainPanel } from './views/main-panel/main-panel';
-import './index.css';
+import { MainPanel } from '~/views/main-panel/main-panel';
+import '~/index.css';
import { Route, Switch } from 'react-router';
import createBrowserHistory from "history/createBrowserHistory";
import { History } from "history";
-import { configureStore, RootStore } from './store/store';
+import { configureStore, RootStore } from '~/store/store';
import { ConnectedRouter } from "react-router-redux";
-import { ApiToken } from "./views-components/api-token/api-token";
-import { initAuth } from "./store/auth/auth-action";
-import { createServices } from "./services/services";
+import { ApiToken } from "~/views-components/api-token/api-token";
+import { initAuth } from "~/store/auth/auth-action";
+import { createServices } from "~/services/services";
import { MuiThemeProvider } from '@material-ui/core/styles';
-import { CustomTheme } from './common/custom-theme';
-import { fetchConfig } from './common/config';
-import { addMenuActionSet, ContextMenuKind } from './views-components/context-menu/context-menu';
-import { rootProjectActionSet } from "./views-components/context-menu/action-sets/root-project-action-set";
-import { projectActionSet } from "./views-components/context-menu/action-sets/project-action-set";
-import { resourceActionSet } from './views-components/context-menu/action-sets/resource-action-set';
-import { favoriteActionSet } from "./views-components/context-menu/action-sets/favorite-action-set";
-import { collectionFilesActionSet } from './views-components/context-menu/action-sets/collection-files-action-set';
-import { collectionFilesItemActionSet } from './views-components/context-menu/action-sets/collection-files-item-action-set';
-import { collectionFilesNotSelectedActionSet } from './views-components/context-menu/action-sets/collection-files-not-selected-action-set';
-import { collectionActionSet } from './views-components/context-menu/action-sets/collection-action-set';
-import { collectionResourceActionSet } from './views-components/context-menu/action-sets/collection-resource-action-set';
-import { processActionSet } from './views-components/context-menu/action-sets/process-action-set';
-import { loadWorkbench } from './store/workbench/workbench-actions';
+import { CustomTheme } from '~/common/custom-theme';
+import { fetchConfig } from '~/common/config';
+import { addMenuActionSet, ContextMenuKind } from '~/views-components/context-menu/context-menu';
+import { rootProjectActionSet } from "~/views-components/context-menu/action-sets/root-project-action-set";
+import { projectActionSet } from "~/views-components/context-menu/action-sets/project-action-set";
+import { resourceActionSet } from '~/views-components/context-menu/action-sets/resource-action-set';
+import { favoriteActionSet } from "~/views-components/context-menu/action-sets/favorite-action-set";
+import { collectionFilesActionSet } from '~/views-components/context-menu/action-sets/collection-files-action-set';
+import { collectionFilesItemActionSet } from '~/views-components/context-menu/action-sets/collection-files-item-action-set';
+import { collectionFilesNotSelectedActionSet } from '~/views-components/context-menu/action-sets/collection-files-not-selected-action-set';
+import { collectionActionSet } from '~/views-components/context-menu/action-sets/collection-action-set';
+import { collectionResourceActionSet } from '~/views-components/context-menu/action-sets/collection-resource-action-set';
+import { processActionSet } from '~/views-components/context-menu/action-sets/process-action-set';
+import { loadWorkbench } from '~/store/workbench/workbench-actions';
import { Routes } from '~/routes/routes';
import { trashActionSet } from "~/views-components/context-menu/action-sets/trash-action-set";
import { ServiceRepository } from '~/services/services';
@@ -53,6 +53,7 @@ import { sshKeyActionSet } from '~/views-components/context-menu/action-sets/ssh
import { keepServiceActionSet } from '~/views-components/context-menu/action-sets/keep-service-action-set';
import { loadVocabulary } from '~/store/vocabulary/vocabulary-actions';
import { virtualMachineActionSet } from '~/views-components/context-menu/action-sets/virtual-machine-action-set';
+import { userActionSet } from '~/views-components/context-menu/action-sets/user-action-set';
console.log(`Starting arvados [${getBuildInfo()}]`);
@@ -73,6 +74,7 @@ addMenuActionSet(ContextMenuKind.REPOSITORY, repositoryActionSet);
addMenuActionSet(ContextMenuKind.SSH_KEY, sshKeyActionSet);
addMenuActionSet(ContextMenuKind.VIRTUAL_MACHINE, virtualMachineActionSet);
addMenuActionSet(ContextMenuKind.KEEP_SERVICE, keepServiceActionSet);
+addMenuActionSet(ContextMenuKind.USER, userActionSet);
fetchConfig()
.then(({ config, apiHost }) => {
diff --git a/src/store/advanced-tab/advanced-tab.ts b/src/store/advanced-tab/advanced-tab.ts
index 92d14d7..67d1394 100644
--- a/src/store/advanced-tab/advanced-tab.ts
+++ b/src/store/advanced-tab/advanced-tab.ts
@@ -72,7 +72,8 @@ enum ResourcePrefix {
REPOSITORIES = 'repositories',
AUTORIZED_KEYS = 'authorized_keys',
VIRTUAL_MACHINES = 'virtual_machines',
- KEEP_SERVICES = 'keep_services'
+ KEEP_SERVICES = 'keep_services',
+ USERS = 'users'
}
enum KeepServiceData {
@@ -80,9 +81,14 @@ enum KeepServiceData {
CREATED_AT = 'created_at'
}
-type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | VirtualMachineData | KeepServiceData;
+enum UserData {
+ USER = 'user',
+ USERNAME = 'username'
+}
+
+type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | VirtualMachineData | KeepServiceData | UserData;
type AdvanceResourcePrefix = GroupContentsResourcePrefix | ResourcePrefix;
-type AdvanceResponseData = ContainerRequestResource | ProjectResource | CollectionResource | RepositoryResource | SshKeyResource | VirtualMachinesResource | KeepServiceResource | undefined;
+type AdvanceResponseData = ContainerRequestResource | ProjectResource | CollectionResource | RepositoryResource | SshKeyResource | VirtualMachinesResource | KeepServiceResource | UserResource | undefined;
export const openAdvancedTabDialog = (uuid: string) =>
async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
@@ -193,6 +199,27 @@ export const openAdvancedTabDialog = (uuid: string) =>
});
dispatch<any>(initAdvancedTabDialog(advanceDataKeepService));
break;
+ case ResourceKind.USER:
+ const { resources } = getState();
+ const data = getResource<UserResource>(uuid)(resources);
+ const metadata = await services.linkService.list({
+ filters: new FilterBuilder()
+ .addEqual('headUuid', uuid)
+ .getFilters()
+ });
+ const advanceDataUser = advancedTabData({
+ uuid,
+ metadata,
+ user: '',
+ apiResponseKind: userApiResponse,
+ data,
+ resourceKind: UserData.USER,
+ resourcePrefix: ResourcePrefix.USERS,
+ resourceKindProperty: UserData.USERNAME,
+ property: data!.username
+ });
+ dispatch<any>(initAdvancedTabDialog(advanceDataUser));
+ break;
default:
dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Could not open advanced tab for this resource.", hideDuration: 2000, kind: SnackbarKind.ERROR }));
}
@@ -441,4 +468,28 @@ const keepServiceApiResponse = (apiResponse: KeepServiceResource) => {
"read_only": "${stringify(readOnly)}"`;
return response;
+};
+
+const userApiResponse = (apiResponse: UserResource) => {
+ const {
+ uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid,
+ email, firstName, lastName, identityUrl, isActive, isAdmin, prefs, defaultOwnerUuid, username
+ } = apiResponse;
+ const response = `"uuid": "${uuid}",
+"owner_uuid": "${ownerUuid}",
+"created_at": "${createdAt}",
+"modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
+"modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
+"modified_at": ${stringify(modifiedAt)},
+"email": "${email}",
+"first_name": "${firstName}",
+"last_name": "${stringify(lastName)}",
+"identity_url": "${identityUrl}",
+"is_active": "${isActive},
+"is_admin": "${isAdmin},
+"prefs": "${stringifyObject(prefs)},
+"default_owner_uuid": "${defaultOwnerUuid},
+"username": "${username}"`;
+
+ return response;
};
\ No newline at end of file
diff --git a/src/store/users/users-actions.ts b/src/store/users/users-actions.ts
index 8ec373a..43d9e6f 100644
--- a/src/store/users/users-actions.ts
+++ b/src/store/users/users-actions.ts
@@ -13,6 +13,7 @@ import { startSubmit, reset, stopSubmit } from "redux-form";
import { getCommonResourceServiceError, CommonResourceServiceError } from "~/services/common-service/common-resource-service";
import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
import { UserResource } from "~/models/user";
+import { getResource } from '~/store/resources/resources';
export const usersPanelActions = unionize({
SET_USERS: ofType<any>(),
@@ -27,8 +28,9 @@ export const USER_REMOVE_DIALOG = 'repositoryRemoveDialog';
export const openUserAttributes = (uuid: string) =>
(dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- const repositoryData = getState().repositories.items.find(it => it.uuid === uuid);
- dispatch(dialogActions.OPEN_DIALOG({ id: USER_ATTRIBUTES_DIALOG, data: { repositoryData } }));
+ const { resources } = getState();
+ const data = getResource<UserResource>(uuid)(resources);
+ dispatch(dialogActions.OPEN_DIALOG({ id: USER_ATTRIBUTES_DIALOG, data }));
};
export const openUserCreateDialog = () =>
diff --git a/src/views-components/context-menu/action-sets/user-action-set.ts b/src/views-components/context-menu/action-sets/user-action-set.ts
new file mode 100644
index 0000000..e06a7c2
--- /dev/null
+++ b/src/views-components/context-menu/action-sets/user-action-set.ts
@@ -0,0 +1,35 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuActionSet } from "~/views-components/context-menu/context-menu-action-set";
+import { AdvancedIcon, ProjectIcon, AttributesIcon, ShareIcon } from "~/components/icon/icon";
+import { openAdvancedTabDialog } from '~/store/advanced-tab/advanced-tab';
+import { openUserAttributes } from "~/store/users/users-actions";
+
+export const userActionSet: ContextMenuActionSet = [[{
+ name: "Attributes",
+ icon: AttributesIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(openUserAttributes(uuid));
+ }
+}, {
+ name: "Project",
+ icon: ProjectIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(openAdvancedTabDialog(uuid));
+ }
+}, {
+ name: "Advanced",
+ icon: AdvancedIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(openAdvancedTabDialog(uuid));
+ }
+},
+{
+ name: "Manage",
+ icon: ShareIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(openAdvancedTabDialog(uuid));
+ }
+}]];
diff --git a/src/views-components/context-menu/context-menu.tsx b/src/views-components/context-menu/context-menu.tsx
index 5f321bf..29b8afb 100644
--- a/src/views-components/context-menu/context-menu.tsx
+++ b/src/views-components/context-menu/context-menu.tsx
@@ -72,5 +72,6 @@ export enum ContextMenuKind {
REPOSITORY = "Repository",
SSH_KEY = "SshKey",
VIRTUAL_MACHINE = "VirtualMachine",
- KEEP_SERVICE = "KeepService"
+ KEEP_SERVICE = "KeepService",
+ USER = "User"
}
diff --git a/src/views-components/user-dialog/attributes-dialog.tsx b/src/views-components/user-dialog/attributes-dialog.tsx
new file mode 100644
index 0000000..5f711de
--- /dev/null
+++ b/src/views-components/user-dialog/attributes-dialog.tsx
@@ -0,0 +1,97 @@
+// 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, Grid } 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 } from "redux";
+import { USER_ATTRIBUTES_DIALOG } from "~/store/users/users-actions";
+import { UserResource } from "~/models/user";
+
+type CssRules = 'rightContainer' | 'leftContainer' | 'spacing';
+
+const styles = withStyles<CssRules>((theme: ArvadosTheme) => ({
+ rightContainer: {
+ textAlign: 'right',
+ paddingRight: theme.spacing.unit * 2,
+ color: theme.palette.grey["500"]
+ },
+ leftContainer: {
+ textAlign: 'left',
+ paddingLeft: theme.spacing.unit * 2
+ },
+ spacing: {
+ paddingTop: theme.spacing.unit * 2
+ },
+}));
+
+interface UserAttributesDataProps {
+ data: UserResource;
+}
+
+type UserAttributesProps = UserAttributesDataProps & WithStyles<CssRules>;
+
+export const UserAttributesDialog = compose(
+ withDialog(USER_ATTRIBUTES_DIALOG),
+ styles)(
+ (props: WithDialogProps<UserAttributesProps> & UserAttributesProps) =>
+ <Dialog open={props.open}
+ onClose={props.closeDialog}
+ fullWidth
+ maxWidth="sm">
+ <DialogTitle>Attributes</DialogTitle>
+ <DialogContent>
+ <Typography variant="body2" className={props.classes.spacing}>
+ {props.data && attributes(props.data, props.classes)}
+ </Typography>
+ </DialogContent>
+ <DialogActions>
+ <Button
+ variant='flat'
+ color='primary'
+ onClick={props.closeDialog}>
+ Close
+ </Button>
+ </DialogActions>
+ </Dialog>
+ );
+
+const attributes = (user: UserResource, classes: any) => {
+ const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, firstName, lastName, href, identityUrl, username } = user;
+ return (
+ <span>
+ <Grid container direction="row">
+ <Grid item xs={5} className={classes.rightContainer}>
+ <Grid item>First name</Grid>
+ <Grid item>Last name</Grid>
+ <Grid item>Owner uuid</Grid>
+ <Grid item>Created at</Grid>
+ <Grid item>Modified at</Grid>
+ <Grid item>Modified by user uuid</Grid>
+ <Grid item>Modified by client uuid</Grid>
+ <Grid item>uuid</Grid>
+ <Grid item>Href</Grid>
+ <Grid item>Identity url</Grid>
+ <Grid item>Username</Grid>
+ </Grid>
+ <Grid item xs={7} className={classes.leftContainer}>
+ <Grid item>{firstName}</Grid>
+ <Grid item>{lastName}</Grid>
+ <Grid item>{ownerUuid}</Grid>
+ <Grid item>{createdAt}</Grid>
+ <Grid item>{modifiedAt}</Grid>
+ <Grid item>{modifiedByUserUuid}</Grid>
+ <Grid item>{modifiedByClientUuid}</Grid>
+ <Grid item>{uuid}</Grid>
+ <Grid item>{href}</Grid>
+ <Grid item>{identityUrl}</Grid>
+ <Grid item>{username}</Grid>
+ </Grid>
+ </Grid>
+ </span>
+ );
+};
diff --git a/src/views/user-panel/user-panel.tsx b/src/views/user-panel/user-panel.tsx
index 4b9a339..ceaba8c 100644
--- a/src/views/user-panel/user-panel.tsx
+++ b/src/views/user-panel/user-panel.tsx
@@ -133,7 +133,6 @@ export const UserPanel = compose(
})))(
class extends React.Component<UserPanelProps> {
render() {
- console.log(this.props.resources);
return <DataExplorer
id={USERS_PANEL_ID}
onRowClick={this.handleRowClick}
@@ -156,7 +155,7 @@ export const UserPanel = compose(
uuid: resource.uuid,
ownerUuid: resource.ownerUuid,
kind: resource.kind,
- menuKind: ContextMenuKind.TRASH
+ menuKind: ContextMenuKind.USER
}));
}
}
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 16032c4..11285ba 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -65,6 +65,7 @@ import { AttributesSshKeyDialog } from '~/views-components/ssh-keys-dialog/attri
import { VirtualMachineAttributesDialog } from '~/views-components/virtual-machines-dialog/attributes-dialog';
import { RemoveVirtualMachineDialog } from '~/views-components/virtual-machines-dialog/remove-dialog';
import { UserPanel } from '~/views/user-panel/user-panel';
+import { UserAttributesDialog } from '~/views-components/user-dialog/attributes-dialog';
type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
@@ -184,6 +185,7 @@ export const WorkbenchPanel =
<UpdateCollectionDialog />
<UpdateProcessDialog />
<UpdateProjectDialog />
+ <UserAttributesDialog />
<VirtualMachineAttributesDialog />
</Grid>
);
\ No newline at end of file
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list