From 670d92f78e9af2390b93e5d984f5fabf59a16071 Mon Sep 17 00:00:00 2001 From: Lucas Di Pentima Date: Tue, 4 Jan 2022 10:58:18 -0300 Subject: [PATCH] 18219: Replaces edit props dialog with full editor on details panel. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- cypress/integration/collection.spec.js | 2 +- .../details-panel/details-panel-action.ts | 11 +-- .../details-panel/collection-details.tsx | 62 ++++++++++-- .../details-panel/project-details.tsx | 31 +++--- .../resource-properties-dialog-form.tsx | 20 ---- .../resource-properties-dialog.tsx | 94 ------------------- .../collection-panel/collection-panel.tsx | 26 +---- src/views/workbench/workbench.tsx | 2 - 8 files changed, 79 insertions(+), 169 deletions(-) delete mode 100644 src/views-components/resource-properties-dialog/resource-properties-dialog-form.tsx delete mode 100644 src/views-components/resource-properties-dialog/resource-properties-dialog.tsx diff --git a/cypress/integration/collection.spec.js b/cypress/integration/collection.spec.js index ce711be9..32c1320b 100644 --- a/cypress/integration/collection.spec.js +++ b/cypress/integration/collection.spec.js @@ -137,7 +137,7 @@ describe('Collection panel tests', function () { cy.get('[data-cy=additional-info-icon]').click(); cy.get('[data-cy=details-panel]').within(() => { - cy.get('[data-cy=property-editor-btn]').click(); + cy.get('[data-cy=details-panel-edit-btn]').click(); }); cy.get('[data-cy=resource-properties-dialog').contains('Edit properties'); diff --git a/src/store/details-panel/details-panel-action.ts b/src/store/details-panel/details-panel-action.ts index 90ca0f4f..b708ad62 100644 --- a/src/store/details-panel/details-panel-action.ts +++ b/src/store/details-panel/details-panel-action.ts @@ -5,11 +5,10 @@ import { unionize, ofType, UnionOf } from 'common/unionize'; import { RootState } from 'store/store'; import { Dispatch } from 'redux'; -import { dialogActions } from 'store/dialog/dialog-actions'; import { getResource } from 'store/resources/resources'; import { ServiceRepository } from 'services/services'; import { resourcesActions } from 'store/resources/resources-actions'; -import {snackbarActions, SnackbarKind} from 'store/snackbar/snackbar-actions'; +import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; import { FilterBuilder } from 'services/api/filter-builder'; import { OrderBuilder } from 'services/api/order-builder'; import { CollectionResource } from 'models/collection'; @@ -25,9 +24,6 @@ export const detailsPanelActions = unionize({ export type DetailsPanelAction = UnionOf; -export const RESOURCE_PROPERTIES_FORM_NAME = 'resourcePropertiesFormName'; -export const RESOURCE_PROPERTIES_DIALOG_NAME = 'resourcePropertiesDialogName'; - export const loadDetailsPanel = (uuid: string) => (dispatch: Dispatch, getState: () => RootState) => { if (getState().detailsPanel.isOpened) { @@ -51,11 +47,6 @@ export const openDetailsPanel = (uuid?: string, tabNr: number = 0) => } }; -export const openResourcePropertiesDialog = () => - (dispatch: Dispatch) => { - dispatch(dialogActions.OPEN_DIALOG({ id: RESOURCE_PROPERTIES_DIALOG_NAME, data: { } })); - }; - export const refreshCollectionVersionsList = (uuid: string) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { services.collectionService.list({ diff --git a/src/views-components/details-panel/collection-details.tsx b/src/views-components/details-panel/collection-details.tsx index dcd2ee48..7f35ca65 100644 --- a/src/views-components/details-panel/collection-details.tsx +++ b/src/views-components/details-panel/collection-details.tsx @@ -3,21 +3,22 @@ // SPDX-License-Identifier: AGPL-3.0 import React from 'react'; -import { CollectionIcon } from 'components/icon/icon'; +import { CollectionIcon, RenameIcon } from 'components/icon/icon'; import { CollectionResource } from 'models/collection'; import { DetailsData } from "./details-data"; import { CollectionDetailsAttributes } from 'views/collection-panel/collection-panel'; import { RootState } from 'store/store'; import { filterResources, getResource } from 'store/resources/resources'; import { connect } from 'react-redux'; -import { Grid, ListItem, StyleRulesCallback, Typography, withStyles, WithStyles } from '@material-ui/core'; +import { Button, Grid, ListItem, StyleRulesCallback, Typography, withStyles, WithStyles } from '@material-ui/core'; import { formatDate, formatFileSize } from 'common/formatters'; import { UserNameFromID } from '../data-explorer/renderers'; import { Dispatch } from 'redux'; import { navigateTo } from 'store/navigation/navigation-action'; import { openContextMenu, resourceUuidToContextMenuKind } from 'store/context-menu/context-menu-actions'; +import { openCollectionUpdateDialog } from 'store/collections/collection-update-actions'; -export type CssRules = 'versionBrowserHeader' | 'versionBrowserItem' | 'versionBrowserField'; +export type CssRules = 'versionBrowserHeader' | 'versionBrowserItem' | 'versionBrowserField' | 'editIcon'; const styles: StyleRulesCallback = theme => ({ versionBrowserHeader: { @@ -29,7 +30,11 @@ const styles: StyleRulesCallback = theme => ({ }, versionBrowserField: { textAlign: 'center', - } + }, + editIcon: { + paddingRight: theme.spacing.unit/2, + fontSize: '1.125rem', + }, }); export class CollectionDetails extends DetailsData { @@ -54,7 +59,7 @@ export class CollectionDetails extends DetailsData { } private getCollectionInfo() { - return ; + return ; } private getVersionBrowser() { @@ -62,6 +67,47 @@ export class CollectionDetails extends DetailsData { } } +interface CollectionInfoDataProps { + currentCollection: CollectionResource | undefined; +} + +interface CollectionInfoDispatchProps { + editCollection: (collection: CollectionResource | undefined) => void; +} + +const ciMapStateToProps = (state: RootState): CollectionInfoDataProps => { + return { + currentCollection: getResource(state.detailsPanel.resourceUuid)(state.resources), + }; +}; + +const ciMapDispatchToProps = (dispatch: Dispatch): CollectionInfoDispatchProps => ({ + editCollection: (collection: CollectionResource) => + dispatch(openCollectionUpdateDialog({ + uuid: collection.uuid, + name: collection.name, + description: collection.description, + properties: collection.properties, + storageClassesDesired: collection.storageClassesDesired, + })), +}); + +type CollectionInfoProps = CollectionInfoDataProps & CollectionInfoDispatchProps & WithStyles; + +const CollectionInfo = withStyles(styles)( + connect(ciMapStateToProps, ciMapDispatchToProps)( + ({ currentCollection, editCollection, classes }: CollectionInfoProps) => + currentCollection !== undefined + ?
+ + +
+ :
+ ) +); + interface CollectionVersionBrowserProps { currentCollection: CollectionResource | undefined; versions: CollectionResource[]; @@ -72,7 +118,7 @@ interface CollectionVersionBrowserDispatchProps { handleContextMenu: (event: React.MouseEvent, collection: CollectionResource) => void; } -const mapStateToProps = (state: RootState): CollectionVersionBrowserProps => { +const vbMapStateToProps = (state: RootState): CollectionVersionBrowserProps => { const currentCollection = getResource(state.detailsPanel.resourceUuid)(state.resources); const versions = (currentCollection && filterResources(rsc => @@ -82,7 +128,7 @@ const mapStateToProps = (state: RootState): CollectionVersionBrowserProps => { return { currentCollection, versions }; }; -const mapDispatchToProps = () => +const vbMapDispatchToProps = () => (dispatch: Dispatch): CollectionVersionBrowserDispatchProps => ({ showVersion: (collection) => dispatch(navigateTo(collection.uuid)), handleContextMenu: (event: React.MouseEvent, collection: CollectionResource) => { @@ -103,7 +149,7 @@ const mapDispatchToProps = () => }); const CollectionVersionBrowser = withStyles(styles)( - connect(mapStateToProps, mapDispatchToProps)( + connect(vbMapStateToProps, vbMapDispatchToProps)( ({ currentCollection, versions, showVersion, handleContextMenu, classes }: CollectionVersionBrowserProps & CollectionVersionBrowserDispatchProps & WithStyles) => { return
diff --git a/src/views-components/details-panel/project-details.tsx b/src/views-components/details-panel/project-details.tsx index 82e3e754..c3c3d68e 100644 --- a/src/views-components/details-panel/project-details.tsx +++ b/src/views-components/details-panel/project-details.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { openResourcePropertiesDialog } from 'store/details-panel/details-panel-action'; import { ProjectIcon, RenameIcon, FilterGroupIcon } from 'components/icon/icon'; import { ProjectResource } from 'models/project'; import { formatDate } from 'common/formatters'; @@ -13,12 +12,13 @@ import { resourceLabel } from 'common/labels'; import { DetailsData } from "./details-data"; import { DetailsAttribute } from "components/details-attribute/details-attribute"; import { RichTextEditorLink } from 'components/rich-text-editor-link/rich-text-editor-link'; -import { withStyles, StyleRulesCallback, WithStyles } from '@material-ui/core'; +import { withStyles, StyleRulesCallback, WithStyles, Button } from '@material-ui/core'; import { ArvadosTheme } from 'common/custom-theme'; import { Dispatch } from 'redux'; import { getPropertyChip } from '../resource-properties-form/property-chip'; import { ResourceOwnerWithName } from '../data-explorer/renderers'; import { GroupClass } from "models/group"; +import { openProjectUpdateDialog, ProjectUpdateFormDialogData } from 'store/projects/project-update-actions'; export class ProjectDetails extends DetailsData { getIcon(className?: string) { @@ -41,8 +41,8 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ marginBottom: theme.spacing.unit }, editIcon: { + paddingRight: theme.spacing.unit/2, fontSize: '1.125rem', - cursor: 'pointer' } }); @@ -51,11 +51,12 @@ interface ProjectDetailsComponentDataProps { } interface ProjectDetailsComponentActionProps { - onClick: () => void; + onClick: (prj: ProjectUpdateFormDialogData) => () => void; } const mapDispatchToProps = (dispatch: Dispatch) => ({ - onClick: () => dispatch(openResourcePropertiesDialog()), + onClick: (prj: ProjectUpdateFormDialogData) => + () => dispatch(openProjectUpdateDialog(prj)), }); type ProjectDetailsComponentProps = ProjectDetailsComponentDataProps & ProjectDetailsComponentActionProps & WithStyles; @@ -63,6 +64,17 @@ type ProjectDetailsComponentProps = ProjectDetailsComponentDataProps & ProjectDe const ProjectDetailsComponent = connect(null, mapDispatchToProps)( withStyles(styles)( ({ classes, project, onClick }: ProjectDetailsComponentProps) =>
+ {project.groupClass !== GroupClass.FILTER ? + + : '' + } } /> @@ -78,14 +90,7 @@ const ProjectDetailsComponent = connect(null, mapDispatchToProps)( : '---' } - - {project.groupClass !== GroupClass.FILTER ? -
- -
- : '' - } -
+ { Object.keys(project.properties).map(k => Array.isArray(project.properties[k]) diff --git a/src/views-components/resource-properties-dialog/resource-properties-dialog-form.tsx b/src/views-components/resource-properties-dialog/resource-properties-dialog-form.tsx deleted file mode 100644 index cfb999cc..00000000 --- a/src/views-components/resource-properties-dialog/resource-properties-dialog-form.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { reduxForm, reset } from 'redux-form'; -import { RESOURCE_PROPERTIES_FORM_NAME } from 'store/details-panel/details-panel-action'; -import { ResourcePropertiesForm, ResourcePropertiesFormData } from 'views-components/resource-properties-form/resource-properties-form'; -import { withStyles } from '@material-ui/core'; -import { Dispatch } from 'redux'; -import { createResourceProperty } from 'store/resources/resources-actions'; - -const Form = withStyles(({ spacing }) => ({ container: { marginBottom: spacing.unit * 2 } }))(ResourcePropertiesForm); - -export const ResourcePropertiesDialogForm = reduxForm({ - form: RESOURCE_PROPERTIES_FORM_NAME, - onSubmit: (data, dispatch: Dispatch) => { - dispatch(createResourceProperty(data)); - dispatch(reset(RESOURCE_PROPERTIES_FORM_NAME)); - } -})(Form); diff --git a/src/views-components/resource-properties-dialog/resource-properties-dialog.tsx b/src/views-components/resource-properties-dialog/resource-properties-dialog.tsx deleted file mode 100644 index 2502f50a..00000000 --- a/src/views-components/resource-properties-dialog/resource-properties-dialog.tsx +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import React from "react"; -import { Dispatch } from "redux"; -import { connect } from "react-redux"; -import { RootState } from 'store/store'; -import { withDialog, WithDialogProps } from "store/dialog/with-dialog"; -import { RESOURCE_PROPERTIES_DIALOG_NAME } from 'store/details-panel/details-panel-action'; -import { - Dialog, - DialogTitle, - DialogContent, - DialogActions, - Button, - withStyles, - StyleRulesCallback, - WithStyles -} from '@material-ui/core'; -import { ArvadosTheme } from 'common/custom-theme'; -import { ResourcePropertiesDialogForm } from 'views-components/resource-properties-dialog/resource-properties-dialog-form'; -import { getResource } from 'store/resources/resources'; -import { getPropertyChip } from "../resource-properties-form/property-chip"; -import { deleteResourceProperty } from "store/resources/resources-actions"; -import { ResourceWithProperties } from "models/resource"; - -type CssRules = 'tag'; - -const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ - tag: { - marginRight: theme.spacing.unit, - marginBottom: theme.spacing.unit - } -}); - -interface ResourcePropertiesDialogDataProps { - resource: ResourceWithProperties; -} - -interface ResourcePropertiesDialogActionProps { - handleDelete: (uuid: string, key: string, value: string) => void; -} - -const mapStateToProps = ({ detailsPanel, resources, properties }: RootState): ResourcePropertiesDialogDataProps => ({ - resource: getResource(detailsPanel.resourceUuid)(resources) as ResourceWithProperties, -}); - -const mapDispatchToProps = (dispatch: Dispatch): ResourcePropertiesDialogActionProps => ({ - handleDelete: (uuid: string, key: string, value: string) => () => dispatch(deleteResourceProperty(uuid, key, value)), -}); - -type ResourcePropertiesDialogProps = ResourcePropertiesDialogDataProps & ResourcePropertiesDialogActionProps & WithDialogProps<{}> & WithStyles; - -export const ResourcePropertiesDialog = connect(mapStateToProps, mapDispatchToProps)( - withStyles(styles)( - withDialog(RESOURCE_PROPERTIES_DIALOG_NAME)( - ({ classes, open, closeDialog, handleDelete, resource }: ResourcePropertiesDialogProps) => - -
- Edit properties - - - {resource && resource.properties && - Object.keys(resource.properties).map(k => - Array.isArray(resource.properties[k]) - ? resource.properties[k].map((v: string) => - getPropertyChip( - k, v, - handleDelete(resource.uuid, k, v), - classes.tag)) - : getPropertyChip( - k, resource.properties[k], - handleDelete(resource.uuid, k, resource.properties[k]), - classes.tag) - ) - } - - - - -
-
- ) - )); diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx index 851008c0..2c7a8f2c 100644 --- a/src/views/collection-panel/collection-panel.tsx +++ b/src/views/collection-panel/collection-panel.tsx @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0 import React from 'react'; -import { Dispatch } from 'redux'; import { StyleRulesCallback, WithStyles, @@ -18,7 +17,7 @@ import { connect, DispatchProp } from "react-redux"; import { RouteComponentProps } from 'react-router'; import { ArvadosTheme } from 'common/custom-theme'; import { RootState } from 'store/store'; -import { MoreOptionsIcon, CollectionIcon, ReadOnlyIcon, CollectionOldVersionIcon, RenameIcon } from 'components/icon/icon'; +import { MoreOptionsIcon, CollectionIcon, ReadOnlyIcon, CollectionOldVersionIcon } from 'components/icon/icon'; import { DetailsAttribute } from 'components/details-attribute/details-attribute'; import { CollectionResource, getCollectionUrl } from 'models/collection'; import { CollectionPanelFiles } from 'views-components/collection-panel-files/collection-panel-files'; @@ -26,7 +25,7 @@ import { navigateToProcess, collectionPanelActions } from 'store/collection-pane import { getResource } from 'store/resources/resources'; import { openContextMenu, resourceUuidToContextMenuKind } from 'store/context-menu/context-menu-actions'; import { formatDate, formatFileSize } from "common/formatters"; -import { openDetailsPanel, openResourcePropertiesDialog } from 'store/details-panel/details-panel-action'; +import { openDetailsPanel } from 'store/details-panel/details-panel-action'; import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; import { getPropertyChip } from 'views-components/resource-properties-form/property-chip'; import { IllegalNamingWarning } from 'components/warning/warning'; @@ -261,10 +260,6 @@ export const CollectionPanel = withStyles(styles)( ) ); -interface CollectionDetailsActionProps { - onClick: () => void; -} - interface CollectionDetailsProps { item: CollectionResource; classes?: any; @@ -272,12 +267,7 @@ interface CollectionDetailsProps { showVersionBrowser?: () => void; } -const mapDispatchToProps = (dispatch: Dispatch) => ({ - onClick: () => dispatch(openResourcePropertiesDialog()), -}); - -export const CollectionDetailsAttributes = connect(null, mapDispatchToProps)( -(props: CollectionDetailsProps & CollectionDetailsActionProps) => { +export const CollectionDetailsAttributes = (props: CollectionDetailsProps) => { const item = props.item; const classes = props.classes || { label: '', value: '', button: '', tag: '' }; const isOldVersion = item && item.currentVersionUuid !== item.uuid; @@ -345,13 +335,7 @@ export const CollectionDetailsAttributes = connect(null, mapDispatchToProps)( - { !props.twoCol - ?
- -
- : '' } -
+ label='Properties' /> { Object.keys(item.properties).length > 0 ? Object.keys(item.properties).map(k => Array.isArray(item.properties[k]) @@ -361,4 +345,4 @@ export const CollectionDetailsAttributes = connect(null, mapDispatchToProps)( :
No properties
}
; -}); +}; diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index ea24c872..e7bb048f 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -54,7 +54,6 @@ import { AdvancedTabDialog } from 'views-components/advanced-tab-dialog/advanced 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 { ResourcePropertiesDialog } from 'views-components/resource-properties-dialog/resource-properties-dialog'; 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'; @@ -242,7 +241,6 @@ export const WorkbenchPanel = - -- 2.30.2