From: Lisa Knox Date: Thu, 7 Sep 2023 14:24:01 +0000 (-0400) Subject: 15768: collection copy dialog mostly works Arvados-DCO-1.1-Signed-off-by: Lisa Knox... X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/44821dc84765936ce99fa2d760ef683281f0a578?hp=2bd3f83db9934198b658b7035a7be65017b754d9 15768: collection copy dialog mostly works Arvados-DCO-1.1-Signed-off-by: Lisa Knox --- diff --git a/src/components/multiselect-toolbar/MultiselectToolbar.tsx b/src/components/multiselect-toolbar/MultiselectToolbar.tsx index 8c36f60f84..2406ef6271 100644 --- a/src/components/multiselect-toolbar/MultiselectToolbar.tsx +++ b/src/components/multiselect-toolbar/MultiselectToolbar.tsx @@ -176,7 +176,7 @@ function selectActionsByKind(currentResourceKinds: Array, filterSet: TMu function mapStateToProps(state: RootState) { const { isVisible, checkedList } = state.multiselect; - // console.log("checkedList", checkedList); //here + // if (Object.keys(state.dialog).length) console.log("latest dialog", state.dialog); //here return { isVisible: isVisible, checkedList: checkedList as TCheckedList, diff --git a/src/store/collections/collection-copy-actions.ts b/src/store/collections/collection-copy-actions.ts index fe204aadfb..a482b9a79c 100644 --- a/src/store/collections/collection-copy-actions.ts +++ b/src/store/collections/collection-copy-actions.ts @@ -16,8 +16,10 @@ import { getResource } from "store/resources/resources"; import { CollectionResource } from "models/collection"; export const COLLECTION_COPY_FORM_NAME = "collectionCopyFormName"; +export const COLLECTION_MULTI_COPY_FORM_NAME = "collectionMultiCopyFormName"; export const openCollectionCopyDialog = (resource: { name: string; uuid: string; isSingle?: boolean }) => (dispatch: Dispatch) => { + //here dispatch(resetPickerProjectTree()); dispatch(initProjectsTreePicker(COLLECTION_COPY_FORM_NAME)); const initialData: CopyFormDialogData = { name: `Copy of: ${resource.name}`, ownerUuid: "", uuid: resource.uuid, isSingle: resource.isSingle }; @@ -25,8 +27,19 @@ export const openCollectionCopyDialog = (resource: { name: string; uuid: string; dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_COPY_FORM_NAME, data: {} })); }; +export const openMultiCollectionCopyDialog = (resource: { name: string; uuid: string; isSingle?: boolean }) => (dispatch: Dispatch) => { + //here + dispatch(resetPickerProjectTree()); + dispatch(initProjectsTreePicker(COLLECTION_MULTI_COPY_FORM_NAME)); + const initialData: CopyFormDialogData = { name: `Copy of: ${resource.name}`, ownerUuid: "", uuid: resource.uuid, isSingle: resource.isSingle }; + dispatch(initialize(COLLECTION_MULTI_COPY_FORM_NAME, initialData)); + dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_MULTI_COPY_FORM_NAME, data: {} })); +}; + export const copyCollection = (resource: CopyFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + console.log("IN COPY COLLECTION", resource); + const formName = resource.isSingle ? COLLECTION_COPY_FORM_NAME : COLLECTION_MULTI_COPY_FORM_NAME; dispatch(startSubmit(COLLECTION_COPY_FORM_NAME)); let collection = getResource(resource.uuid)(getState().resources); try { @@ -41,22 +54,22 @@ export const copyCollection = ownerUuid: resource.ownerUuid, name: resource.name, }); - dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_COPY_FORM_NAME })); + dispatch(dialogActions.CLOSE_DIALOG({ id: formName })); return newCollection; } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_NAME_VIOLATION) { dispatch( - stopSubmit(COLLECTION_COPY_FORM_NAME, { + stopSubmit(formName, { ownerUuid: "A collection with the same name already exists in the target project.", } as FormErrors) ); } else { - dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_COPY_FORM_NAME })); + dispatch(dialogActions.CLOSE_DIALOG({ id: formName })); throw new Error("Could not copy the collection."); } return; } finally { - dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_COPY_FORM_NAME)); + dispatch(progressIndicatorActions.STOP_WORKING(formName)); } }; diff --git a/src/store/context-menu/context-menu-actions.ts b/src/store/context-menu/context-menu-actions.ts index ee973784bb..6fc5d56f51 100644 --- a/src/store/context-menu/context-menu-actions.ts +++ b/src/store/context-menu/context-menu-actions.ts @@ -47,6 +47,7 @@ export type ContextMenuResource = { storageClassesDesired?: string[]; properties?: { [key: string]: string | string[] }; isMulti?: boolean; + isSingle?: boolean; }; export const isKeyboardClick = (event: React.MouseEvent) => event.nativeEvent.detail === 0; diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts index e79df23947..71fdc6aa88 100644 --- a/src/store/workbench/workbench-actions.ts +++ b/src/store/workbench/workbench-actions.ts @@ -432,18 +432,20 @@ export const copyCollection = (data: CopyFormDialogData) => async (dispatch: Dis //if no items in checkedlist && no items passed in, default to normal context menu behavior if (!uuidsToCopy.length) uuidsToCopy.push(data.uuid); - const collectionsToCopy: Resource[] = uuidsToCopy - .map(uuid => getResource(uuid)(getState().resources) as any) + const collectionsToCopy: CollectionCopyResource[] = uuidsToCopy + .map(uuid => getResource(uuid)(getState().resources) as CollectionCopyResource) .filter(resource => resource.kind === ResourceKind.COLLECTION); for (const collection of collectionsToCopy) { - await copySingleCollection(collection as Resource & { name: string }); + await copySingleCollection(collection as CollectionCopyResource); } - async function copySingleCollection(copyToProject: Resource & { name: string }) { + async function copySingleCollection(copyToProject: CollectionCopyResource) { const newName = data.isSingle ? data.name : `Copy of: ${copyToProject.name}`; try { - const collection = await dispatch(collectionCopyActions.copyCollection({ ...copyToProject, name: newName })); + const collection = await dispatch( + collectionCopyActions.copyCollection({ ...copyToProject, name: newName, isSingle: data.isSingle }) + ); if (copyToProject && collection) { await dispatch(reloadProjectMatchingUuid([copyToProject.uuid])); dispatch( @@ -828,6 +830,8 @@ const groupContentsHandlers = unionize(groupContentsHandlersRecord); type GroupContentsHandler = UnionOf; +type CollectionCopyResource = Resource & { name: string; isSingle: boolean }; + type MoveableResource = Resource & { name: string }; type MoveFunc = ( 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 f1250582c1..b63497f20f 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 @@ -20,7 +20,7 @@ import { import { openCollectionUpdateDialog } from "store/collections/collection-update-actions"; import { favoritePanelActions } from "store/favorite-panel/favorite-panel-action"; import { openMoveCollectionDialog } from "store/collections/collection-move-actions"; -import { openCollectionCopyDialog } from "store/collections/collection-copy-actions"; +import { openCollectionCopyDialog, openMultiCollectionCopyDialog } from "store/collections/collection-copy-actions"; import { openWebDavS3InfoDialog } from "store/collections/collection-info-actions"; import { ToggleTrashAction } from "views-components/context-menu/actions/trash-action"; import { toggleCollectionTrashed } from "store/trash/trash-actions"; @@ -66,7 +66,10 @@ const commonActionSet: ContextMenuActionSet = [ icon: CopyIcon, name: "Make a copy", execute: (dispatch, resources) => { - dispatch(openCollectionCopyDialog(resources[0])); + console.log(resources[0]); + //here fix single vs one + if (resources[0].isSingle) dispatch(openCollectionCopyDialog(resources[0])); + else dispatch(openMultiCollectionCopyDialog(resources[0])); }, }, { @@ -126,6 +129,7 @@ export const collectionActionSet: ContextMenuActionSet = [ component: ToggleTrashAction, name: "ToggleTrashAction", execute: (dispatch, resources: ContextMenuResource[]) => { + //here fix multi? resources.forEach(resource => dispatch(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!))); }, }, diff --git a/src/views-components/dialog-copy/dialog-copy.tsx b/src/views-components/dialog-copy/dialog-copy.tsx index aa6b6784d7..e7e7836e87 100644 --- a/src/views-components/dialog-copy/dialog-copy.tsx +++ b/src/views-components/dialog-copy/dialog-copy.tsx @@ -15,14 +15,18 @@ import { PickerIdProp } from "store/tree-picker/picker-id"; type CopyFormDialogProps = WithDialogProps & InjectedFormProps; -export const DialogCopy = (props: CopyFormDialogProps & PickerIdProp) => ( - -); +export const DialogCopy = (props: CopyFormDialogProps & PickerIdProp) => { + console.log("single dialog copy", props); + + return ( + + ); +}; const CopyDialogFields = memoize((pickerId: string) => () => ( <> @@ -40,3 +44,25 @@ const CopyDialogFields = memoize((pickerId: string) => () => ( /> )); + +export const DialogMultiCopy = (props: CopyFormDialogProps & PickerIdProp) => { + console.log("multi dialog copy", props); + + return ( + + ); +}; + +const CopyMultiDialogFields = memoize((pickerId: string) => () => ( + +)); diff --git a/src/views-components/dialog-forms/copy-collection-dialog.ts b/src/views-components/dialog-forms/copy-collection-dialog.ts index eb1f26153f..5d0ff29fc3 100644 --- a/src/views-components/dialog-forms/copy-collection-dialog.ts +++ b/src/views-components/dialog-forms/copy-collection-dialog.ts @@ -5,8 +5,8 @@ import { compose } from "redux"; import { withDialog } from "store/dialog/with-dialog"; import { reduxForm } from "redux-form"; -import { COLLECTION_COPY_FORM_NAME } from "store/collections/collection-copy-actions"; -import { DialogCopy } from "views-components/dialog-copy/dialog-copy"; +import { COLLECTION_COPY_FORM_NAME, COLLECTION_MULTI_COPY_FORM_NAME } from "store/collections/collection-copy-actions"; +import { DialogCopy, DialogMultiCopy } from "views-components/dialog-copy/dialog-copy"; import { copyCollection } from "store/workbench/workbench-actions"; import { CopyFormDialogData } from "store/copy-dialog/copy-dialog"; import { pickerId } from "store/tree-picker/picker-id"; @@ -17,8 +17,22 @@ export const CopyCollectionDialog = compose( form: COLLECTION_COPY_FORM_NAME, touchOnChange: true, onSubmit: (data, dispatch) => { + console.log("DATA main", data); dispatch(copyCollection(data)); }, }), pickerId(COLLECTION_COPY_FORM_NAME) )(DialogCopy); + +export const CopyMultiCollectionDialog = compose( + withDialog(COLLECTION_MULTI_COPY_FORM_NAME), + reduxForm({ + form: COLLECTION_MULTI_COPY_FORM_NAME, + touchOnChange: true, + onSubmit: (data, dispatch) => { + console.log("DATA main", data); + dispatch(copyCollection(data)); + }, + }), + pickerId(COLLECTION_MULTI_COPY_FORM_NAME) +)(DialogMultiCopy); diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index 445e86de66..f7b8e8337b 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -2,108 +2,108 @@ // // SPDX-License-Identifier: AGPL-3.0 -import React from 'react'; -import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles'; -import { Route, Switch } from 'react-router'; -import { ProjectPanel } from 'views/project-panel/project-panel'; -import { DetailsPanel } from 'views-components/details-panel/details-panel'; -import { ArvadosTheme } from 'common/custom-theme'; -import { ContextMenu } from 'views-components/context-menu/context-menu'; -import { FavoritePanel } from '../favorite-panel/favorite-panel'; -import { TokenDialog } from 'views-components/token-dialog/token-dialog'; -import { RichTextEditorDialog } from 'views-components/rich-text-editor-dialog/rich-text-editor-dialog'; -import { Snackbar } from 'views-components/snackbar/snackbar'; -import { CollectionPanel } from '../collection-panel/collection-panel'; -import { RenameFileDialog } from 'views-components/rename-file-dialog/rename-file-dialog'; -import { FileRemoveDialog } from 'views-components/file-remove-dialog/file-remove-dialog'; -import { MultipleFilesRemoveDialog } from 'views-components/file-remove-dialog/multiple-files-remove-dialog'; -import { Routes } from 'routes/routes'; -import { SidePanel } from 'views-components/side-panel/side-panel'; -import { ProcessPanel } from 'views/process-panel/process-panel'; -import { ChangeWorkflowDialog } from 'views-components/run-process-dialog/change-workflow-dialog'; -import { CreateProjectDialog } from 'views-components/dialog-forms/create-project-dialog'; -import { CreateCollectionDialog } from 'views-components/dialog-forms/create-collection-dialog'; -import { CopyCollectionDialog } from 'views-components/dialog-forms/copy-collection-dialog'; -import { CopyProcessDialog } from 'views-components/dialog-forms/copy-process-dialog'; -import { UpdateCollectionDialog } from 'views-components/dialog-forms/update-collection-dialog'; -import { UpdateProcessDialog } from 'views-components/dialog-forms/update-process-dialog'; -import { UpdateProjectDialog } from 'views-components/dialog-forms/update-project-dialog'; -import { MoveProcessDialog } from 'views-components/dialog-forms/move-process-dialog'; -import { MoveProjectDialog } from 'views-components/dialog-forms/move-project-dialog'; -import { MoveCollectionDialog } from 'views-components/dialog-forms/move-collection-dialog'; -import { FilesUploadCollectionDialog } from 'views-components/dialog-forms/files-upload-collection-dialog'; -import { PartialCopyCollectionDialog } from 'views-components/dialog-forms/partial-copy-collection-dialog'; -import { RemoveProcessDialog } from 'views-components/process-remove-dialog/process-remove-dialog'; -import { MainContentBar } from 'views-components/main-content-bar/main-content-bar'; -import { Grid } from '@material-ui/core'; -import { TrashPanel } from 'views/trash-panel/trash-panel'; -import { SharedWithMePanel } from 'views/shared-with-me-panel/shared-with-me-panel'; -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 { RegisteredWorkflowPanel } from 'views/workflow-panel/registered-workflow-panel'; -import { SearchResultsPanel } from 'views/search-results-panel/search-results-panel'; -import { SshKeyPanel } from 'views/ssh-key-panel/ssh-key-panel'; -import { SshKeyAdminPanel } from 'views/ssh-key-panel/ssh-key-admin-panel'; -import { SiteManagerPanel } from 'views/site-manager-panel/site-manager-panel'; -import { UserProfilePanel } from 'views/user-profile-panel/user-profile-panel'; -import { SharingDialog } from 'views-components/sharing-dialog/sharing-dialog'; -import { NotFoundDialog } from 'views-components/not-found-dialog/not-found-dialog'; -import { AdvancedTabDialog } from 'views-components/advanced-tab-dialog/advanced-tab-dialog'; -import { ProcessInputDialog } from 'views-components/process-input-dialog/process-input-dialog'; -import { VirtualMachineUserPanel } from 'views/virtual-machine-panel/virtual-machine-user-panel'; -import { VirtualMachineAdminPanel } from 'views/virtual-machine-panel/virtual-machine-admin-panel'; -import { RepositoriesPanel } from 'views/repositories-panel/repositories-panel'; -import { KeepServicePanel } from 'views/keep-service-panel/keep-service-panel'; -import { ApiClientAuthorizationPanel } from 'views/api-client-authorization-panel/api-client-authorization-panel'; -import { LinkPanel } from 'views/link-panel/link-panel'; -import { RepositoriesSampleGitDialog } from 'views-components/repositories-sample-git-dialog/repositories-sample-git-dialog'; -import { RepositoryAttributesDialog } from 'views-components/repository-attributes-dialog/repository-attributes-dialog'; -import { CreateRepositoryDialog } from 'views-components/dialog-forms/create-repository-dialog'; -import { RemoveRepositoryDialog } from 'views-components/repository-remove-dialog/repository-remove-dialog'; -import { CreateSshKeyDialog } from 'views-components/dialog-forms/create-ssh-key-dialog'; -import { PublicKeyDialog } from 'views-components/ssh-keys-dialog/public-key-dialog'; -import { RemoveApiClientAuthorizationDialog } from 'views-components/api-client-authorizations-dialog/remove-dialog'; -import { RemoveKeepServiceDialog } from 'views-components/keep-services-dialog/remove-dialog'; -import { RemoveLinkDialog } from 'views-components/links-dialog/remove-dialog'; -import { RemoveSshKeyDialog } from 'views-components/ssh-keys-dialog/remove-dialog'; -import { VirtualMachineAttributesDialog } from 'views-components/virtual-machines-dialog/attributes-dialog'; -import { RemoveVirtualMachineDialog } from 'views-components/virtual-machines-dialog/remove-dialog'; -import { RemoveVirtualMachineLoginDialog } from 'views-components/virtual-machines-dialog/remove-login-dialog'; -import { VirtualMachineAddLoginDialog } from 'views-components/virtual-machines-dialog/add-login-dialog'; -import { AttributesApiClientAuthorizationDialog } from 'views-components/api-client-authorizations-dialog/attributes-dialog'; -import { AttributesKeepServiceDialog } from 'views-components/keep-services-dialog/attributes-dialog'; -import { AttributesLinkDialog } from 'views-components/links-dialog/attributes-dialog'; -import { AttributesSshKeyDialog } from 'views-components/ssh-keys-dialog/attributes-dialog'; -import { UserPanel } from 'views/user-panel/user-panel'; -import { UserAttributesDialog } from 'views-components/user-dialog/attributes-dialog'; -import { CreateUserDialog } from 'views-components/dialog-forms/create-user-dialog'; -import { HelpApiClientAuthorizationDialog } from 'views-components/api-client-authorizations-dialog/help-dialog'; -import { DeactivateDialog } from 'views-components/user-dialog/deactivate-dialog'; -import { ActivateDialog } from 'views-components/user-dialog/activate-dialog'; -import { SetupDialog } from 'views-components/user-dialog/setup-dialog'; -import { GroupsPanel } from 'views/groups-panel/groups-panel'; -import { RemoveGroupDialog } from 'views-components/groups-dialog/remove-dialog'; -import { GroupAttributesDialog } from 'views-components/groups-dialog/attributes-dialog'; -import { GroupDetailsPanel } from 'views/group-details-panel/group-details-panel'; -import { RemoveGroupMemberDialog } from 'views-components/groups-dialog/member-remove-dialog'; -import { GroupMemberAttributesDialog } from 'views-components/groups-dialog/member-attributes-dialog'; -import { PartialCopyToCollectionDialog } from 'views-components/dialog-forms/partial-copy-to-collection-dialog'; -import { PublicFavoritePanel } from 'views/public-favorites-panel/public-favorites-panel'; -import { LinkAccountPanel } from 'views/link-account-panel/link-account-panel'; -import { FedLogin } from './fed-login'; -import { CollectionsContentAddressPanel } from 'views/collection-content-address-panel/collection-content-address-panel'; -import { AllProcessesPanel } from '../all-processes-panel/all-processes-panel'; -import { NotFoundPanel } from '../not-found-panel/not-found-panel'; -import { AutoLogout } from 'views-components/auto-logout/auto-logout'; -import { RestoreCollectionVersionDialog } from 'views-components/collections-dialog/restore-version-dialog'; -import { WebDavS3InfoDialog } from 'views-components/webdav-s3-dialog/webdav-s3-dialog'; -import { pluginConfig } from 'plugins'; -import { ElementListReducer } from 'common/plugintypes'; -import { COLLAPSE_ICON_SIZE } from 'views-components/side-panel-toggle/side-panel-toggle'; -import { Banner } from 'views-components/baner/banner'; +import React from "react"; +import { StyleRulesCallback, WithStyles, withStyles } from "@material-ui/core/styles"; +import { Route, Switch } from "react-router"; +import { ProjectPanel } from "views/project-panel/project-panel"; +import { DetailsPanel } from "views-components/details-panel/details-panel"; +import { ArvadosTheme } from "common/custom-theme"; +import { ContextMenu } from "views-components/context-menu/context-menu"; +import { FavoritePanel } from "../favorite-panel/favorite-panel"; +import { TokenDialog } from "views-components/token-dialog/token-dialog"; +import { RichTextEditorDialog } from "views-components/rich-text-editor-dialog/rich-text-editor-dialog"; +import { Snackbar } from "views-components/snackbar/snackbar"; +import { CollectionPanel } from "../collection-panel/collection-panel"; +import { RenameFileDialog } from "views-components/rename-file-dialog/rename-file-dialog"; +import { FileRemoveDialog } from "views-components/file-remove-dialog/file-remove-dialog"; +import { MultipleFilesRemoveDialog } from "views-components/file-remove-dialog/multiple-files-remove-dialog"; +import { Routes } from "routes/routes"; +import { SidePanel } from "views-components/side-panel/side-panel"; +import { ProcessPanel } from "views/process-panel/process-panel"; +import { ChangeWorkflowDialog } from "views-components/run-process-dialog/change-workflow-dialog"; +import { CreateProjectDialog } from "views-components/dialog-forms/create-project-dialog"; +import { CreateCollectionDialog } from "views-components/dialog-forms/create-collection-dialog"; +import { CopyCollectionDialog, CopyMultiCollectionDialog } from "views-components/dialog-forms/copy-collection-dialog"; +import { CopyProcessDialog } from "views-components/dialog-forms/copy-process-dialog"; +import { UpdateCollectionDialog } from "views-components/dialog-forms/update-collection-dialog"; +import { UpdateProcessDialog } from "views-components/dialog-forms/update-process-dialog"; +import { UpdateProjectDialog } from "views-components/dialog-forms/update-project-dialog"; +import { MoveProcessDialog } from "views-components/dialog-forms/move-process-dialog"; +import { MoveProjectDialog } from "views-components/dialog-forms/move-project-dialog"; +import { MoveCollectionDialog } from "views-components/dialog-forms/move-collection-dialog"; +import { FilesUploadCollectionDialog } from "views-components/dialog-forms/files-upload-collection-dialog"; +import { PartialCopyCollectionDialog } from "views-components/dialog-forms/partial-copy-collection-dialog"; +import { RemoveProcessDialog } from "views-components/process-remove-dialog/process-remove-dialog"; +import { MainContentBar } from "views-components/main-content-bar/main-content-bar"; +import { Grid } from "@material-ui/core"; +import { TrashPanel } from "views/trash-panel/trash-panel"; +import { SharedWithMePanel } from "views/shared-with-me-panel/shared-with-me-panel"; +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 { RegisteredWorkflowPanel } from "views/workflow-panel/registered-workflow-panel"; +import { SearchResultsPanel } from "views/search-results-panel/search-results-panel"; +import { SshKeyPanel } from "views/ssh-key-panel/ssh-key-panel"; +import { SshKeyAdminPanel } from "views/ssh-key-panel/ssh-key-admin-panel"; +import { SiteManagerPanel } from "views/site-manager-panel/site-manager-panel"; +import { UserProfilePanel } from "views/user-profile-panel/user-profile-panel"; +import { SharingDialog } from "views-components/sharing-dialog/sharing-dialog"; +import { NotFoundDialog } from "views-components/not-found-dialog/not-found-dialog"; +import { AdvancedTabDialog } from "views-components/advanced-tab-dialog/advanced-tab-dialog"; +import { ProcessInputDialog } from "views-components/process-input-dialog/process-input-dialog"; +import { VirtualMachineUserPanel } from "views/virtual-machine-panel/virtual-machine-user-panel"; +import { VirtualMachineAdminPanel } from "views/virtual-machine-panel/virtual-machine-admin-panel"; +import { RepositoriesPanel } from "views/repositories-panel/repositories-panel"; +import { KeepServicePanel } from "views/keep-service-panel/keep-service-panel"; +import { ApiClientAuthorizationPanel } from "views/api-client-authorization-panel/api-client-authorization-panel"; +import { LinkPanel } from "views/link-panel/link-panel"; +import { RepositoriesSampleGitDialog } from "views-components/repositories-sample-git-dialog/repositories-sample-git-dialog"; +import { RepositoryAttributesDialog } from "views-components/repository-attributes-dialog/repository-attributes-dialog"; +import { CreateRepositoryDialog } from "views-components/dialog-forms/create-repository-dialog"; +import { RemoveRepositoryDialog } from "views-components/repository-remove-dialog/repository-remove-dialog"; +import { CreateSshKeyDialog } from "views-components/dialog-forms/create-ssh-key-dialog"; +import { PublicKeyDialog } from "views-components/ssh-keys-dialog/public-key-dialog"; +import { RemoveApiClientAuthorizationDialog } from "views-components/api-client-authorizations-dialog/remove-dialog"; +import { RemoveKeepServiceDialog } from "views-components/keep-services-dialog/remove-dialog"; +import { RemoveLinkDialog } from "views-components/links-dialog/remove-dialog"; +import { RemoveSshKeyDialog } from "views-components/ssh-keys-dialog/remove-dialog"; +import { VirtualMachineAttributesDialog } from "views-components/virtual-machines-dialog/attributes-dialog"; +import { RemoveVirtualMachineDialog } from "views-components/virtual-machines-dialog/remove-dialog"; +import { RemoveVirtualMachineLoginDialog } from "views-components/virtual-machines-dialog/remove-login-dialog"; +import { VirtualMachineAddLoginDialog } from "views-components/virtual-machines-dialog/add-login-dialog"; +import { AttributesApiClientAuthorizationDialog } from "views-components/api-client-authorizations-dialog/attributes-dialog"; +import { AttributesKeepServiceDialog } from "views-components/keep-services-dialog/attributes-dialog"; +import { AttributesLinkDialog } from "views-components/links-dialog/attributes-dialog"; +import { AttributesSshKeyDialog } from "views-components/ssh-keys-dialog/attributes-dialog"; +import { UserPanel } from "views/user-panel/user-panel"; +import { UserAttributesDialog } from "views-components/user-dialog/attributes-dialog"; +import { CreateUserDialog } from "views-components/dialog-forms/create-user-dialog"; +import { HelpApiClientAuthorizationDialog } from "views-components/api-client-authorizations-dialog/help-dialog"; +import { DeactivateDialog } from "views-components/user-dialog/deactivate-dialog"; +import { ActivateDialog } from "views-components/user-dialog/activate-dialog"; +import { SetupDialog } from "views-components/user-dialog/setup-dialog"; +import { GroupsPanel } from "views/groups-panel/groups-panel"; +import { RemoveGroupDialog } from "views-components/groups-dialog/remove-dialog"; +import { GroupAttributesDialog } from "views-components/groups-dialog/attributes-dialog"; +import { GroupDetailsPanel } from "views/group-details-panel/group-details-panel"; +import { RemoveGroupMemberDialog } from "views-components/groups-dialog/member-remove-dialog"; +import { GroupMemberAttributesDialog } from "views-components/groups-dialog/member-attributes-dialog"; +import { PartialCopyToCollectionDialog } from "views-components/dialog-forms/partial-copy-to-collection-dialog"; +import { PublicFavoritePanel } from "views/public-favorites-panel/public-favorites-panel"; +import { LinkAccountPanel } from "views/link-account-panel/link-account-panel"; +import { FedLogin } from "./fed-login"; +import { CollectionsContentAddressPanel } from "views/collection-content-address-panel/collection-content-address-panel"; +import { AllProcessesPanel } from "../all-processes-panel/all-processes-panel"; +import { NotFoundPanel } from "../not-found-panel/not-found-panel"; +import { AutoLogout } from "views-components/auto-logout/auto-logout"; +import { RestoreCollectionVersionDialog } from "views-components/collections-dialog/restore-version-dialog"; +import { WebDavS3InfoDialog } from "views-components/webdav-s3-dialog/webdav-s3-dialog"; +import { pluginConfig } from "plugins"; +import { ElementListReducer } from "common/plugintypes"; +import { COLLAPSE_ICON_SIZE } from "views-components/side-panel-toggle/side-panel-toggle"; +import { Banner } from "views-components/baner/banner"; -type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content'; +type CssRules = "root" | "container" | "splitter" | "asidePanel" | "contentWrapper" | "content"; const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ root: { @@ -111,20 +111,20 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ background: theme.palette.background.default, }, container: { - position: 'relative', + position: "relative", }, splitter: { - '& > .layout-splitter': { - width: '2px', + "& > .layout-splitter": { + width: "2px", }, - '& > .layout-splitter-disabled': { - pointerEvents: 'none', - cursor: 'pointer', + "& > .layout-splitter-disabled": { + pointerEvents: "none", + cursor: "pointer", }, }, asidePanel: { paddingTop: theme.spacing.unit, - height: '100%', + height: "100%", }, contentWrapper: { paddingTop: theme.spacing.unit, @@ -136,7 +136,7 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ paddingRight: theme.spacing.unit * 3, // Reserve vertical space for app bar + MainContentBar minHeight: `calc(100vh - ${theme.spacing.unit * 16}px)`, - display: 'flex', + display: "flex", }, }); @@ -152,42 +152,126 @@ type WorkbenchPanelProps = WithStyles & WorkbenchDataProps; const defaultSplitterSize = 90; const getSplitterInitialSize = () => { - const splitterSize = localStorage.getItem('splitterSize'); + const splitterSize = localStorage.getItem("splitterSize"); return splitterSize ? Number(splitterSize) : defaultSplitterSize; }; -const saveSplitterSize = (size: number) => localStorage.setItem('splitterSize', size.toString()); +const saveSplitterSize = (size: number) => localStorage.setItem("splitterSize", size.toString()); let routes = ( <> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); @@ -199,26 +283,34 @@ routes = React.createElement( pluginConfig.centerPanelList.reduce(reduceRoutesFn, React.Children.toArray(routes.props.children)) ); -const applyCollapsedState = (isCollapsed) => { - const rightPanel: Element = document.getElementsByClassName('layout-pane')[1]; - const totalWidth: number = document.getElementsByClassName('splitter-layout')[0]?.clientWidth; +const applyCollapsedState = isCollapsed => { + const rightPanel: Element = document.getElementsByClassName("layout-pane")[1]; + const totalWidth: number = document.getElementsByClassName("splitter-layout")[0]?.clientWidth; const rightPanelExpandedWidth = (totalWidth - COLLAPSE_ICON_SIZE) / (totalWidth / 100); if (rightPanel) { - rightPanel.setAttribute('style', `width: ${isCollapsed ? rightPanelExpandedWidth : getSplitterInitialSize()}%`); + rightPanel.setAttribute("style", `width: ${isCollapsed ? rightPanelExpandedWidth : getSplitterInitialSize()}%`); } - const splitter = document.getElementsByClassName('layout-splitter')[0]; - isCollapsed ? splitter?.classList.add('layout-splitter-disabled') : splitter?.classList.remove('layout-splitter-disabled'); + const splitter = document.getElementsByClassName("layout-splitter")[0]; + isCollapsed ? splitter?.classList.add("layout-splitter-disabled") : splitter?.classList.remove("layout-splitter-disabled"); }; export const WorkbenchPanel = withStyles(styles)((props: WorkbenchPanelProps) => { //panel size will not scale automatically on window resize, so we do it manually - window.addEventListener('resize', () => applyCollapsedState(props.sidePanelIsCollapsed)); + window.addEventListener("resize", () => applyCollapsedState(props.sidePanelIsCollapsed)); applyCollapsedState(props.sidePanelIsCollapsed); return ( - + {props.sessionIdleTimeout > 0 && } - + primaryMinSize={10} secondaryInitialSize={getSplitterInitialSize()} secondaryMinSize={40} - onSecondaryPaneSizeChange={saveSplitterSize} - > + onSecondaryPaneSizeChange={saveSplitterSize}> {props.isUserActive && props.isNotLinking && ( - + )} - - + + {props.isNotLinking && } - + {routes.props.children} - + @@ -257,6 +368,7 @@ export const WorkbenchPanel = withStyles(styles)((props: WorkbenchPanelProps) => +