diff --git a/Classes/Controller/BackendServiceController.php b/Classes/Controller/BackendServiceController.php index fa17949ed2..83a0205ef8 100644 --- a/Classes/Controller/BackendServiceController.php +++ b/Classes/Controller/BackendServiceController.php @@ -452,8 +452,9 @@ public function cutNodesAction(array $nodes): void public function getWorkspaceInfoAction(): void { + $contentRepositoryIdentifier = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryIdentifier; $workspaceHelper = new WorkspaceHelper(); - $personalWorkspaceInfo = $workspaceHelper->getPersonalWorkspace(); + $personalWorkspaceInfo = $workspaceHelper->getPersonalWorkspace($contentRepositoryIdentifier); $this->view->assign('value', $personalWorkspaceInfo); } diff --git a/packages/neos-ui-backend-connector/src/Endpoints/Helpers.ts b/packages/neos-ui-backend-connector/src/Endpoints/Helpers.ts index b37702d16e..b0bf9e0946 100644 --- a/packages/neos-ui-backend-connector/src/Endpoints/Helpers.ts +++ b/packages/neos-ui-backend-connector/src/Endpoints/Helpers.ts @@ -1,8 +1,3 @@ -export const getContextString = (uri: string) => { - const decodedUri = unescape(uri); - const uriParts = decodedUri.split('@'); - return uriParts ? uriParts[1].split('.')[0] : ''; -}; /** * diff --git a/packages/neos-ui-backend-connector/src/Endpoints/index.ts b/packages/neos-ui-backend-connector/src/Endpoints/index.ts index aa39086ae7..e6aae49105 100644 --- a/packages/neos-ui-backend-connector/src/Endpoints/index.ts +++ b/packages/neos-ui-backend-connector/src/Endpoints/index.ts @@ -1,4 +1,4 @@ -import {getElementInnerText, getElementAttributeValue, getContextString} from './Helpers'; +import {getElementInnerText, getElementAttributeValue} from './Helpers'; import {isNil} from '@neos-project/utils-helpers'; import {urlWithParams, encodeAsQueryString} from '@neos-project/utils-helpers/src/urlWithParams'; @@ -475,16 +475,11 @@ export default (routes: Routes) => { throw new Error('.node-frontend-uri does not contain a valid href attribut'); } - const nodePath = d.querySelector('.node-path'); - if (!nodePath) { - throw new Error('.node-path is not found in the result'); + const nodeContextPath = d.querySelector('.node-context-path'); + if (!nodeContextPath) { + throw new Error('.node-context-path is not found in the result'); } - // Hackish way to get context string from uri - const contextString = getContextString(nodeFrontendUri); - // TODO: Temporary hack due to missing contextPath in the API response - const nodeContextPath = `${nodePath.innerHTML}@${contextString}`; - return { nodeFound: true, nodeFrontendUri, diff --git a/packages/neos-ui-redux-store/src/UI/PageTree/selectors.ts b/packages/neos-ui-redux-store/src/UI/PageTree/selectors.ts index 49f863cd2f..d4c225c433 100644 --- a/packages/neos-ui-redux-store/src/UI/PageTree/selectors.ts +++ b/packages/neos-ui-redux-store/src/UI/PageTree/selectors.ts @@ -4,8 +4,32 @@ import {createSelector} from 'reselect'; import {siteNodeContextPathSelector, siteNodeSelector, nodesByContextPathSelector} from '@neos-project/neos-ui-redux-store/src/CR/Nodes/selectors'; import {isNodeCollapsed} from '@neos-project/neos-ui-redux-store/src/CR/Nodes/helpers'; +import {NodeContextPath, NodeMap} from '@neos-project/neos-ts-interfaces'; + +// contextPath for Neos >= 9.0 is a NodeAddress without hierarchy infos; so we need to traverse the "parent" links. +function rootlineForNode(contextPath: NodeContextPath, nodesByContextPath: NodeMap): string[] { + const node = nodesByContextPath[contextPath]; + if (node && node.parent) { + return [...rootlineForNode(node.parent, nodesByContextPath), node.identifier]; + } + return []; +} export const getAllFocused = (state: GlobalState) => $get(['ui', 'pageTree', 'focused'], state); +export const areFocusedNodesNestedInEachOther = createSelector( + [ + getAllFocused, + nodesByContextPathSelector + ], + (focusedNodesContextPaths, nodesByContextPath) => { + const rootlinesOfFocusedNodes = focusedNodesContextPaths.map((contextPath: NodeContextPath) => rootlineForNode(contextPath, nodesByContextPath).join('/')); + + return !rootlinesOfFocusedNodes.every((pathA: string) => { + return rootlinesOfFocusedNodes.every((pathB: string) => !(pathB.indexOf(pathA) === 0 && pathA !== pathB)); + }); + } +); + export const getFocused = (state: GlobalState) => { const focused = getAllFocused(state); return focused && focused[0] ? focused[0] : null; diff --git a/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/Node/index.js b/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/Node/index.js index 3b4c14fb8d..192a25e853 100644 --- a/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/Node/index.js +++ b/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/Node/index.js @@ -12,8 +12,6 @@ import {actions, selectors} from '@neos-project/neos-ui-redux-store'; import {isNodeCollapsed} from '@neos-project/neos-ui-redux-store/src/CR/Nodes/helpers'; import {neos} from '@neos-project/neos-ui-decorators'; -import {hasNestedNodes} from '@neos-project/neos-ui/src/Containers/LeftSideBar/NodeTree/helpers'; - import hashSum from 'hash-sum'; import moment from 'moment'; import {urlWithParams} from '@neos-project/utils-helpers/src/urlWithParams'; @@ -74,6 +72,8 @@ export default class Node extends PureComponent { canBeInsertedAlongside: PropTypes.bool, canBeInsertedInto: PropTypes.bool, isNodeDirty: PropTypes.bool.isRequired, + + areFocusedNodesNestedInEachOther: PropTypes.bool, isWorkspaceReadOnly: PropTypes.bool, nodeTypesRegistry: PropTypes.object.isRequired, @@ -281,6 +281,7 @@ export default class Node extends PureComponent { currentlyDraggedNodes, isContentTreeNode, focusedNodesContextPaths, + areFocusedNodesNestedInEachOther, isWorkspaceReadOnly } = this.props; @@ -298,7 +299,7 @@ export default class Node extends PureComponent { // Autocreated or we have nested nodes and the node that we are dragging belongs to the selection // For read only workspaces we also forbid drag and drop - const dragForbidden = isWorkspaceReadOnly || node.isAutoCreated || (hasNestedNodes(focusedNodesContextPaths) && focusedNodesContextPaths.includes(node.contextPath)); + const dragForbidden = isWorkspaceReadOnly || node.isAutoCreated || (areFocusedNodesNestedInEachOther && focusedNodesContextPaths.includes(node.contextPath)); return ( @@ -409,6 +410,7 @@ export const PageTreeNode = withNodeTypeRegistryAndI18nRegistry(connect( return ({ isContentTreeNode: false, focusedNodesContextPaths: selectors.UI.PageTree.getAllFocused(state), + areFocusedNodesNestedInEachOther: selectors.UI.PageTree.areFocusedNodesNestedInEachOther(state), rootNode: selectors.CR.Nodes.siteNodeSelector(state), loadingDepth: neos.configuration.nodeTree.loadingDepth, childNodes: childrenOfSelector(state, getContextPath(node)), @@ -457,6 +459,7 @@ export const ContentTreeNode = withNodeTypeRegistryAndI18nRegistry(connect( return ({ isContentTreeNode: true, focusedNodesContextPaths: selectors.UI.PageTree.getAllFocused(state), + areFocusedNodesNestedInEachOther: selectors.UI.PageTree.areFocusedNodesNestedInEachOther(state), rootNode: selectors.CR.Nodes.documentNodeSelector(state), loadingDepth: neos.configuration.structureTree.loadingDepth, childNodes: childrenOfSelector(state, getContextPath(node)), diff --git a/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/helpers.ts b/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/helpers.ts deleted file mode 100644 index d26bdd3fb3..0000000000 --- a/packages/neos-ui/src/Containers/LeftSideBar/NodeTree/helpers.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {NodeContextPath} from '@neos-project/neos-ts-interfaces'; - -export const hasNestedNodes = (focusedNodesContextPaths: NodeContextPath[]) => { - return !focusedNodesContextPaths.every((contextPathA: NodeContextPath) => { - const path = contextPathA.split('@')[0]; - // TODO: adjust this for the new CR when this is merged: https://github.com/neos/neos-ui/pull/2178 - return focusedNodesContextPaths.every((contextPathB: NodeContextPath) => !(contextPathB.indexOf(path) === 0 && contextPathA !== contextPathB)); - }); -}; diff --git a/packages/neos-ui/src/Containers/LeftSideBar/NodeTreeToolBar/index.js b/packages/neos-ui/src/Containers/LeftSideBar/NodeTreeToolBar/index.js index 58ab25654c..36cfbb0ab1 100644 --- a/packages/neos-ui/src/Containers/LeftSideBar/NodeTreeToolBar/index.js +++ b/packages/neos-ui/src/Containers/LeftSideBar/NodeTreeToolBar/index.js @@ -6,7 +6,6 @@ import {$transform, $get, $contains} from 'plow-js'; import {isEqualSet} from '@neos-project/utils-helpers'; import {neos} from '@neos-project/neos-ui-decorators'; import {selectors, actions} from '@neos-project/neos-ui-redux-store'; -import {hasNestedNodes} from '@neos-project/neos-ui/src/Containers/LeftSideBar/NodeTree/helpers'; import {InsertPosition} from '@neos-project/neos-ts-interfaces'; import { @@ -302,9 +301,9 @@ const makeMapStateToProps = isDocument => (state, {nodeTypesRegistry}) => { }); } - const selectionHasNestedNodes = hasNestedNodes(focusedNodesContextPaths); + const areFocusedNodesNestedInEachOther = selectors.UI.PageTree.areFocusedNodesNestedInEachOther(state); - const canBeDeleted = (removeAllowed(focusedNodesContextPaths, state) && !selectionHasNestedNodes) || false; + const canBeDeleted = (removeAllowed(focusedNodesContextPaths, state) && !areFocusedNodesNestedInEachOther) || false; const visibilityCanBeToggled = visibilityToggleAllowed(focusedNodesContextPaths, state); const canBeEdited = editingAllowed(focusedNodesContextPaths, state); @@ -324,7 +323,7 @@ const makeMapStateToProps = isDocument => (state, {nodeTypesRegistry}) => { isDocument ? selectors.UI.PageTree.destructiveOperationsAreDisabledForPageTreeSelector(state) : selectors.CR.Nodes.destructiveOperationsAreDisabledForContentTreeSelector(state) - ) || selectionHasNestedNodes; + ) || areFocusedNodesNestedInEachOther; const isLoading = isDocument ? selectors.UI.PageTree.getIsLoading(state) : selectors.UI.ContentTree.getIsLoading(state); return {