[ARVADOS-WORKBENCH2] created: 1.4.1-293-g14304aae
Git user
git at public.arvados.org
Fri Jan 7 19:46:32 UTC 2022
at 14304aae3f34e0cf0a5c5275416abc26113d65e0 (commit)
commit 14304aae3f34e0cf0a5c5275416abc26113d65e0
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Fri Aug 14 15:41:31 2020 -0400
16683: Take count out from list params. Fix getPublicGroupUuid
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/store/data-explorer/data-explorer-middleware-service.ts b/src/store/data-explorer/data-explorer-middleware-service.ts
index a7c32f42..64e6e50b 100644
--- a/src/store/data-explorer/data-explorer-middleware-service.ts
+++ b/src/store/data-explorer/data-explorer-middleware-service.ts
@@ -35,8 +35,7 @@ export const getDataExplorerColumnFilters = <T>(columns: DataColumns<T>, columnN
export const dataExplorerToListParams = (dataExplorer: DataExplorer) => ({
limit: dataExplorer.rowsPerPage,
- offset: dataExplorer.page * dataExplorer.rowsPerPage,
- count: "none"
+ offset: dataExplorer.page * dataExplorer.rowsPerPage
});
export const listResultsToDataExplorerItemsMeta = <R>({ itemsAvailable, offset, limit }: ListResults<R>) => ({
diff --git a/src/store/workflow-panel/workflow-panel-actions.ts b/src/store/workflow-panel/workflow-panel-actions.ts
index 3f91c102..bfd899fd 100644
--- a/src/store/workflow-panel/workflow-panel-actions.ts
+++ b/src/store/workflow-panel/workflow-panel-actions.ts
@@ -50,11 +50,11 @@ export const openRunProcess = (uuid: string) =>
};
export const getPublicUserUuid = (state: RootState) => {
- const prefix = getProperty<string>(UUID_PREFIX_PROPERTY_NAME)(state.properties);
+ const prefix = state.auth.localCluster;
return `${prefix}-tpzed-anonymouspublic`;
};
export const getPublicGroupUuid = (state: RootState) => {
- const prefix = getProperty<string>(UUID_PREFIX_PROPERTY_NAME)(state.properties);
+ const prefix = state.auth.localCluster;
return `${prefix}-j7d0g-anonymouspublic`;
};
commit be94d8139ea574dc9e07766cad5408a8e9587b91
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Fri Aug 14 14:58:44 2020 -0400
16683: Remove reference to "klingenc"
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/views-components/current-token-dialog/current-token-dialog.tsx b/src/views-components/current-token-dialog/current-token-dialog.tsx
index bc0071af..e5208d44 100644
--- a/src/views-components/current-token-dialog/current-token-dialog.tsx
+++ b/src/views-components/current-token-dialog/current-token-dialog.tsx
@@ -57,7 +57,7 @@ export const CurrentTokenDialog =
</Typography>
</Typography>
<Typography paragraph={true}>
- Paste the following lines at a shell prompt to set up the necessary environment for Arvados SDKs to authenticate to your klingenc account.
+ Paste the following lines at a shell prompt to set up the necessary environment for Arvados SDKs to authenticate to your account.
</Typography>
<DefaultCodeSnippet lines={[getSnippet(data)]} />
<Typography >
commit a1ec1954154e42a374f28c2f625ebc1da9d4dd07
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Fri Aug 14 14:49:03 2020 -0400
16683: Tweak other calls to user listing to work with federated users
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/store/collections-content-address-panel/collections-content-address-middleware-service.ts b/src/store/collections-content-address-panel/collections-content-address-middleware-service.ts
index dc0f2c52..13c460f8 100644
--- a/src/store/collections-content-address-panel/collections-content-address-middleware-service.ts
+++ b/src/store/collections-content-address-panel/collections-content-address-middleware-service.ts
@@ -76,18 +76,16 @@ export class CollectionsWithSameContentAddressMiddlewareService extends DataExpl
}
});
const responseUsers = await this.services.userService.list({
- limit: dataExplorer.rowsPerPage,
- offset: dataExplorer.page * dataExplorer.rowsPerPage,
filters: new FilterBuilder()
.addIn('uuid', userUuids)
- .getFilters()
+ .getFilters(),
+ count: "none"
});
const responseGroups = await this.services.groupsService.list({
- limit: dataExplorer.rowsPerPage,
- offset: dataExplorer.page * dataExplorer.rowsPerPage,
filters: new FilterBuilder()
.addIn('uuid', groupUuids)
- .getFilters()
+ .getFilters(),
+ count: "none"
});
responseUsers.items.map(it => {
api.dispatch<any>(ownerNameActions.SET_OWNER_NAME({ name: it.uuid === userUuid ? 'User: Me' : `User: ${it.firstName} ${it.lastName}`, uuid: it.uuid }));
diff --git a/src/store/data-explorer/data-explorer-middleware-service.ts b/src/store/data-explorer/data-explorer-middleware-service.ts
index 219e7603..a7c32f42 100644
--- a/src/store/data-explorer/data-explorer-middleware-service.ts
+++ b/src/store/data-explorer/data-explorer-middleware-service.ts
@@ -36,6 +36,7 @@ export const getDataExplorerColumnFilters = <T>(columns: DataColumns<T>, columnN
export const dataExplorerToListParams = (dataExplorer: DataExplorer) => ({
limit: dataExplorer.rowsPerPage,
offset: dataExplorer.page * dataExplorer.rowsPerPage,
+ count: "none"
});
export const listResultsToDataExplorerItemsMeta = <R>({ itemsAvailable, offset, limit }: ListResults<R>) => ({
diff --git a/src/store/group-details-panel/group-details-panel-middleware-service.ts b/src/store/group-details-panel/group-details-panel-middleware-service.ts
index 94f78a58..5aff4e7b 100644
--- a/src/store/group-details-panel/group-details-panel-middleware-service.ts
+++ b/src/store/group-details-panel/group-details-panel-middleware-service.ts
@@ -36,7 +36,8 @@ export class GroupDetailsPanelMiddlewareService extends DataExplorerMiddlewareSe
const users = await this.services.userService.list({
filters: new FilterBuilder()
.addIn('uuid', permissions.items.map(item => item.headUuid))
- .getFilters()
+ .getFilters(),
+ count: "none"
});
api.dispatch(GroupDetailsPanelActions.SET_ITEMS({
...listResultsToDataExplorerItemsMeta(permissions),
diff --git a/src/store/users/users-actions.ts b/src/store/users/users-actions.ts
index 7b12fe75..8f696fa2 100644
--- a/src/store/users/users-actions.ts
+++ b/src/store/users/users-actions.ts
@@ -157,7 +157,7 @@ export const userBindedActions = bindDataExplorerActions(USERS_PANEL_ID);
export const loadUsersData = () =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- await services.userService.list();
+ await services.userService.list({ count: "none" });
};
export const loadUsersPanel = () =>
diff --git a/src/views-components/sharing-dialog/people-select.tsx b/src/views-components/sharing-dialog/people-select.tsx
index 90235cd5..181ff078 100644
--- a/src/views-components/sharing-dialog/people-select.tsx
+++ b/src/views-components/sharing-dialog/people-select.tsx
@@ -120,11 +120,11 @@ export const PeopleSelect = connect()(
.addNotIn('group_class', [GroupClass.PROJECT])
.addILike('name', value)
.getFilters();
- const groupItems = await groupsService.list({ filters: filterGroups, limit: 5 });
+ const groupItems = await groupsService.list({ filters: filterGroups, limit: 5, count: "none" });
const filterUsers = new FilterBuilder()
.addILike('email', value)
.getFilters();
- const userItems: any = await userService.list({ filters: filterUsers, limit: 5 });
+ const userItems: any = await userService.list({ filters: filterUsers, limit: 5, count: "none" });
const items = groupItems.items.concat(userItems.items);
this.setState({ suggestions: this.props.onlyPeople ? userItems.items : items });
}
commit 964e3cd81197d2131b5de5a77abc33dd81b2e7a4
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Aug 13 14:22:40 2020 -0400
16683: Add count: "none" to sharing dialog
To work with federated user listing.
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/store/sharing-dialog/sharing-dialog-actions.ts b/src/store/sharing-dialog/sharing-dialog-actions.ts
index 671c10fc..58fc3198 100644
--- a/src/store/sharing-dialog/sharing-dialog-actions.ts
+++ b/src/store/sharing-dialog/sharing-dialog-actions.ts
@@ -79,8 +79,8 @@ const initializeManagementForm = (permissionLinks: PermissionResource[]) =>
.addIn('uuid', permissionLinks.map(({ tailUuid }) => tailUuid))
.getFilters();
- const { items: users } = await userService.list({ filters });
- const { items: groups} = await groupsService.list({ filters });
+ const { items: users } = await userService.list({ filters, count: "none" });
+ const { items: groups } = await groupsService.list({ filters, count: "none" });
const getEmail = (tailUuid: string) => {
const user = users.find(({ uuid }) => uuid === tailUuid);
commit 0fca724529ecc364ebbdb7bb1366ffff0d08bbd9
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Jun 2 16:05:22 2020 -0300
16439: Disables +NEW button even on trashed subprojects.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/views-components/side-panel-button/side-panel-button.tsx b/src/views-components/side-panel-button/side-panel-button.tsx
index 4e2e90f1..5e547740 100644
--- a/src/views-components/side-panel-button/side-panel-button.tsx
+++ b/src/views-components/side-panel-button/side-panel-button.tsx
@@ -17,6 +17,7 @@ import { getUserUuid } from '~/common/getuser';
import { matchProjectRoute } from '~/routes/routes';
import { GroupResource } from '~/models/group';
import { ResourcesState, getResource } from '~/store/resources/resources';
+import { extractUuidKind, ResourceKind } from '~/models/resource';
type CssRules = 'button' | 'menuItem' | 'icon';
@@ -53,6 +54,13 @@ const transformOrigin: PopoverOrigin = {
horizontal: 0
};
+const isProjectTrashed = (proj: GroupResource, resources: ResourcesState): boolean => {
+ if (proj.isTrashed) { return true; }
+ if (extractUuidKind(proj.ownerUuid) === ResourceKind.USER) { return false; }
+ const parentProj = getResource<GroupResource>(proj.ownerUuid)(resources);
+ return isProjectTrashed(parentProj!, resources);
+};
+
export const SidePanelButton = withStyles(styles)(
connect((state: RootState) => ({
currentItemId: state.router.location
@@ -78,7 +86,7 @@ export const SidePanelButton = withStyles(styles)(
const currentProject = getResource<GroupResource>(currentItemId)(resources);
if (currentProject &&
currentProject.writableBy.indexOf(currentUserUUID || '') >= 0 &&
- !currentProject.isTrashed) {
+ !isProjectTrashed(currentProject, resources)) {
enabled = true;
}
}
commit 5c17f40de035a71cb05fc0b7f80bbf6550da2c31
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Jun 2 15:47:42 2020 -0300
16439: Fixes colletion/project creation placement.
When the user was placed on other sections than 'Projects' on the side
panel, the newly created collections/projects were going to the user's
home project.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts
index 140756bf..b6f0ddcc 100644
--- a/src/store/collections/collection-create-actions.ts
+++ b/src/store/collections/collection-create-actions.ts
@@ -12,7 +12,7 @@ import { getCommonResourceServiceError, CommonResourceServiceError } from "~/ser
import { uploadCollectionFiles } from './collection-upload-actions';
import { fileUploaderActions } from '~/store/file-uploader/file-uploader-actions';
import { progressIndicatorActions } from "~/store/progress-indicator/progress-indicator-actions";
-import { isItemNotInProject, isProjectOrRunProcessRoute } from '~/store/projects/project-create-actions';
+import { isProjectOrRunProcessRoute } from '~/store/projects/project-create-actions';
import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
import { CollectionResource } from "~/models/collection";
@@ -26,9 +26,8 @@ export const COLLECTION_CREATE_FORM_NAME = "collectionCreateFormName";
export const openCollectionCreateDialog = (ownerUuid: string) =>
(dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- const router = getState();
- const properties = getState().properties;
- if (isItemNotInProject(properties) || !isProjectOrRunProcessRoute(router)) {
+ const { router } = getState();
+ if (!isProjectOrRunProcessRoute(router)) {
const userUuid = getUserUuid(getState());
if (!userUuid) { return; }
dispatch(initialize(COLLECTION_CREATE_FORM_NAME, { ownerUuid: userUuid }));
diff --git a/src/store/projects/project-create-actions.ts b/src/store/projects/project-create-actions.ts
index 6f45bc38..583a4bd6 100644
--- a/src/store/projects/project-create-actions.ts
+++ b/src/store/projects/project-create-actions.ts
@@ -12,6 +12,7 @@ import { ProjectResource } from '~/models/project';
import { ServiceRepository } from '~/services/services';
import { matchProjectRoute, matchRunProcessRoute } from '~/routes/routes';
import { ResourcePropertiesFormData } from '~/views-components/resource-properties-form/resource-properties-form';
+import { RouterState } from "react-router-redux";
export interface ProjectCreateFormDialogData {
ownerUuid: string;
@@ -28,26 +29,17 @@ export const PROJECT_CREATE_FORM_NAME = 'projectCreateFormName';
export const PROJECT_CREATE_PROPERTIES_FORM_NAME = 'projectCreatePropertiesFormName';
export const PROJECT_CREATE_FORM_SELECTOR = formValueSelector(PROJECT_CREATE_FORM_NAME);
-export const isProjectOrRunProcessRoute = ({ router }: RootState) => {
+export const isProjectOrRunProcessRoute = (router: RouterState) => {
const pathname = router.location ? router.location.pathname : '';
const matchProject = matchProjectRoute(pathname);
const matchRunProcess = matchRunProcessRoute(pathname);
return Boolean(matchProject || matchRunProcess);
};
-export const isItemNotInProject = (properties: any) => {
- if (properties.breadcrumbs) {
- return Boolean(properties.breadcrumbs[0].label !== 'Projects');
- } else {
- return;
- }
-};
-
export const openProjectCreateDialog = (ownerUuid: string) =>
(dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- const router = getState();
- const properties = getState().properties;
- if (isItemNotInProject(properties) || !isProjectOrRunProcessRoute(router)) {
+ const { router } = getState();
+ if (!isProjectOrRunProcessRoute(router)) {
const userUuid = getUserUuid(getState());
if (!userUuid) { return; }
dispatch(initialize(PROJECT_CREATE_FORM_NAME, { ownerUuid: userUuid }));
commit 43893508f11ffc3841e59f445e29c62c91b026d7
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Jun 1 18:30:19 2020 -0300
16439: Enables the +NEW button only when the user's view is writable.
Also, makes the SidePanelButton component to not depend on a state property
set by a something rendered later, because that makes the button being
re-renderered at least twice on every location change, instead try to get the
current item id from the location url.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/views-components/side-panel-button/side-panel-button.tsx b/src/views-components/side-panel-button/side-panel-button.tsx
index 0f797590..4e2e90f1 100644
--- a/src/views-components/side-panel-button/side-panel-button.tsx
+++ b/src/views-components/side-panel-button/side-panel-button.tsx
@@ -5,8 +5,6 @@
import * as React from 'react';
import { connect, DispatchProp } from 'react-redux';
import { RootState } from '~/store/store';
-import { getProperty } from '~/store/properties/properties';
-import { PROJECT_PANEL_CURRENT_UUID } from '~/store/project-panel/project-panel-action';
import { ArvadosTheme } from '~/common/custom-theme';
import { PopoverOrigin } from '@material-ui/core/Popover';
import { StyleRulesCallback, WithStyles, withStyles, Toolbar, Grid, Button, MenuItem, Menu } from '@material-ui/core';
@@ -15,6 +13,10 @@ import { openProjectCreateDialog } from '~/store/projects/project-create-actions
import { openCollectionCreateDialog } from '~/store/collections/collection-create-actions';
import { navigateToRunProcess } from '~/store/navigation/navigation-action';
import { runProcessPanelActions } from '~/store/run-process-panel/run-process-panel-actions';
+import { getUserUuid } from '~/common/getuser';
+import { matchProjectRoute } from '~/routes/routes';
+import { GroupResource } from '~/models/group';
+import { ResourcesState, getResource } from '~/store/resources/resources';
type CssRules = 'button' | 'menuItem' | 'icon';
@@ -36,6 +38,8 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
interface SidePanelDataProps {
location: any;
currentItemId: string;
+ resources: ResourcesState;
+ currentUserUUID: string | undefined;
}
interface SidePanelState {
@@ -51,8 +55,12 @@ const transformOrigin: PopoverOrigin = {
export const SidePanelButton = withStyles(styles)(
connect((state: RootState) => ({
- currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties),
- location: state.router.location
+ currentItemId: state.router.location
+ ? state.router.location.pathname.split('/').slice(-1)[0]
+ : null,
+ location: state.router.location,
+ resources: state.resources,
+ currentUserUUID: getUserUuid(state),
}))(
class extends React.Component<SidePanelProps> {
@@ -61,12 +69,24 @@ export const SidePanelButton = withStyles(styles)(
};
render() {
- const { classes } = this.props;
+ const { classes, location, resources, currentUserUUID, currentItemId } = this.props;
const { anchorEl } = this.state;
+ let enabled = false;
+ if (currentItemId === currentUserUUID) {
+ enabled = true;
+ } else if (matchProjectRoute(location ? location.pathname : '')) {
+ const currentProject = getResource<GroupResource>(currentItemId)(resources);
+ if (currentProject &&
+ currentProject.writableBy.indexOf(currentUserUUID || '') >= 0 &&
+ !currentProject.isTrashed) {
+ enabled = true;
+ }
+ }
return <Toolbar>
<Grid container>
<Grid container item xs alignItems="center" justify="flex-start">
- <Button variant="contained" color="primary" size="small" className={classes.button}
+ <Button variant="contained" disabled={!enabled}
+ color="primary" size="small" className={classes.button}
aria-owns={anchorEl ? 'aside-menu-list' : undefined}
aria-haspopup="true"
onClick={this.handleOpen}>
@@ -104,7 +124,7 @@ export const SidePanelButton = withStyles(styles)(
this.props.dispatch(runProcessPanelActions.RESET_RUN_PROCESS_PANEL());
this.props.dispatch(runProcessPanelActions.SET_PROCESS_PATHNAME(location.pathname));
this.props.dispatch(runProcessPanelActions.SET_PROCESS_OWNER_UUID(this.props.currentItemId));
-
+
this.props.dispatch<any>(navigateToRunProcess);
}
commit e0357748cb73aa795970bb8cd2f495bd310e6b89
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Jun 1 10:49:29 2020 -0300
16439: Reduces vertical spacing between form elements.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/form-dialog/form-dialog.tsx b/src/components/form-dialog/form-dialog.tsx
index e95693df..3df874b7 100644
--- a/src/components/form-dialog/form-dialog.tsx
+++ b/src/components/form-dialog/form-dialog.tsx
@@ -16,22 +16,24 @@ const styles: StyleRulesCallback<CssRules> = theme => ({
},
lastButton: {
marginLeft: theme.spacing.unit,
- marginRight: "20px",
+ marginRight: "0",
},
formContainer: {
display: "flex",
flexDirection: "column",
- marginTop: "20px",
+ paddingBottom: "0",
},
dialogTitle: {
- paddingBottom: "0"
+ paddingTop: theme.spacing.unit,
+ paddingBottom: theme.spacing.unit,
},
progressIndicator: {
position: "absolute",
minWidth: "20px",
},
dialogActions: {
- marginBottom: theme.spacing.unit * 3
+ marginBottom: theme.spacing.unit,
+ marginRight: theme.spacing.unit * 3,
}
});
diff --git a/src/components/text-field/text-field.tsx b/src/components/text-field/text-field.tsx
index 82d640d8..1cf9a81d 100644
--- a/src/components/text-field/text-field.tsx
+++ b/src/components/text-field/text-field.tsx
@@ -19,7 +19,7 @@ type CssRules = 'textField' | 'rte';
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
textField: {
- marginBottom: theme.spacing.unit * 3
+ marginBottom: theme.spacing.unit
},
rte: {
fontFamily: 'Arial',
diff --git a/src/views-components/dialog-create/dialog-collection-create.tsx b/src/views-components/dialog-create/dialog-collection-create.tsx
index 86d6a217..a70030c7 100644
--- a/src/views-components/dialog-create/dialog-collection-create.tsx
+++ b/src/views-components/dialog-create/dialog-collection-create.tsx
@@ -9,7 +9,7 @@ import { CollectionCreateFormDialogData } from '~/store/collections/collection-c
import { FormDialog } from '~/components/form-dialog/form-dialog';
import { CollectionNameField, CollectionDescriptionField } from '~/views-components/form-fields/collection-form-fields';
import { FileUploaderField } from '../file-uploader/file-uploader';
-import { ResourceLocationField } from '../form-fields/resource-form-fields';
+import { ResourceParentField } from '../form-fields/resource-form-fields';
type DialogCollectionProps = WithDialogProps<{}> & InjectedFormProps<CollectionCreateFormDialogData>;
@@ -22,7 +22,7 @@ export const DialogCollectionCreate = (props: DialogCollectionProps) =>
/>;
const CollectionAddFields = () => <span>
- <ResourceLocationField />
+ <ResourceParentField />
<CollectionNameField />
<CollectionDescriptionField />
<Field
diff --git a/src/views-components/dialog-create/dialog-project-create.tsx b/src/views-components/dialog-create/dialog-project-create.tsx
index 7359ba84..c835e04e 100644
--- a/src/views-components/dialog-create/dialog-project-create.tsx
+++ b/src/views-components/dialog-create/dialog-project-create.tsx
@@ -10,7 +10,7 @@ import { FormDialog } from '~/components/form-dialog/form-dialog';
import { ProjectNameField, ProjectDescriptionField } from '~/views-components/form-fields/project-form-fields';
import { CreateProjectPropertiesForm } from '~/views-components/project-properties/create-project-properties-form';
import { CreateProjectPropertiesList } from '~/views-components/project-properties/create-project-properties-list';
-import { ResourceLocationField } from '../form-fields/resource-form-fields';
+import { ResourceParentField } from '../form-fields/resource-form-fields';
type DialogProjectProps = WithDialogProps<{}> & InjectedFormProps<ProjectCreateFormDialogData>;
@@ -23,7 +23,7 @@ export const DialogProjectCreate = (props: DialogProjectProps) =>
/>;
const ProjectAddFields = () => <span>
- <ResourceLocationField />
+ <ResourceParentField />
<ProjectNameField />
<ProjectDescriptionField />
<CreateProjectPropertiesForm />
diff --git a/src/views-components/form-fields/resource-form-fields.tsx b/src/views-components/form-fields/resource-form-fields.tsx
index 60bcafc0..0c4ae64a 100644
--- a/src/views-components/form-fields/resource-form-fields.tsx
+++ b/src/views-components/form-fields/resource-form-fields.tsx
@@ -11,19 +11,19 @@ import { GroupResource } from "~/models/group";
import { TextField } from "~/components/text-field/text-field";
import { getUserUuid } from "~/common/getuser";
-interface ResourceLocationFieldProps {
+interface ResourceParentFieldProps {
resources: ResourcesState;
userUuid: string|undefined;
}
-export const ResourceLocationField = connect(
+export const ResourceParentField = connect(
(state: RootState) => {
return {
resources: state.resources,
userUuid: getUserUuid(state),
};
})
- ((props: ResourceLocationFieldProps) =>
+ ((props: ResourceParentFieldProps) =>
<Field
name='ownerUuid'
disabled={true}
commit 36a400f4b2a04ccbcc7c43db984fc0062aa96042
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Fri May 29 15:59:42 2020 -0300
16439: Updates field label.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/views-components/form-fields/resource-form-fields.tsx b/src/views-components/form-fields/resource-form-fields.tsx
index 0ba357c3..60bcafc0 100644
--- a/src/views-components/form-fields/resource-form-fields.tsx
+++ b/src/views-components/form-fields/resource-form-fields.tsx
@@ -27,7 +27,7 @@ export const ResourceLocationField = connect(
<Field
name='ownerUuid'
disabled={true}
- label='Location'
+ label='Parent project'
format={
(value, name) => {
if (value === props.userUuid) {
@@ -35,7 +35,7 @@ export const ResourceLocationField = connect(
}
const rsc = getResource<GroupResource>(value)(props.resources);
if (rsc !== undefined) {
- return `Project '${rsc.name}' (${rsc.uuid})`;
+ return `${rsc.name} (${rsc.uuid})`;
}
return value;
}
commit 99dd1757aa26b258aee49c631af39097db1a8bcf
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Fri May 29 11:05:24 2020 -0300
16439: Adds read-only field 'Location' to project/collection creation dialogs.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts
index 39565f1d..140756bf 100644
--- a/src/store/collections/collection-create-actions.ts
+++ b/src/store/collections/collection-create-actions.ts
@@ -31,7 +31,7 @@ export const openCollectionCreateDialog = (ownerUuid: string) =>
if (isItemNotInProject(properties) || !isProjectOrRunProcessRoute(router)) {
const userUuid = getUserUuid(getState());
if (!userUuid) { return; }
- dispatch(initialize(COLLECTION_CREATE_FORM_NAME, { userUuid }));
+ dispatch(initialize(COLLECTION_CREATE_FORM_NAME, { ownerUuid: userUuid }));
} else {
dispatch(initialize(COLLECTION_CREATE_FORM_NAME, { ownerUuid }));
}
diff --git a/src/store/projects/project-create-actions.ts b/src/store/projects/project-create-actions.ts
index a303b551..6f45bc38 100644
--- a/src/store/projects/project-create-actions.ts
+++ b/src/store/projects/project-create-actions.ts
@@ -50,7 +50,7 @@ export const openProjectCreateDialog = (ownerUuid: string) =>
if (isItemNotInProject(properties) || !isProjectOrRunProcessRoute(router)) {
const userUuid = getUserUuid(getState());
if (!userUuid) { return; }
- dispatch(initialize(PROJECT_CREATE_FORM_NAME, { userUuid }));
+ dispatch(initialize(PROJECT_CREATE_FORM_NAME, { ownerUuid: userUuid }));
} else {
dispatch(initialize(PROJECT_CREATE_FORM_NAME, { ownerUuid }));
}
diff --git a/src/views-components/dialog-create/dialog-collection-create.tsx b/src/views-components/dialog-create/dialog-collection-create.tsx
index fb492c43..86d6a217 100644
--- a/src/views-components/dialog-create/dialog-collection-create.tsx
+++ b/src/views-components/dialog-create/dialog-collection-create.tsx
@@ -9,7 +9,7 @@ import { CollectionCreateFormDialogData } from '~/store/collections/collection-c
import { FormDialog } from '~/components/form-dialog/form-dialog';
import { CollectionNameField, CollectionDescriptionField } from '~/views-components/form-fields/collection-form-fields';
import { FileUploaderField } from '../file-uploader/file-uploader';
-
+import { ResourceLocationField } from '../form-fields/resource-form-fields';
type DialogCollectionProps = WithDialogProps<{}> & InjectedFormProps<CollectionCreateFormDialogData>;
@@ -22,6 +22,7 @@ export const DialogCollectionCreate = (props: DialogCollectionProps) =>
/>;
const CollectionAddFields = () => <span>
+ <ResourceLocationField />
<CollectionNameField />
<CollectionDescriptionField />
<Field
diff --git a/src/views-components/dialog-create/dialog-project-create.tsx b/src/views-components/dialog-create/dialog-project-create.tsx
index 02fb67e5..7359ba84 100644
--- a/src/views-components/dialog-create/dialog-project-create.tsx
+++ b/src/views-components/dialog-create/dialog-project-create.tsx
@@ -10,6 +10,7 @@ import { FormDialog } from '~/components/form-dialog/form-dialog';
import { ProjectNameField, ProjectDescriptionField } from '~/views-components/form-fields/project-form-fields';
import { CreateProjectPropertiesForm } from '~/views-components/project-properties/create-project-properties-form';
import { CreateProjectPropertiesList } from '~/views-components/project-properties/create-project-properties-list';
+import { ResourceLocationField } from '../form-fields/resource-form-fields';
type DialogProjectProps = WithDialogProps<{}> & InjectedFormProps<ProjectCreateFormDialogData>;
@@ -22,6 +23,7 @@ export const DialogProjectCreate = (props: DialogProjectProps) =>
/>;
const ProjectAddFields = () => <span>
+ <ResourceLocationField />
<ProjectNameField />
<ProjectDescriptionField />
<CreateProjectPropertiesForm />
diff --git a/src/views-components/form-fields/resource-form-fields.tsx b/src/views-components/form-fields/resource-form-fields.tsx
new file mode 100644
index 00000000..0ba357c3
--- /dev/null
+++ b/src/views-components/form-fields/resource-form-fields.tsx
@@ -0,0 +1,44 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { connect } from "react-redux";
+import { RootState } from "~/store/store";
+import { Field } from "redux-form";
+import { ResourcesState, getResource } from "~/store/resources/resources";
+import { GroupResource } from "~/models/group";
+import { TextField } from "~/components/text-field/text-field";
+import { getUserUuid } from "~/common/getuser";
+
+interface ResourceLocationFieldProps {
+ resources: ResourcesState;
+ userUuid: string|undefined;
+}
+
+export const ResourceLocationField = connect(
+ (state: RootState) => {
+ return {
+ resources: state.resources,
+ userUuid: getUserUuid(state),
+ };
+ })
+ ((props: ResourceLocationFieldProps) =>
+ <Field
+ name='ownerUuid'
+ disabled={true}
+ label='Location'
+ format={
+ (value, name) => {
+ if (value === props.userUuid) {
+ return 'Home project';
+ }
+ const rsc = getResource<GroupResource>(value)(props.resources);
+ if (rsc !== undefined) {
+ return `Project '${rsc.name}' (${rsc.uuid})`;
+ }
+ return value;
+ }
+ }
+ component={TextField} />
+ );
commit 1d244cd80af604f70d08985ee39d4184db2177a9
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Thu May 28 15:05:01 2020 -0300
16439: Sends the user to the newly created project/collection.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts
index dbf795b6..7faad1e8 100644
--- a/src/store/workbench/workbench-actions.ts
+++ b/src/store/workbench/workbench-actions.ts
@@ -237,7 +237,7 @@ export const createProject = (data: projectCreateActions.ProjectCreateFormDialog
kind: SnackbarKind.SUCCESS
}));
await dispatch<any>(loadSidePanelTreeProjects(newProject.ownerUuid));
- dispatch<any>(reloadProjectMatchingUuid([newProject.ownerUuid]));
+ dispatch<any>(navigateTo(newProject.uuid));
}
};
@@ -301,7 +301,6 @@ export const loadCollection = (uuid: string) =>
dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.TRASH));
dispatch(loadCollectionPanel(collection.uuid));
},
-
});
}
});
@@ -316,7 +315,7 @@ export const createCollection = (data: collectionCreateActions.CollectionCreateF
kind: SnackbarKind.SUCCESS
}));
dispatch<any>(updateResources([collection]));
- dispatch<any>(reloadProjectMatchingUuid([collection.ownerUuid]));
+ dispatch<any>(navigateTo(collection.uuid));
}
};
commit f9c8d194d7a27ee7624b01877abb65dd63f51dab
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue May 26 12:18:17 2020 -0300
16439: Allows creation of empty (no files) collections.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/views-components/dialog-create/dialog-collection-create.tsx b/src/views-components/dialog-create/dialog-collection-create.tsx
index 690cf8e5..fb492c43 100644
--- a/src/views-components/dialog-create/dialog-collection-create.tsx
+++ b/src/views-components/dialog-create/dialog-collection-create.tsx
@@ -8,7 +8,6 @@ import { WithDialogProps } from '~/store/dialog/with-dialog';
import { CollectionCreateFormDialogData } from '~/store/collections/collection-create-actions';
import { FormDialog } from '~/components/form-dialog/form-dialog';
import { CollectionNameField, CollectionDescriptionField } from '~/views-components/form-fields/collection-form-fields';
-import { require } from '~/validators/require';
import { FileUploaderField } from '../file-uploader/file-uploader';
@@ -27,7 +26,6 @@ const CollectionAddFields = () => <span>
<CollectionDescriptionField />
<Field
name='files'
- validate={[require]}
label='Files'
component={FileUploaderField} />
</span>;
commit 3c722b14754ee83bf5cda8bceb8de03c28429f02
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Wed May 27 18:21:38 2020 -0300
16439: Fixes WebDAV request URL.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/common/webdav.ts b/src/common/webdav.ts
index a09e8fdd..b2f43348 100644
--- a/src/common/webdav.ts
+++ b/src/common/webdav.ts
@@ -61,7 +61,11 @@ export class WebDAV {
private request = (config: RequestConfig) => {
return new Promise<XMLHttpRequest>((resolve, reject) => {
const r = this.createRequest();
- r.open(config.method, this.defaults.baseURL + config.url);
+ this.defaults.baseURL = this.defaults.baseURL.replace(/\/+$/, '');
+ r.open(config.method,
+ `${this.defaults.baseURL
+ ? this.defaults.baseURL+'/'
+ : ''}${config.url}`);
const headers = { ...this.defaults.headers, ...config.headers };
Object
.keys(headers)
commit 6f5c42c1239fe585b805088eb2b4baf783584cc7
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Apr 6 17:15:30 2020 -0300
Upgrades vulnerable minimist module by upgrading handlebars (2 levels up).
No issue #
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/yarn.lock b/yarn.lock
index 876d073e..8ed5fe10 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4549,13 +4549,14 @@ handle-thing@^2.0.0:
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
handlebars@^4.0.3:
- version "4.7.2"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7"
- integrity sha512-4PwqDL2laXtTWZghzzCtunQUTLbo31pcCJrd/B/9JP8XbhVzpS5ZXuKqlOzsd1rtcaLo4KqAn8nl8mkknS4MHw==
+ version "4.7.6"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
+ integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
dependencies:
+ minimist "^1.2.5"
neo-async "^2.6.0"
- optimist "^0.6.1"
source-map "^0.6.1"
+ wordwrap "^1.0.0"
optionalDependencies:
uglify-js "^3.1.4"
@@ -6780,16 +6781,11 @@ minimist at 0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
+minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-minimist@~0.0.1:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
- integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
-
mississippi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
@@ -7335,14 +7331,6 @@ opn@^5.1.0, opn@^5.5.0:
dependencies:
is-wsl "^1.1.0"
-optimist@^0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
- integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
- dependencies:
- minimist "~0.0.1"
- wordwrap "~0.0.2"
-
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@@ -11008,10 +10996,10 @@ wordwrap at 0.0.2:
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=
-wordwrap@~0.0.2:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
- integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
+wordwrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
worker-farm@^1.3.1, worker-farm@^1.5.2, worker-farm@^1.7.0:
version "1.7.0"
commit 877b4f6e64dcd96b31e2ffc1610520d373c1a033
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Apr 6 16:59:19 2020 -0300
Upgrades minimist package (indirect dependency) to address CVE-2020-7598.
No issue #
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/yarn.lock b/yarn.lock
index 44b098f0..876d073e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6781,9 +6781,9 @@ minimist at 0.0.8:
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
- integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+ integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minimist@~0.0.1:
version "0.0.10"
commit 17ed55d1651843fc0ecf0ff5d62db80adfc842a1
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Mon Apr 6 16:51:53 2020 -0300
Upgrades acorn package (indirect dependency) to address a security issue.
https://www.npmjs.com/advisories/1488
No issue #
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/yarn.lock b/yarn.lock
index 41aaa359..44b098f0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -584,19 +584,14 @@ acorn@^4.0.3, acorn@^4.0.4:
integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=
acorn@^5.0.0, acorn@^5.5.3:
- version "5.7.3"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
- integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
-
-acorn@^6.0.1:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
- integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==
-
-acorn@^6.2.1:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e"
- integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==
+ version "5.7.4"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
+ integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
+
+acorn@^6.0.1, acorn@^6.2.1:
+ version "6.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
+ integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
address at 1.0.3:
version "1.0.3"
commit 188c5c005b522683143d76d26529d37b88171ba9
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Mar 10 19:11:42 2020 -0300
15951: Fixes 'select columns' button tooltip label & behavior.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/column-selector/column-selector.tsx b/src/components/column-selector/column-selector.tsx
index ccff6181..566bb9d6 100644
--- a/src/components/column-selector/column-selector.tsx
+++ b/src/components/column-selector/column-selector.tsx
@@ -55,8 +55,8 @@ export const ColumnSelector = withStyles(styles)(
);
export const ColumnSelectorTrigger = (props: IconButtonProps) =>
- <Tooltip title="Filters">
+ <Tooltip disableFocusListener title="Select columns">
<IconButton {...props}>
- <MenuIcon aria-label="Filters" />
+ <MenuIcon aria-label="Select columns" />
</IconButton>
</Tooltip>;
commit 9593a6d5074b5aa817583941089207280dc74c64
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Mar 3 22:37:21 2020 -0300
15951: Removes dead code, updates tests to work with component being used.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/data-table-filters/data-table-filters-popover.test.tsx b/src/components/data-table-filters/data-table-filters-popover.test.tsx
new file mode 100644
index 00000000..f7bd00f0
--- /dev/null
+++ b/src/components/data-table-filters/data-table-filters-popover.test.tsx
@@ -0,0 +1,24 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { mount, configure } from "enzyme";
+import { DataTableFiltersPopover } from "./data-table-filters-popover";
+import * as Adapter from 'enzyme-adapter-react-16';
+import { Checkbox, IconButton } from "@material-ui/core";
+import { getInitialProcessStatusFilters } from "~/store/resource-type-filters/resource-type-filters"
+
+configure({ adapter: new Adapter() });
+
+describe("<DataTableFiltersPopover />", () => {
+ it("renders filters according to their state", () => {
+ // 1st filter (All) is selected, the rest aren't.
+ const filters = getInitialProcessStatusFilters()
+
+ const dataTableFilter = mount(<DataTableFiltersPopover name="" filters={filters} />);
+ dataTableFilter.find(IconButton).simulate("click");
+ expect(dataTableFilter.find(Checkbox).at(0).prop("checked")).toBeTruthy();
+ expect(dataTableFilter.find(Checkbox).at(1).prop("checked")).toBeFalsy();
+ });
+});
diff --git a/src/components/data-table-filters/data-table-filters.test.tsx b/src/components/data-table-filters/data-table-filters.test.tsx
deleted file mode 100644
index dc1969f4..00000000
--- a/src/components/data-table-filters/data-table-filters.test.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import * as React from "react";
-import { mount, configure } from "enzyme";
-import { DataTableFilters } from "./data-table-filters";
-import * as Adapter from 'enzyme-adapter-react-16';
-import { Checkbox, ButtonBase } from "@material-ui/core";
-
-configure({ adapter: new Adapter() });
-
-describe("<DataTableFilter />", () => {
- it("renders filters according to their state", () => {
- const filters = [{
- name: "Filter 1",
- selected: true
- }, {
- name: "Filter 2",
- selected: false
- }];
- const dataTableFilter = mount(<DataTableFilters name="" filters={filters} />);
- dataTableFilter.find(ButtonBase).simulate("click");
- expect(dataTableFilter.find(Checkbox).at(0).prop("checked")).toBeTruthy();
- expect(dataTableFilter.find(Checkbox).at(1).prop("checked")).toBeFalsy();
- });
-});
diff --git a/src/components/data-table-filters/data-table-filters.tsx b/src/components/data-table-filters/data-table-filters.tsx
index a57f29aa..ed7b30e7 100644
--- a/src/components/data-table-filters/data-table-filters.tsx
+++ b/src/components/data-table-filters/data-table-filters.tsx
@@ -2,207 +2,7 @@
//
// SPDX-License-Identifier: AGPL-3.0
-import * as React from "react";
-import {
- WithStyles,
- withStyles,
- ButtonBase,
- StyleRulesCallback,
- Theme,
- Popover,
- List,
- ListItem,
- Checkbox,
- ListItemText,
- Button,
- Card,
- CardActions,
- Typography,
- CardContent,
- Tooltip
-} from "@material-ui/core";
-import * as classnames from "classnames";
-import { DefaultTransformOrigin } from "../popover/helpers";
-import { createTree, initTreeNode, mapTree } from '~/models/tree';
-import { DataTableFilters as DataTableFiltersModel, DataTableFiltersTree } from "./data-table-filters-tree";
-import { pipe } from 'lodash/fp';
-import { setNode } from '~/models/tree';
-
-export type CssRules = "root" | "icon" | "active" | "checkbox";
-
-const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
- root: {
- cursor: "pointer",
- display: "inline-flex",
- justifyContent: "flex-start",
- flexDirection: "inherit",
- alignItems: "center",
- "&:hover": {
- color: theme.palette.text.primary,
- },
- "&:focus": {
- color: theme.palette.text.primary,
- },
- },
- active: {
- color: theme.palette.text.primary,
- '& $icon': {
- opacity: 1,
- },
- },
- icon: {
- marginRight: 4,
- marginLeft: 4,
- opacity: 0.7,
- userSelect: "none",
- width: 16
- },
- checkbox: {
- width: 24,
- height: 24
- }
-});
-
export interface DataTableFilterItem {
name: string;
selected: boolean;
}
-
-export interface DataTableFilterProps {
- name: string;
- filters: DataTableFilterItem[];
- onChange?: (filters: DataTableFilterItem[]) => void;
-}
-
-interface DataTableFilterState {
- anchorEl?: HTMLElement;
- filters: DataTableFilterItem[];
- prevFilters: DataTableFilterItem[];
- filtersTree: DataTableFiltersModel;
-}
-
-const filters: DataTableFiltersModel = pipe(
- createTree,
- setNode(initTreeNode({ id: 'Project', value: { name: 'Project' } })),
- setNode(initTreeNode({ id: 'Process', value: { name: 'Process' } })),
- setNode(initTreeNode({ id: 'Data collection', value: { name: 'Data collection' } })),
- setNode(initTreeNode({ id: 'General', parent: 'Data collection', value: { name: 'General' } })),
- setNode(initTreeNode({ id: 'Output', parent: 'Data collection', value: { name: 'Output' } })),
- setNode(initTreeNode({ id: 'Log', parent: 'Data collection', value: { name: 'Log' } })),
- mapTree(node => ({...node, selected: true})),
-)();
-
-export const DataTableFilters = withStyles(styles)(
- class extends React.Component<DataTableFilterProps & WithStyles<CssRules>, DataTableFilterState> {
- state: DataTableFilterState = {
- anchorEl: undefined,
- filters: [],
- prevFilters: [],
- filtersTree: filters,
- };
- icon = React.createRef<HTMLElement>();
-
- render() {
- const { name, classes, children } = this.props;
- const isActive = this.state.filters.some(f => f.selected);
- return <>
- <Tooltip title='Filters'>
- <ButtonBase
- className={classnames([classes.root, { [classes.active]: isActive }])}
- component="span"
- onClick={this.open}
- disableRipple>
- {children}
- <i className={classnames(["fas fa-filter", classes.icon])}
- data-fa-transform="shrink-3"
- ref={this.icon} />
- </ButtonBase>
- </Tooltip>
- <Popover
- anchorEl={this.state.anchorEl}
- open={!!this.state.anchorEl}
- anchorOrigin={DefaultTransformOrigin}
- transformOrigin={DefaultTransformOrigin}
- onClose={this.cancel}>
- <Card>
- <CardContent>
- <Typography variant="caption">
- {name}
- </Typography>
- </CardContent>
- <List dense>
- {this.state.filters.map((filter, index) =>
- <ListItem
- key={index}>
- <Checkbox
- onClick={this.toggleFilter(filter)}
- color="primary"
- checked={filter.selected}
- className={classes.checkbox} />
- <ListItemText>
- {filter.name}
- </ListItemText>
- </ListItem>
- )}
- </List>
- <DataTableFiltersTree
- filters={this.state.filtersTree}
- onChange={filtersTree => this.setState({ filtersTree })} />
- <CardActions>
- <Button
- color="primary"
- variant='contained'
- size="small"
- onClick={this.submit}>
- Ok
- </Button>
- <Button
- color="primary"
- variant="outlined"
- size="small"
- onClick={this.cancel}>
- Cancel
- </Button>
- </CardActions >
- </Card>
- </Popover>
- </>;
- }
-
- static getDerivedStateFromProps(props: DataTableFilterProps, state: DataTableFilterState): DataTableFilterState {
- return props.filters !== state.prevFilters
- ? { ...state, filters: props.filters, prevFilters: props.filters }
- : state;
- }
-
- open = () => {
- this.setState({ anchorEl: this.icon.current || undefined });
- }
-
- submit = () => {
- const { onChange } = this.props;
- if (onChange) {
- onChange(this.state.filters);
- }
- this.setState({ anchorEl: undefined });
- }
-
- cancel = () => {
- this.setState(prev => ({
- ...prev,
- filters: prev.prevFilters,
- anchorEl: undefined
- }));
- }
-
- toggleFilter = (toggledFilter: DataTableFilterItem) => () => {
- this.setState(prev => ({
- ...prev,
- filters: prev.filters.map(filter =>
- filter === toggledFilter
- ? { ...filter, selected: !filter.selected }
- : filter)
- }));
- }
- }
-);
diff --git a/src/components/data-table/data-table.test.tsx b/src/components/data-table/data-table.test.tsx
index d0b83b96..3e4cc212 100644
--- a/src/components/data-table/data-table.test.tsx
+++ b/src/components/data-table/data-table.test.tsx
@@ -8,7 +8,6 @@ import { pipe } from 'lodash/fp';
import { TableHead, TableCell, Typography, TableBody, Button, TableSortLabel } from "@material-ui/core";
import * as Adapter from "enzyme-adapter-react-16";
import { DataTable, DataColumns } from "./data-table";
-import { DataTableFilters } from "~/components/data-table-filters/data-table-filters";
import { SortDirection, createDataColumn } from "./data-column";
import { DataTableFiltersPopover } from '~/components/data-table-filters/data-table-filters-popover';
import { createTree, setNode, initTreeNode } from '~/models/tree';
@@ -162,7 +161,7 @@ describe("<DataTable />", () => {
expect(onSortToggle).toHaveBeenCalledWith(columns[0]);
});
- it("does not display <DataTableFilter /> if there is no filters provided", () => {
+ it("does not display <DataTableFiltersPopover /> if there is no filters provided", () => {
const columns: DataColumns<string> = [{
name: "Column 1",
sortDirection: SortDirection.ASC,
@@ -180,7 +179,7 @@ describe("<DataTable />", () => {
onRowDoubleClick={jest.fn()}
onSortToggle={jest.fn()}
onContextMenu={jest.fn()} />);
- expect(dataTable.find(DataTableFilters)).toHaveLength(0);
+ expect(dataTable.find(DataTableFiltersPopover)).toHaveLength(0);
});
it("passes filter props to <DataTableFiltersPopover />", () => {
@@ -209,24 +208,4 @@ describe("<DataTable />", () => {
dataTable.find(DataTableFiltersPopover).prop("onChange")([]);
expect(onFiltersChange).toHaveBeenCalledWith([], columns[0]);
});
-
- // it("shows default view if there is no items", () => {
- // const columns: DataColumns<string> = [
- // createDataColumn({
- // name: "Column 1",
- // render: () => <span />,
- // selected: true,
- // configurable: true
- // }),
- // ];
- // const dataTable = mount(<DataTable
- // columns={columns}
- // items={[]}
- // onFiltersChange={jest.fn()}
- // onRowClick={jest.fn()}
- // onRowDoubleClick={jest.fn()}
- // onContextMenu={jest.fn()}
- // onSortToggle={jest.fn()} />);
- // expect(dataTable.find(DataTableDefaultView)).toHaveLength(1);
- // });
});
commit f1e3bc95a43facf190d5f4250299fab0a267d10b
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Mar 3 21:42:12 2020 -0300
15951: Hides tooltips on filter buttons after being clicked.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/data-table-filters/data-table-filters-popover.tsx b/src/components/data-table-filters/data-table-filters-popover.tsx
index 30b98d33..456d2375 100644
--- a/src/components/data-table-filters/data-table-filters-popover.tsx
+++ b/src/components/data-table-filters/data-table-filters-popover.tsx
@@ -108,7 +108,7 @@ export const DataTableFiltersPopover = withStyles(styles)(
: f.selected
);
return <>
- <Tooltip title='Filters'>
+ <Tooltip disableFocusListener title='Filters'>
<ButtonBase
className={classnames([classes.root, { [classes.active]: isActive }])}
component="span"
commit b76d55cc985f22cab2f59ec725f8b8a1b88d003e
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Mar 3 21:20:28 2020 -0300
15951: Accepts filter toggle actions when clicking on the entire row.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/data-table-filters/data-table-filters-tree.tsx b/src/components/data-table-filters/data-table-filters-tree.tsx
index be08743e..5f0d5e39 100644
--- a/src/components/data-table-filters/data-table-filters-tree.tsx
+++ b/src/components/data-table-filters/data-table-filters-tree.tsx
@@ -39,9 +39,12 @@ export class DataTableFiltersTree extends React.Component<DataTableFilterProps>
useRadioButtons={this.props.mutuallyExclusive}
disableRipple
onContextMenu={noop}
- toggleItemActive={this.props.mutuallyExclusive ? this.toggleRadioButtonFilter : noop}
+ toggleItemActive={
+ this.props.mutuallyExclusive
+ ? this.toggleRadioButtonFilter
+ : this.toggleFilter
+ }
toggleItemOpen={this.toggleOpen}
- toggleItemSelection={this.toggleFilter}
/>;
}
commit 65f7ca2fd28e49891f942b639be43dc4f594a379
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date: Tue Mar 3 18:45:05 2020 -0300
15951: Makes 'mutually exclusive' filter dialog auto-submit selection on click.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>
diff --git a/src/components/data-table-filters/data-table-filters-popover.tsx b/src/components/data-table-filters/data-table-filters-popover.tsx
index 670afa95..30b98d33 100644
--- a/src/components/data-table-filters/data-table-filters-popover.tsx
+++ b/src/components/data-table-filters/data-table-filters-popover.tsx
@@ -139,7 +139,15 @@ export const DataTableFiltersPopover = withStyles(styles)(
mutuallyExclusive={this.props.mutuallyExclusive}
onChange={filters => {
this.setState({ filters });
+ if (this.props.mutuallyExclusive) {
+ const { onChange } = this.props;
+ if (onChange) {
+ onChange(filters);
+ }
+ this.setState({ anchorEl: undefined });
+ }
}} />
+ {this.props.mutuallyExclusive ||
<CardActions>
<Button
color="primary"
@@ -156,6 +164,7 @@ export const DataTableFiltersPopover = withStyles(styles)(
Cancel
</Button>
</CardActions >
+ }
</Card>
</Popover>
</>;
diff --git a/src/components/data-table-filters/data-table-filters-tree.tsx b/src/components/data-table-filters/data-table-filters-tree.tsx
index d964012d..be08743e 100644
--- a/src/components/data-table-filters/data-table-filters-tree.tsx
+++ b/src/components/data-table-filters/data-table-filters-tree.tsx
@@ -37,10 +37,9 @@ export class DataTableFiltersTree extends React.Component<DataTableFilterProps>
render={renderItem}
showSelection
useRadioButtons={this.props.mutuallyExclusive}
- toggleItemRadioButton={this.toggleRadioButtonFilter}
disableRipple
onContextMenu={noop}
- toggleItemActive={noop}
+ toggleItemActive={this.props.mutuallyExclusive ? this.toggleRadioButtonFilter : noop}
toggleItemOpen={this.toggleOpen}
toggleItemSelection={this.toggleFilter}
/>;
@@ -50,7 +49,7 @@ export class DataTableFiltersTree extends React.Component<DataTableFilterProps>
* Handler for when a tree item is toggled via a radio button.
* Ensures mutual exclusivity among filter tree items.
*/
- toggleRadioButtonFilter = (item: TreeItem<DataTableFilterItem>) => {
+ toggleRadioButtonFilter = (_: any, item: TreeItem<DataTableFilterItem>) => {
const { onChange = noop } = this.props;
// If the filter is already selected, do nothing.
diff --git a/src/components/tree/tree.tsx b/src/components/tree/tree.tsx
index 67858e9b..76fbf011 100644
--- a/src/components/tree/tree.tsx
+++ b/src/components/tree/tree.tsx
@@ -98,15 +98,9 @@ export interface TreeProps<T> {
/**
* When set to true use radio buttons instead of checkboxes for item selection.
* This does not guarantee radio group behavior (i.e item mutual exclusivity).
- * Any item selection logic must be done in the toggleItemRadioButton callback prop.
+ * Any item selection logic must be done in the toggleItemActive callback prop.
*/
useRadioButtons?: boolean;
-
- /**
- * Called when selection of an item in the tree is toggled via a radio button.
- * Use this callback prop to implement any selection logic (i.e item mutual exclusivity).
- */
- toggleItemRadioButton?: (item: TreeItem<T>) => void;
}
export const Tree = withStyles(styles)(
@@ -151,8 +145,7 @@ export const Tree = withStyles(styles)(
<Radio
checked={it.selected}
className={classes.checkbox}
- color="primary"
- onChange={this.handleRadioButtonChange(it)} />}
+ color="primary" />}
<div className={renderContainer}>
{render(it, level)}
</div>
@@ -207,16 +200,6 @@ export const Tree = withStyles(styles)(
: undefined;
}
- handleRadioButtonChange = (item: TreeItem<T>) => {
- const { toggleItemRadioButton } = this.props;
- return toggleItemRadioButton
- ? (event: React.ChangeEvent<HTMLInputElement>, checked: boolean) => {
- event.stopPropagation();
- toggleItemRadioButton(item);
- }
- : undefined;
- }
-
handleToggleItemOpen = (item: TreeItem<T>) => (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
this.props.toggleItemOpen(event, item);
commit 5924c2b69f48a6b91243d1593b4f16bab0eace56
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Feb 27 14:50:28 2020 -0500
16181: Default to empty string if SSHHelpHostSuffix undefined
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
index 5e131861..49d880e5 100644
--- a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
+++ b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
@@ -60,7 +60,7 @@ const mapStateToProps = (state: RootState) => {
requestedDate: state.virtualMachines.date,
userUuid: state.auth.user!.uuid,
helpText: state.auth.config.clusterConfig.Workbench.SSHHelpPageHTML,
- hostSuffix: state.auth.config.clusterConfig.Workbench.SSHHelpHostSuffix,
+ hostSuffix: state.auth.config.clusterConfig.Workbench.SSHHelpHostSuffix || "",
webShell: state.auth.config.clusterConfig.Services.WebShell.ExternalURL,
...state.virtualMachines
};
commit 63fe27f7e2715f9e6d5ea90cd1be791ea96410da
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Feb 27 10:44:42 2020 -0500
16181: Rework the user attributes dialog a bit
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/views-components/user-dialog/attributes-dialog.tsx b/src/views-components/user-dialog/attributes-dialog.tsx
index 67b267ae..df44d62c 100644
--- a/src/views-components/user-dialog/attributes-dialog.tsx
+++ b/src/views-components/user-dialog/attributes-dialog.tsx
@@ -61,35 +61,38 @@ export const UserAttributesDialog = compose(
);
const attributes = (user: UserResource, classes: any) => {
- const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, firstName, lastName, href, username } = user;
+ const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid,
+ firstName, lastName, username, email, isActive, isAdmin } = user;
return (
<span>
<Grid container direction="row">
<Grid item xs={5} className={classes.rightContainer}>
+ {uuid && <Grid item>Uuid</Grid>}
{firstName && <Grid item>First name</Grid>}
{lastName && <Grid item>Last name</Grid>}
- {ownerUuid && <Grid item>Owner uuid</Grid>}
+ {email && <Grid item>Email</Grid>}
+ {username && <Grid item>Username</Grid>}
+ {isActive && <Grid item>Is active</Grid>}
+ {isAdmin && <Grid item>Is admin</Grid>}
{createdAt && <Grid item>Created at</Grid>}
{modifiedAt && <Grid item>Modified at</Grid>}
+ {ownerUuid && <Grid item>Owner uuid</Grid>}
{modifiedByUserUuid && <Grid item>Modified by user uuid</Grid>}
{modifiedByClientUuid && <Grid item>Modified by client uuid</Grid>}
- {uuid && <Grid item>uuid</Grid>}
- {href && <Grid item>Href</Grid>}
- {username && <Grid item>Username</Grid>}
- {username && <Grid item>Username</Grid>}
</Grid>
<Grid item xs={7} className={classes.leftContainer}>
+ <Grid item>{uuid}</Grid>
<Grid item>{firstName}</Grid>
<Grid item>{lastName}</Grid>
- <Grid item>{ownerUuid}</Grid>
+ <Grid item>{email}</Grid>
+ <Grid item>{username}</Grid>
+ <Grid item>{isActive}</Grid>
+ <Grid item>{isAdmin}</Grid>
<Grid item>{createdAt}</Grid>
<Grid item>{modifiedAt}</Grid>
+ <Grid item>{ownerUuid}</Grid>
<Grid item>{modifiedByUserUuid}</Grid>
<Grid item>{modifiedByClientUuid}</Grid>
- <Grid item>{uuid}</Grid>
- <Grid item>{href}</Grid>
- <Grid item>{username}</Grid>
- <Grid item>{username}</Grid>
</Grid>
</Grid>
</span>
commit 987db424780cd47b96305bb16ec744b284131828
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Feb 27 10:02:32 2020 -0500
16181: Support SSHHelpHostSuffix, fix user VM page render issues
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/common/config.ts b/src/common/config.ts
index 23faaf91..356ad391 100644
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@ -53,6 +53,7 @@ export interface ClusterConfigJSON {
WelcomePageHTML: string;
InactivePageHTML: string;
SSHHelpPageHTML: string;
+ SSHHelpHostSuffix: string;
SiteName: string;
};
Login: {
@@ -168,6 +169,7 @@ export const mockClusterConfigJSON = (config: Partial<ClusterConfigJSON>): Clust
WelcomePageHTML: "",
InactivePageHTML: "",
SSHHelpPageHTML: "",
+ SSHHelpHostSuffix: "",
SiteName: "",
},
Login: {
diff --git a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
index a641ec63..5e131861 100644
--- a/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
+++ b/src/views/virtual-machine-panel/virtual-machine-user-panel.tsx
@@ -12,6 +12,7 @@ import { saveRequestedDate, loadVirtualMachinesUserData } from '~/store/virtual-
import { RootState } from '~/store/store';
import { ListResults } from '~/services/common-service/common-service';
import { HelpIcon } from '~/components/icon/icon';
+// import * as CopyToClipboard from 'react-copy-to-clipboard';
type CssRules = 'button' | 'codeSnippet' | 'link' | 'linkIcon' | 'rightAlign' | 'cardWithoutMachines' | 'icon';
@@ -59,6 +60,7 @@ const mapStateToProps = (state: RootState) => {
requestedDate: state.virtualMachines.date,
userUuid: state.auth.user!.uuid,
helpText: state.auth.config.clusterConfig.Workbench.SSHHelpPageHTML,
+ hostSuffix: state.auth.config.clusterConfig.Workbench.SSHHelpHostSuffix,
webShell: state.auth.config.clusterConfig.Services.WebShell.ExternalURL,
...state.virtualMachines
};
@@ -75,6 +77,7 @@ interface VirtualMachinesPanelDataProps {
userUuid: string;
links: ListResults<any>;
helpText: string;
+ hostSuffix: string;
webShell: string;
}
@@ -166,25 +169,30 @@ const virtualMachinesTable = (props: VirtualMachineProps) =>
</TableRow>
</TableHead>
<TableBody>
- {props.virtualMachines.items.map((it, index) =>
- <TableRow key={index}>
- <TableCell>{it.hostname}</TableCell>
- <TableCell>{getUsername(props.links, props.userUuid)}</TableCell>
- <TableCell>ssh {getUsername(props.links, props.userUuid)}@{it.hostname}</TableCell>
- {props.webShell !== "" && <TableCell>
- <a href={`${props.webShell}${it.href}/webshell/${getUsername(props.links, props.userUuid)}`} target="_blank" className={props.classes.link}>
- Log in as {getUsername(props.links, props.userUuid)}
- </a>
- </TableCell>}
- </TableRow>
- )}
+ {props.virtualMachines.items.map(it =>
+ props.links.items.map(lk => {
+ if (lk.tailUuid === props.userUuid) {
+ const username = lk.properties.username;
+ const command = `ssh ${username}@${it.hostname}${props.hostSuffix}`;
+ return <TableRow key={lk.uuid}>
+ <TableCell>{it.hostname}</TableCell>
+ <TableCell>{username}</TableCell>
+ <TableCell>
+ {command}
+ </TableCell>
+ {props.webShell !== "" && <TableCell>
+ <a href={`${props.webShell}${it.href}/webshell/${username}`} target="_blank" className={props.classes.link}>
+ Log in as {username}
+ </a>
+ </TableCell>}
+ </TableRow>;
+ }
+ return;
+ }
+ ))}
</TableBody>
</Table>;
-const getUsername = (links: ListResults<any>, userUuid: string) => {
- return links.items.map(it => it.tailUuid === userUuid ? it.properties.username : '');
-};
-
const CardSSHSection = (props: VirtualMachineProps) =>
<Grid item xs={12}>
<Card>
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list