From: Pawel Kowalczyk Date: Tue, 30 Oct 2018 09:10:53 +0000 (+0100) Subject: Merge branch 'master' into 13969-advanced-tab X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/ef3b2c15f10a3fea50170bc346105d909145a98f?hp=eec72fb6bd94a219b07370120e2c2af67d562a05 Merge branch 'master' into 13969-advanced-tab refs #13969 Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk --- diff --git a/src/models/collection.ts b/src/models/collection.ts index f8e38f9a0f..a25afeb128 100644 --- a/src/models/collection.ts +++ b/src/models/collection.ts @@ -14,6 +14,10 @@ export interface CollectionResource extends TrashableResource { replicationDesired: number; replicationConfirmed: number; replicationConfirmedAt: string; + fileNames: string; + storageClassesDesired: string[]; + storageClassesConfirmed: string[]; + storageClassesConfirmedAt: string; } export const getCollectionUrl = (uuid: string) => { diff --git a/src/models/container-request.ts b/src/models/container-request.ts index e65bed9fd3..f7342d23d7 100644 --- a/src/models/container-request.ts +++ b/src/models/container-request.ts @@ -38,4 +38,5 @@ export interface ContainerRequestResource extends Resource { logUuid: string | null; outputUuid: string | null; filters: string; + containerCount: number; } diff --git a/src/store/advanced-tab/advanced-tab.ts b/src/store/advanced-tab/advanced-tab.ts new file mode 100644 index 0000000000..bcc0b85f15 --- /dev/null +++ b/src/store/advanced-tab/advanced-tab.ts @@ -0,0 +1,246 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { dialogActions } from '~/store/dialog/dialog-actions'; +import { RootState } from '~/store/store'; +import { Dispatch } from 'redux'; +import { ResourceKind, extractUuidKind } from '~/models/resource'; +import { getResource } from '~/store/resources/resources'; +import { GroupContentsResourcePrefix } from '~/services/groups-service/groups-service'; +import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions'; +import { ContainerRequestResource } from '~/models/container-request'; +import { CollectionResource } from '~/models/collection'; +import { ProjectResource } from '~/models/project'; +import { ServiceRepository } from '~/services/services'; +import { FilterBuilder } from '~/services/api/filter-builder'; + +export const ADVANCED_TAB_DIALOG = 'advancedTabDialog'; + +export interface AdvancedTabDialogData { + apiResponse: any; + metadata: any; + pythonHeader: string; + pythonExample: string; + cliGetHeader: string; + cliGetExample: string; + cliUpdateHeader: string; + cliUpdateExample: string; + curlHeader: string; + curlExample: string; +} + +enum CollectionData { + COLLECTION = 'collection', + STORAGE_CLASSES_CONFIRMED = 'storage_classes_confirmed' +} + +enum ProcessData { + CONTAINER_REQUEST = 'container_request', + OUTPUT_NAME = 'output_name' +} + +enum ProjectData { + GROUP = 'group', + DELETE_AT = 'delete_at' +} + +export const openAdvancedTabDialog = (uuid: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const { resources } = getState(); + const kind = extractUuidKind(uuid); + const data = getResource(uuid)(resources); + const metadata = await services.linkService.list({ + filters: new FilterBuilder() + .addEqual('headUuid', uuid) + .getFilters() + }); + if (data) { + if (kind === ResourceKind.COLLECTION) { + const dataCollection: AdvancedTabDialogData = { + apiResponse: collectionApiResponse(data), + metadata, + pythonHeader: pythonHeader(CollectionData.COLLECTION), + pythonExample: pythonExample(data.uuid, GroupContentsResourcePrefix.COLLECTION), + cliGetHeader: cliGetHeader(CollectionData.COLLECTION), + cliGetExample: cliGetExample(data.uuid, GroupContentsResourcePrefix.COLLECTION), + cliUpdateHeader: cliUpdateHeader(CollectionData.COLLECTION, CollectionData.STORAGE_CLASSES_CONFIRMED), + cliUpdateExample: cliUpdateExample(data.uuid, CollectionData.COLLECTION, data.storageClassesConfirmed, CollectionData.STORAGE_CLASSES_CONFIRMED), + curlHeader: curlHeader(CollectionData.COLLECTION, CollectionData.STORAGE_CLASSES_CONFIRMED), + curlExample: curlExample(data.uuid, GroupContentsResourcePrefix.COLLECTION, data.storageClassesConfirmed, CollectionData.COLLECTION, CollectionData.STORAGE_CLASSES_CONFIRMED) + }; + dispatch(dialogActions.OPEN_DIALOG({ id: ADVANCED_TAB_DIALOG, data: dataCollection })); + } else if (kind === ResourceKind.PROCESS) { + const dataProcess: AdvancedTabDialogData = { + apiResponse: containerRequestApiResponse(data), + metadata, + pythonHeader: pythonHeader(ProcessData.CONTAINER_REQUEST), + pythonExample: pythonExample(data.uuid, GroupContentsResourcePrefix.PROCESS), + cliGetHeader: cliGetHeader(ProcessData.CONTAINER_REQUEST), + cliGetExample: cliGetExample(data.uuid, GroupContentsResourcePrefix.PROCESS), + cliUpdateHeader: cliUpdateHeader(ProcessData.CONTAINER_REQUEST, ProcessData.OUTPUT_NAME), + cliUpdateExample: cliUpdateExample(data.uuid, ProcessData.CONTAINER_REQUEST, data.outputName, ProcessData.OUTPUT_NAME), + curlHeader: curlHeader(ProcessData.CONTAINER_REQUEST, ProcessData.OUTPUT_NAME), + curlExample: curlExample(data.uuid, GroupContentsResourcePrefix.PROCESS, data.outputName, ProcessData.CONTAINER_REQUEST, ProcessData.OUTPUT_NAME) + }; + dispatch(dialogActions.OPEN_DIALOG({ id: ADVANCED_TAB_DIALOG, data: dataProcess })); + } else if (kind === ResourceKind.PROJECT) { + const dataProject: AdvancedTabDialogData = { + apiResponse: groupRequestApiResponse(data), + metadata, + pythonHeader: pythonHeader(ProjectData.GROUP), + pythonExample: pythonExample(data.uuid, GroupContentsResourcePrefix.PROJECT), + cliGetHeader: cliGetHeader(ProjectData.GROUP), + cliGetExample: cliGetExample(data.uuid, GroupContentsResourcePrefix.PROJECT), + cliUpdateHeader: cliUpdateHeader(ProjectData.GROUP, ProjectData.DELETE_AT), + cliUpdateExample: cliUpdateExample(data.uuid, ProjectData.GROUP, data.deleteAt, ProjectData.DELETE_AT), + curlHeader: curlHeader(ProjectData.GROUP, ProjectData.DELETE_AT), + curlExample: curlExample(data.uuid, GroupContentsResourcePrefix.PROJECT, data.deleteAt, ProjectData.GROUP, ProjectData.DELETE_AT) + }; + dispatch(dialogActions.OPEN_DIALOG({ id: ADVANCED_TAB_DIALOG, data: dataProject })); + } + } else { + dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Could not open advanced tab for this resource.", hideDuration: 2000, kind: SnackbarKind.ERROR })); + } + }; + +const pythonHeader = (resourceKind: string) => + `An example python command to get a ${resourceKind} using its uuid:`; + +const pythonExample = (uuid: string, resourcePrefix: string) => { + const pythonExample = `import arvados + + x = arvados.api().${resourcePrefix}().get(uuid='${uuid}').execute()`; + + return pythonExample; +}; + +const cliGetHeader = (resourceKind: string) => + `An example arv command to get a ${resourceKind} using its uuid:`; + +const cliGetExample = (uuid: string, resourcePrefix: string) => { + const cliGetExample = `arv ${resourcePrefix} get \\ + --uuid ${uuid}`; + + return cliGetExample; +}; + +const cliUpdateHeader = (resourceKind: string, resourceName: string) => + `An example arv command to update the "${resourceName}" attribute for the current ${resourceKind}:`; + +const cliUpdateExample = (uuid: string, resourceKind: string, resource: string | string[], resourceName: string) => { + const CLIUpdateCollectionExample = `arv ${resourceKind} update \\ + --uuid ${uuid} \\ + --${resourceKind} '{"${resourceName}":${resource}}'`; + + return CLIUpdateCollectionExample; +}; + +const curlHeader = (resourceKind: string, resource: string) => + `An example curl command to update the "${resource}" attribute for the current ${resourceKind}:`; + +const curlExample = (uuid: string, resourcePrefix: string, resource: string | string[], resourceKind: string, resourceName: string) => { + const curlExample = `curl -X PUT \\ + -H "Authorization: OAuth2 $ARVADOS_API_TOKEN" \\ + --data-urlencode ${resourceKind}@/dev/stdin \\ + https://$ARVADOS_API_HOST/arvados/v1/${resourcePrefix}/${uuid} \\ + < + JSON.stringify(item) || 'null'; + +const stringifyObject = (item: any) => + JSON.stringify(item, null, 2) || 'null'; + +const containerRequestApiResponse = (apiResponse: ContainerRequestResource) => { + const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, state, requestingContainerUuid, containerUuid, + containerCountMax, mounts, runtimeConstraints, containerImage, environment, cwd, command, outputPath, priority, expiresAt, filters, containerCount, + useExisting, schedulingParameters, outputUuid, logUuid, outputName, outputTtl } = apiResponse; + const response = `"uuid": "${uuid}", +"owner_uuid": "${ownerUuid}", +"created_at": "${createdAt}", +"modified_at": ${stringify(modifiedAt)}, +"modified_by_client_uuid": ${stringify(modifiedByClientUuid)}, +"modified_by_user_uuid": ${stringify(modifiedByUserUuid)}, +"name": ${stringify(name)}, +"description": ${stringify(description)}, +"properties": ${stringifyObject(properties)}, +"state": ${stringify(state)}, +"requesting_container_uuid": ${stringify(requestingContainerUuid)}, +"container_uuid": ${stringify(containerUuid)}, +"container_count_max": ${stringify(containerCountMax)}, +"mounts": ${stringifyObject(mounts)}, +"runtime_constraints": ${stringifyObject(runtimeConstraints)}, +"container_image": "${stringify(containerImage)}", +"environment": ${stringifyObject(environment)}, +"cwd": ${stringify(cwd)}, +"command": ${stringifyObject(command)}, +"output_path": ${stringify(outputPath)}, +"priority": ${stringify(priority)}, +"expires_at": ${stringify(expiresAt)}, +"filters": ${stringify(filters)}, +"container_count": ${stringify(containerCount)}, +"use_existing": ${stringify(useExisting)}, +"scheduling_parameters": ${stringifyObject(schedulingParameters)}, +"output_uuid": ${stringify(outputUuid)}, +"log_uuid": ${stringify(logUuid)}, +"output_name": ${stringify(outputName)}, +"output_ttl": ${stringify(outputTtl)}`; + + return response; +}; + +const collectionApiResponse = (apiResponse: CollectionResource) => { + const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, portableDataHash, replicationDesired, + replicationConfirmedAt, replicationConfirmed, manifestText, deleteAt, fileNames, trashAt, isTrashed, storageClassesDesired, + storageClassesConfirmed, storageClassesConfirmedAt } = 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)}, +"portable_data_hash": ${stringify(portableDataHash)}, +"replication_desired": ${stringify(replicationDesired)}, +"replication_confirmed_at": ${stringify(replicationConfirmedAt)}, +"replication_confirmed": ${stringify(replicationConfirmed)}, +"manifest_text": ${stringify(manifestText)}, +"name": ${stringify(name)}, +"description": ${stringify(description)}, +"properties": ${stringifyObject(properties)}, +"delete_at": ${stringify(deleteAt)}, +"file_names": ${stringify(fileNames)}, +"trash_at": ${stringify(trashAt)}, +"is_trashed": ${stringify(isTrashed)}, +"storage_classes_desired": ${JSON.stringify(storageClassesDesired, null, 2)}, +"storage_classes_confirmed": ${JSON.stringify(storageClassesConfirmed, null, 2)}, +"storage_classes_confirmed_at": ${stringify(storageClassesConfirmedAt)}`; + + return response; +}; + +const groupRequestApiResponse = (apiResponse: ProjectResource) => { + const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, groupClass, trashAt, isTrashed, deleteAt, properties } = 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)}, +"name": ${stringify(name)}, +"description": ${stringify(description)}, +"group_class": ${stringify(groupClass)}, +"trash_at": ${stringify(trashAt)}, +"is_trashed": ${stringify(isTrashed)}, +"delete_at": ${stringify(deleteAt)}, +"properties": ${stringifyObject(properties)}`; + + return response; +}; \ No newline at end of file diff --git a/src/views-components/advanced-tab-dialog/advanced-tab-dialog.tsx b/src/views-components/advanced-tab-dialog/advanced-tab-dialog.tsx new file mode 100644 index 0000000000..3b3ca6d434 --- /dev/null +++ b/src/views-components/advanced-tab-dialog/advanced-tab-dialog.tsx @@ -0,0 +1,111 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import * as React from "react"; +import { Dialog, DialogActions, Button, StyleRulesCallback, WithStyles, withStyles, DialogTitle, DialogContent, Tabs, Tab, DialogContentText } from '@material-ui/core'; +import { WithDialogProps } from '~/store/dialog/with-dialog'; +import { withDialog } from "~/store/dialog/with-dialog"; +import { compose } from 'redux'; +import { ADVANCED_TAB_DIALOG } from "~/store/advanced-tab/advanced-tab"; +import { DefaultCodeSnippet } from "~/components/default-code-snippet/default-code-snippet"; +import { MetadataTab } from '~/views-components/advanced-tab-dialog/metadataTab'; + +type CssRules = 'content' | 'codeSnippet' | 'spacing'; + +const styles: StyleRulesCallback = theme => ({ + content: { + paddingTop: theme.spacing.unit * 3, + minHeight: '400px', + minWidth: '1232px' + }, + codeSnippet: { + borderRadius: theme.spacing.unit * 0.5, + border: '1px solid', + borderColor: theme.palette.grey["400"], + maxHeight: '400px' + }, + spacing: { + paddingBottom: theme.spacing.unit * 2 + }, +}); + +export const AdvancedTabDialog = compose( + withDialog(ADVANCED_TAB_DIALOG), + withStyles(styles), +)( + class extends React.Component & WithStyles>{ + state = { + value: 0, + }; + + componentDidMount() { + this.setState({ value: 0 }); + } + + handleChange = (event: React.MouseEvent, value: number) => { + this.setState({ value }); + } + render() { + const { classes, open, closeDialog } = this.props; + const { value } = this.state; + const { + apiResponse, + metadata, + pythonHeader, + pythonExample, + cliGetHeader, + cliGetExample, + cliUpdateHeader, + cliUpdateExample, + curlHeader, + curlExample + } = this.props.data; + return this.setState({ value: 0 })} > + Advanced + + + + + + + + + {value === 0 &&
{dialogContentExample(apiResponse, classes)}
} + {value === 1 &&
{metadata.items.length > 0 ? : dialogContentHeader('(No metadata links found)')}
} + {value === 2 && dialogContent(pythonHeader, pythonExample, classes)} + {value === 3 &&
+ {dialogContent(cliGetHeader, cliGetExample, classes)} + {dialogContent(cliUpdateHeader, cliUpdateExample, classes)} +
} + {value === 4 && dialogContent(curlHeader, curlExample, classes)} +
+ + + +
; + } + } +); + +const dialogContent = (header: string, example: string, classes: any) => +
+ {dialogContentHeader(header)} + {dialogContentExample(example, classes)} +
; + +const dialogContentHeader = (header: string) => + + {header} + ; + +const dialogContentExample = (example: string, classes: any) => + ; \ No newline at end of file diff --git a/src/views-components/advanced-tab-dialog/metadataTab.tsx b/src/views-components/advanced-tab-dialog/metadataTab.tsx new file mode 100644 index 0000000000..340149a3e9 --- /dev/null +++ b/src/views-components/advanced-tab-dialog/metadataTab.tsx @@ -0,0 +1,57 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import * as React from "react"; +import { Table, TableHead, TableCell, TableRow, TableBody, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core'; +import { navigateTo } from "~/store/navigation/navigation-action"; + +type CssRules = 'cell'; + +const styles: StyleRulesCallback = theme => ({ + cell: { + paddingRight: theme.spacing.unit * 2 + } +}); + +interface MetadataTable { + uuid: string; + linkClass: string; + name: string; + tailUuid: string; + headUuid: string; + properties: any; +} + +interface MetadataProps { + items: MetadataTable[]; +} + +export const MetadataTab = withStyles(styles)((props: MetadataProps & WithStyles) => + + + + uuid + link_class + name + tail + head + properties + + + + {props.items.map((it, index) => { + return ( + + {it.uuid} + {it.linkClass} + {it.name} + {it.tailUuid} + {it.headUuid} + {JSON.stringify(it.properties, null, 2)} + + ); + })} + +
+); \ No newline at end of file diff --git a/src/views-components/context-menu/action-sets/collection-action-set.ts b/src/views-components/context-menu/action-sets/collection-action-set.ts index cff30fb166..121fe17ab5 100644 --- a/src/views-components/context-menu/action-sets/collection-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-action-set.ts @@ -13,14 +13,13 @@ import { openCollectionCopyDialog } from "~/store/collections/collection-copy-ac import { ToggleTrashAction } from "~/views-components/context-menu/actions/trash-action"; import { toggleCollectionTrashed } from "~/store/trash/trash-actions"; import { detailsPanelActions } from '~/store/details-panel/details-panel-action'; +import { openAdvancedTabDialog } from "~/store/advanced-tab/advanced-tab"; export const collectionActionSet: ContextMenuActionSet = [[ { icon: RenameIcon, name: "Edit collection", - execute: (dispatch, resource) => { - dispatch(openCollectionUpdateDialog(resource)); - } + execute: (dispatch, resource) => dispatch(openCollectionUpdateDialog(resource)) }, { icon: ShareIcon, @@ -44,16 +43,13 @@ export const collectionActionSet: ContextMenuActionSet = [[ }, { component: ToggleTrashAction, - execute: (dispatch, resource) => { - dispatch(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!)); - } + execute: (dispatch, resource) => dispatch(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!)) }, { icon: CopyIcon, name: "Copy to project", - execute: (dispatch, resource) => { - dispatch(openCollectionCopyDialog(resource)); - } + execute: (dispatch, resource) => dispatch(openCollectionCopyDialog(resource)) + }, { icon: DetailsIcon, @@ -70,9 +66,7 @@ export const collectionActionSet: ContextMenuActionSet = [[ { icon: AdvancedIcon, name: "Advanced", - execute: (dispatch, resource) => { - // add code - } + execute: (dispatch, resource) => dispatch(openAdvancedTabDialog(resource.uuid)) }, { icon: RemoveIcon, diff --git a/src/views-components/context-menu/action-sets/collection-files-action-set.ts b/src/views-components/context-menu/action-sets/collection-files-action-set.ts index 5c4dab30e5..c86f1d7d61 100644 --- a/src/views-components/context-menu/action-sets/collection-files-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-files-action-set.ts @@ -2,33 +2,23 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { ContextMenuActionSet } from "../context-menu-action-set"; +import { ContextMenuActionSet } from "~/views-components/context-menu/context-menu-action-set"; import { collectionPanelFilesAction, openMultipleFilesRemoveDialog } from "~/store/collection-panel/collection-panel-files/collection-panel-files-actions"; import { openCollectionPartialCopyDialog } from '~/store/collections/collection-partial-copy-actions'; export const collectionFilesActionSet: ContextMenuActionSet = [[{ name: "Select all", - execute: (dispatch) => { - dispatch(collectionPanelFilesAction.SELECT_ALL_COLLECTION_FILES()); - } + execute: dispatch => dispatch(collectionPanelFilesAction.SELECT_ALL_COLLECTION_FILES()) }, { name: "Unselect all", - execute: (dispatch) => { - dispatch(collectionPanelFilesAction.UNSELECT_ALL_COLLECTION_FILES()); - } + execute: dispatch => dispatch(collectionPanelFilesAction.UNSELECT_ALL_COLLECTION_FILES()) }, { name: "Remove selected", - execute: (dispatch) => { - dispatch(openMultipleFilesRemoveDialog()); - } + execute: dispatch => dispatch(openMultipleFilesRemoveDialog()) }, { name: "Download selected", - execute: (dispatch, resource) => { - return; - } + execute: () => { return; } }, { name: "Create a new collection with selected", - execute: (dispatch) => { - dispatch(openCollectionPartialCopyDialog()); - } + execute: dispatch => dispatch(openCollectionPartialCopyDialog()) }]]; diff --git a/src/views-components/context-menu/action-sets/collection-files-item-action-set.ts b/src/views-components/context-menu/action-sets/collection-files-item-action-set.ts index b556489173..2baa524401 100644 --- a/src/views-components/context-menu/action-sets/collection-files-item-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-files-item-action-set.ts @@ -11,16 +11,12 @@ import { openFileRemoveDialog, openRenameFileDialog } from '~/store/collection-p export const collectionFilesItemActionSet: ContextMenuActionSet = [[{ name: "Rename", icon: RenameIcon, - execute: (dispatch, resource) => { - dispatch(openRenameFileDialog({ name: resource.name, id: resource.uuid })); - } + execute: (dispatch, resource) => dispatch(openRenameFileDialog({ name: resource.name, id: resource.uuid })) }, { component: DownloadCollectionFileAction, execute: () => { return; } }, { name: "Remove", icon: RemoveIcon, - execute: (dispatch, resource) => { - dispatch(openFileRemoveDialog(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(openFileRemoveDialog(resource.uuid)) }]]; diff --git a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts index 8665bc1b6b..c54d40e4cf 100644 --- a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts @@ -18,9 +18,7 @@ export const collectionResourceActionSet: ContextMenuActionSet = [[ { icon: RenameIcon, name: "Edit collection", - execute: (dispatch, resource) => { - dispatch(openCollectionUpdateDialog(resource)); - } + execute: (dispatch, resource) => dispatch(openCollectionUpdateDialog(resource)) }, { icon: ShareIcon, @@ -44,16 +42,12 @@ export const collectionResourceActionSet: ContextMenuActionSet = [[ }, { component: ToggleTrashAction, - execute: (dispatch, resource) => { - dispatch(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!)); - } + execute: (dispatch, resource) => dispatch(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!)) }, { icon: CopyIcon, name: "Copy to project", - execute: (dispatch, resource) => { - dispatch(openCollectionCopyDialog(resource)); - }, + execute: (dispatch, resource) => dispatch(openCollectionCopyDialog(resource)) }, { icon: DetailsIcon, diff --git a/src/views-components/context-menu/action-sets/process-action-set.ts b/src/views-components/context-menu/action-sets/process-action-set.ts index 3248873186..9447567d1f 100644 --- a/src/views-components/context-menu/action-sets/process-action-set.ts +++ b/src/views-components/context-menu/action-sets/process-action-set.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { ContextMenuActionSet } from "../context-menu-action-set"; -import { ToggleFavoriteAction } from "../actions/favorite-action"; +import { ContextMenuActionSet } from "~/views-components/context-menu/context-menu-action-set"; +import { ToggleFavoriteAction } from "~/views-components/context-menu/actions/favorite-action"; import { toggleFavorite } from "~/store/favorites/favorites-actions"; import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, ProvenanceGraphIcon, @@ -14,8 +14,9 @@ import { navigateToProcessLogs } from '~/store/navigation/navigation-action'; import { openMoveProcessDialog } from '~/store/processes/process-move-actions'; import { openProcessUpdateDialog } from "~/store/processes/process-update-actions"; import { openCopyProcessDialog } from '~/store/processes/process-copy-actions'; -import { openProcessCommandDialog } from '../../../store/processes/process-command-actions'; +import { openProcessCommandDialog } from '~/store/processes/process-command-actions'; import { detailsPanelActions } from '~/store/details-panel/details-panel-action'; +import { openAdvancedTabDialog } from "~/store/advanced-tab/advanced-tab"; export const processActionSet: ContextMenuActionSet = [[ { @@ -72,9 +73,7 @@ export const processActionSet: ContextMenuActionSet = [[ { icon: CommandIcon, name: "Command", - execute: (dispatch, resource) => { - dispatch(openProcessCommandDialog(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(openProcessCommandDialog(resource.uuid)) }, { icon: DetailsIcon, @@ -84,9 +83,7 @@ export const processActionSet: ContextMenuActionSet = [[ { icon: LogIcon, name: "Log", - execute: (dispatch, resource) => { - dispatch(navigateToProcessLogs(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(navigateToProcessLogs(resource.uuid)) }, { icon: ProvenanceGraphIcon, @@ -98,9 +95,7 @@ export const processActionSet: ContextMenuActionSet = [[ { icon: AdvancedIcon, name: "Advanced", - execute: (dispatch, resource) => { - // add code - } + execute: (dispatch, resource) => dispatch(openAdvancedTabDialog(resource.uuid)) }, { icon: RemoveIcon, diff --git a/src/views-components/context-menu/action-sets/project-action-set.ts b/src/views-components/context-menu/action-sets/project-action-set.ts index 85848a2d6b..cc57a3f747 100644 --- a/src/views-components/context-menu/action-sets/project-action-set.ts +++ b/src/views-components/context-menu/action-sets/project-action-set.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0 import { ContextMenuActionSet } from "../context-menu-action-set"; -import { NewProjectIcon, RenameIcon, CopyIcon, MoveToIcon, DetailsIcon } from '~/components/icon/icon'; +import { NewProjectIcon, RenameIcon, CopyIcon, MoveToIcon, DetailsIcon, AdvancedIcon } from '~/components/icon/icon'; import { ToggleFavoriteAction } from "../actions/favorite-action"; import { toggleFavorite } from "~/store/favorites/favorites-actions"; import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action"; @@ -13,21 +13,18 @@ import { openProjectUpdateDialog } from '~/store/projects/project-update-actions import { ToggleTrashAction } from "~/views-components/context-menu/actions/trash-action"; import { toggleProjectTrashed } from "~/store/trash/trash-actions"; import { detailsPanelActions } from '~/store/details-panel/details-panel-action'; +import { openAdvancedTabDialog } from "~/store/advanced-tab/advanced-tab"; export const projectActionSet: ContextMenuActionSet = [[ { icon: NewProjectIcon, name: "New project", - execute: (dispatch, resource) => { - dispatch(openProjectCreateDialog(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(openProjectCreateDialog(resource.uuid)) }, { icon: RenameIcon, name: "Edit project", - execute: (dispatch, resource) => { - dispatch(openProjectUpdateDialog(resource)); - } + execute: (dispatch, resource) => dispatch(openProjectUpdateDialog(resource)) }, { component: ToggleFavoriteAction, @@ -39,9 +36,7 @@ export const projectActionSet: ContextMenuActionSet = [[ }, { component: ToggleTrashAction, - execute: (dispatch, resource) => { - dispatch(toggleProjectTrashed(resource.uuid, resource.ownerUuid, resource.isTrashed!!)); - } + execute: (dispatch, resource) => dispatch(toggleProjectTrashed(resource.uuid, resource.ownerUuid, resource.isTrashed!!)) }, { icon: MoveToIcon, @@ -59,5 +54,10 @@ export const projectActionSet: ContextMenuActionSet = [[ icon: DetailsIcon, name: "View details", execute: dispatch => dispatch(detailsPanelActions.TOGGLE_DETAILS_PANEL()) - } + }, + { + icon: AdvancedIcon, + name: "Advanced", + execute: (dispatch, resource) => dispatch(openAdvancedTabDialog(resource.uuid)) + }, ]]; diff --git a/src/views-components/context-menu/action-sets/root-project-action-set.ts b/src/views-components/context-menu/action-sets/root-project-action-set.ts index 386c5162f3..d80fc9dab4 100644 --- a/src/views-components/context-menu/action-sets/root-project-action-set.ts +++ b/src/views-components/context-menu/action-sets/root-project-action-set.ts @@ -11,15 +11,11 @@ export const rootProjectActionSet: ContextMenuActionSet = [[ { icon: NewProjectIcon, name: "New project", - execute: (dispatch, resource) => { - dispatch(openProjectCreateDialog(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(openProjectCreateDialog(resource.uuid)) }, { icon: CollectionIcon, name: "New Collection", - execute: (dispatch, resource) => { - dispatch(openCollectionCreateDialog(resource.uuid)); - } + execute: (dispatch, resource) => dispatch(openCollectionCreateDialog(resource.uuid)) } ]]; diff --git a/src/views-components/context-menu/action-sets/trash-action-set.ts b/src/views-components/context-menu/action-sets/trash-action-set.ts index fafd5feb22..f81a9952a9 100644 --- a/src/views-components/context-menu/action-sets/trash-action-set.ts +++ b/src/views-components/context-menu/action-sets/trash-action-set.ts @@ -9,8 +9,6 @@ import { toggleTrashed } from "~/store/trash/trash-actions"; export const trashActionSet: ContextMenuActionSet = [[ { component: ToggleTrashAction, - execute: (dispatch, resource) => { - dispatch(toggleTrashed(resource.kind, resource.uuid, resource.ownerUuid, resource.isTrashed!!)); - } + execute: (dispatch, resource) => dispatch(toggleTrashed(resource.kind, resource.uuid, resource.ownerUuid, resource.isTrashed!!)) }, ]]; diff --git a/src/views-components/context-menu/action-sets/trashed-collection-action-set.ts b/src/views-components/context-menu/action-sets/trashed-collection-action-set.ts index c42da1e6f8..e11228b49e 100644 --- a/src/views-components/context-menu/action-sets/trashed-collection-action-set.ts +++ b/src/views-components/context-menu/action-sets/trashed-collection-action-set.ts @@ -5,14 +5,14 @@ import { ContextMenuActionSet } from "../context-menu-action-set"; import { DetailsIcon, ProvenanceGraphIcon, AdvancedIcon, RestoreFromTrashIcon } from '~/components/icon/icon'; import { toggleCollectionTrashed } from "~/store/trash/trash-actions"; +import { detailsPanelActions } from "~/store/details-panel/details-panel-action"; +import { openAdvancedTabDialog } from "~/store/advanced-tab/advanced-tab"; export const trashedCollectionActionSet: ContextMenuActionSet = [[ { icon: DetailsIcon, name: "View details", - execute: (dispatch, resource) => { - // add code - } + execute: dispatch => dispatch(detailsPanelActions.TOGGLE_DETAILS_PANEL()) }, { icon: ProvenanceGraphIcon, @@ -24,15 +24,11 @@ export const trashedCollectionActionSet: ContextMenuActionSet = [[ { icon: AdvancedIcon, name: "Advanced", - execute: (dispatch, resource) => { - // add code - } + execute: (dispatch, resource) => dispatch(openAdvancedTabDialog(resource.uuid)) }, { icon: RestoreFromTrashIcon, name: "Restore", - execute: (dispatch, resource) => { - dispatch(toggleCollectionTrashed(resource.uuid, true)); - } + execute: (dispatch, resource) => dispatch(toggleCollectionTrashed(resource.uuid, true)) }, ]]; diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index 788c96ae6b..1e6538485e 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -42,12 +42,7 @@ import { RunProcessPanel } from '~/views/run-process-panel/run-process-panel'; import SplitterLayout from 'react-splitter-layout'; import { WorkflowPanel } from '~/views/workflow-panel/workflow-panel'; import { SearchResultsPanel } from '~/views/search-results-panel/search-results-panel'; -import { HomeTreePicker } from '~/views-components/projects-tree-picker/home-tree-picker'; -import { SharedTreePicker } from '~/views-components/projects-tree-picker/shared-tree-picker'; -import { FavoritesTreePicker } from '../../views-components/projects-tree-picker/favorites-tree-picker'; -import { ProjectsTreePicker } from '~/views-components/projects-tree-picker/projects-tree-picker'; -import { Chips } from '~/components/chips/chips'; -import { ChipsInput } from '../../components/chips-input/chips-input'; +import { AdvancedTabDialog } from '~/views-components/advanced-tab-dialog/advanced-tab-dialog'; type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content'; @@ -114,6 +109,7 @@ export const WorkbenchPanel = + diff --git a/src/views/workflow-panel/workflow-description-card.tsx b/src/views/workflow-panel/workflow-description-card.tsx index 70fdb6b3b6..b4b9f20ae4 100644 --- a/src/views/workflow-panel/workflow-description-card.tsx +++ b/src/views/workflow-panel/workflow-description-card.tsx @@ -14,8 +14,7 @@ import { TableHead, TableCell, TableBody, - TableRow, - Divider + TableRow } from '@material-ui/core'; import { ArvadosTheme } from '~/common/custom-theme'; import { WorkflowIcon } from '~/components/icon/icon';