From 8603b0cfa5ac1d3c349cdab8c493ecabc18123fc Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Thu, 22 Dec 2022 17:15:39 +0100 Subject: [PATCH 01/15] TASK: Remove plow-js from `@neos-project/neos-ui-sagas` --- packages/neos-ui-sagas/package.json | 1 - .../src/CR/ContentDimensions/index.js | 7 +-- .../src/CR/NodeOperations/addNode.js | 9 ++-- .../src/CR/NodeOperations/moveDroppedNode.js | 5 +- .../src/CR/NodeOperations/pasteNode.js | 9 ++-- .../src/CR/NodeOperations/reloadState.js | 18 +++++--- .../NodeOperations/removeNodeIfConfirmed.js | 3 +- .../neos-ui-sagas/src/CR/Policies/index.js | 6 +-- packages/neos-ui-sagas/src/Changes/index.js | 7 ++- packages/neos-ui-sagas/src/Publish/index.js | 11 +++-- .../src/UI/ContentCanvas/index.js | 16 +++++-- .../neos-ui-sagas/src/UI/ContentTree/index.js | 46 +++++++++++-------- .../src/UI/EditPreviewMode/index.js | 5 +- .../neos-ui-sagas/src/UI/Impersonate/index.js | 7 ++- .../neos-ui-sagas/src/UI/Inspector/index.js | 17 ++++--- .../neos-ui-sagas/src/UI/PageTree/index.js | 35 ++++++++------ yarn.lock | 1 - 17 files changed, 117 insertions(+), 86 deletions(-) diff --git a/packages/neos-ui-sagas/package.json b/packages/neos-ui-sagas/package.json index 7b0ecea3e9..ba351f339e 100644 --- a/packages/neos-ui-sagas/package.json +++ b/packages/neos-ui-sagas/package.json @@ -25,7 +25,6 @@ "@neos-project/neos-ui-redux-store": "workspace:*", "lodash.escaperegexp": "^4.1.2", "mousetrap": "^1.6.3", - "plow-js": "^2.2.0", "redux-saga": "^0.15.0" }, "license": "GNU GPLv3", diff --git a/packages/neos-ui-sagas/src/CR/ContentDimensions/index.js b/packages/neos-ui-sagas/src/CR/ContentDimensions/index.js index 4ac5a70e0c..94c8fe909d 100644 --- a/packages/neos-ui-sagas/src/CR/ContentDimensions/index.js +++ b/packages/neos-ui-sagas/src/CR/ContentDimensions/index.js @@ -1,5 +1,4 @@ import {put, select, race, take, takeLatest, takeEvery, call} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actions, actionTypes, selectors} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -22,7 +21,7 @@ export function * watchSelectPreset() { yield take(actionTypes.CR.ContentDimensions.SELECT_PRESET); const targetDimensions = yield select(selectors.CR.ContentDimensions.active); const currentContentCanvasNode = yield select(selectors.CR.Nodes.documentNodeSelector); - const currentContentCanvasNodeIdentifier = $get('identifier', currentContentCanvasNode); + const currentContentCanvasNodeIdentifier = currentContentCanvasNode?.identifier; const informationAboutNodeInTargetDimension = yield call(ensureNodeInSelectedDimension, { nodeIdentifier: currentContentCanvasNodeIdentifier, @@ -67,7 +66,9 @@ function * ensureNodeInSelectedDimension({nodeIdentifier, sourceDimensions, targ getSingleNode, adoptNodeToOtherDimension } = backend.get().endpoints; - const currentWorkspaceName = yield select($get('cr.workspaces.personalWorkspace.name')); + const currentWorkspaceName = yield select( + state => state?.cr?.workspaces?.personalWorkspace?.name + ); const { nodeFound, diff --git a/packages/neos-ui-sagas/src/CR/NodeOperations/addNode.js b/packages/neos-ui-sagas/src/CR/NodeOperations/addNode.js index 77ad9da4e2..27a4d95a94 100644 --- a/packages/neos-ui-sagas/src/CR/NodeOperations/addNode.js +++ b/packages/neos-ui-sagas/src/CR/NodeOperations/addNode.js @@ -1,5 +1,4 @@ import {takeLatest, take, put, race, call, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actions, actionTypes, selectors} from '@neos-project/neos-ui-redux-store'; @@ -54,8 +53,8 @@ function * nodeCreationWorkflow(context, step = STEP_SELECT_NODETYPE, workflowDa } case STEP_NODE_CREATION_DIALOG: { const nodeType = nodeTypesRegistry.get(workflowData.nodeType); - const label = $get('label', nodeType); - const configuration = $get('ui.creationDialog', nodeType); + const label = nodeType?.label; + const configuration = nodeType?.ui?.creationDialog; if (configuration) { // // This node type has a creationDialog configuration, @@ -97,7 +96,9 @@ function * nodeCreationWorkflow(context, step = STEP_SELECT_NODETYPE, workflowDa const referenceNodeSelector = selectors.CR.Nodes.makeGetNodeByContextPathSelector(referenceNodeContextPath); const referenceNode = yield select(referenceNodeSelector); - const baseNodeType = yield select($get('ui.pageTree.filterNodeType')); + const baseNodeType = yield select( + state => state?.ui?.pageTree?.filterNodeType + ); const data = yield * applySaveHooksForTransientValuesMap(transientValues, saveHooksRegistry); return yield put(actions.Changes.persistChanges([{ diff --git a/packages/neos-ui-sagas/src/CR/NodeOperations/moveDroppedNode.js b/packages/neos-ui-sagas/src/CR/NodeOperations/moveDroppedNode.js index 4ce7528033..ee1225d5f0 100644 --- a/packages/neos-ui-sagas/src/CR/NodeOperations/moveDroppedNode.js +++ b/packages/neos-ui-sagas/src/CR/NodeOperations/moveDroppedNode.js @@ -1,5 +1,4 @@ import {takeEvery, put, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actions, actionTypes, selectors} from '@neos-project/neos-ui-redux-store'; @@ -11,7 +10,9 @@ export default function * moveDroppedNode() { const referenceNodeSelector = selectors.CR.Nodes.makeGetNodeByContextPathSelector(reference); const referenceNode = yield select(referenceNodeSelector); - const baseNodeType = yield select($get('ui.pageTree.filterNodeType')); + const baseNodeType = yield select( + state => state?.ui?.pageTree?.filterNodeType + ); yield put(actions.Changes.persistChanges([{ type: calculateChangeTypeFromMode(position, 'Move'), diff --git a/packages/neos-ui-sagas/src/CR/NodeOperations/pasteNode.js b/packages/neos-ui-sagas/src/CR/NodeOperations/pasteNode.js index 80dc6d8bfb..68f61691f3 100644 --- a/packages/neos-ui-sagas/src/CR/NodeOperations/pasteNode.js +++ b/packages/neos-ui-sagas/src/CR/NodeOperations/pasteNode.js @@ -1,5 +1,4 @@ import {takeEvery, put, select, call} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {selectors, actions, actionTypes} from '@neos-project/neos-ui-redux-store'; @@ -13,7 +12,9 @@ export default function * pasteNode({globalRegistry}) { yield takeEvery(actionTypes.CR.Nodes.PASTE, function * waitForPaste(action) { const subject = yield select(selectors.CR.Nodes.clipboardNodesContextPathsSelector); - const clipboardMode = yield select($get('cr.nodes.clipboardMode')); + const clipboardMode = yield select( + state => state?.cr?.nodes?.clipboardMode + ); const {contextPath: reference, fusionPath} = action.payload; const state = yield select(); @@ -38,7 +39,9 @@ export default function * pasteNode({globalRegistry}) { if (mode) { const referenceNodeSelector = selectors.CR.Nodes.makeGetNodeByContextPathSelector(reference); const referenceNode = yield select(referenceNodeSelector); - const baseNodeType = yield select($get('ui.pageTree.filterNodeType')); + const baseNodeType = yield select( + state => state?.ui?.pageTree?.filterNodeType + ); yield put(actions.CR.Nodes.commitPaste(clipboardMode)); const changes = subject.map(contextPath => ({ diff --git a/packages/neos-ui-sagas/src/CR/NodeOperations/reloadState.js b/packages/neos-ui-sagas/src/CR/NodeOperations/reloadState.js index d4cd62e4f2..b0f7a143ec 100644 --- a/packages/neos-ui-sagas/src/CR/NodeOperations/reloadState.js +++ b/packages/neos-ui-sagas/src/CR/NodeOperations/reloadState.js @@ -1,5 +1,5 @@ import {takeLatest, put, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; + import backend from '@neos-project/neos-ui-backend-connector'; import {selectors, actions, actionTypes} from '@neos-project/neos-ui-redux-store'; @@ -8,11 +8,15 @@ export default function * watchReloadState({configuration}) { yield takeLatest(actionTypes.CR.Nodes.RELOAD_STATE, function * reloadState(action) { const {q} = backend.get(); - const currentSiteNodeContextPath = yield select($get('cr.nodes.siteNode')); + const currentSiteNodeContextPath = yield select( + state => state?.cr?.nodes?.siteNode + ); const clipboardNodesContextPaths = yield select(selectors.CR.Nodes.clipboardNodesContextPathsSelector); - const toggledNodes = yield select($get('ui.pageTree.toggled')); - const siteNodeContextPath = $get('payload.siteNodeContextPath', action) || currentSiteNodeContextPath; - const documentNodeContextPath = yield $get('payload.documentNodeContextPath', action) || select($get('cr.nodes.documentNode')); + const toggledNodes = yield select( + state => state?.ui?.pageTree?.toggled + ); + const siteNodeContextPath = action?.payload?.siteNodeContextPath || currentSiteNodeContextPath; + const documentNodeContextPath = yield action?.payload?.documentNodeContextPath || select(state => state?.cr?.nodes?.documentNode); yield put(actions.CR.Nodes.setDocumentNode(documentNodeContextPath, currentSiteNodeContextPath)); yield put(actions.UI.PageTree.setAsLoading(currentSiteNodeContextPath)); const nodes = yield q([siteNodeContextPath, documentNodeContextPath]).neosUiDefaultNodes( @@ -22,14 +26,14 @@ export default function * watchReloadState({configuration}) { clipboardNodesContextPaths ).getForTree(); const nodeMap = nodes.reduce((nodeMap, node) => { - nodeMap[$get('contextPath', node)] = node; + nodeMap[node?.contextPath] = node; return nodeMap; }, {}); yield put(actions.CR.Nodes.setState({ siteNodeContextPath, documentNodeContextPath, nodes: nodeMap, - merge: $get('payload.merge', action) + merge: action?.payload?.merge })); yield put(actions.UI.PageTree.setAsLoaded(currentSiteNodeContextPath)); }); diff --git a/packages/neos-ui-sagas/src/CR/NodeOperations/removeNodeIfConfirmed.js b/packages/neos-ui-sagas/src/CR/NodeOperations/removeNodeIfConfirmed.js index 90751184a8..287f7dcd96 100644 --- a/packages/neos-ui-sagas/src/CR/NodeOperations/removeNodeIfConfirmed.js +++ b/packages/neos-ui-sagas/src/CR/NodeOperations/removeNodeIfConfirmed.js @@ -1,5 +1,4 @@ import {takeLatest, take, put, race, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actions, actionTypes} from '@neos-project/neos-ui-redux-store'; @@ -17,7 +16,7 @@ export default function * removeNodeIfConfirmed() { } if (nextAction.type === actionTypes.CR.Nodes.REMOVAL_CONFIRMED) { - const nodesToBeRemovedContextPath = $get('cr.nodes.toBeRemoved', state); + const nodesToBeRemovedContextPath = state?.cr?.nodes?.toBeRemoved; const changes = nodesToBeRemovedContextPath.map(nodeToBeRemovedContextPath => ({ type: 'Neos.Neos.Ui:RemoveNode', subject: nodeToBeRemovedContextPath diff --git a/packages/neos-ui-sagas/src/CR/Policies/index.js b/packages/neos-ui-sagas/src/CR/Policies/index.js index 726c7528e0..9afcb69118 100644 --- a/packages/neos-ui-sagas/src/CR/Policies/index.js +++ b/packages/neos-ui-sagas/src/CR/Policies/index.js @@ -1,5 +1,5 @@ import {select, take, put, fork} from 'redux-saga/effects'; -import {$get} from 'plow-js'; + import {actions, actionTypes, selectors} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -30,11 +30,11 @@ export function * watchNodeInformationChanges() { const nodesWithoutAdditionalMetadata = Object.keys(nodeMap).filter(contextPath => { const node = selectors.CR.Nodes.nodeByContextPath(state)(contextPath); - if ($get('properties._removed', node)) { + if (node?.properties?._removed) { return false; } - const policyInfo = $get('policy', node); + const policyInfo = node?.policy; return (!policyInfo); }); diff --git a/packages/neos-ui-sagas/src/Changes/index.js b/packages/neos-ui-sagas/src/Changes/index.js index 5bff7889d8..e9c7debb44 100644 --- a/packages/neos-ui-sagas/src/Changes/index.js +++ b/packages/neos-ui-sagas/src/Changes/index.js @@ -1,5 +1,4 @@ import {takeEvery, put, call, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -16,12 +15,12 @@ function * persistChanges(changes) { yield put(actions.ServerFeedback.handleServerFeedback(feedback)); const state = yield select(); - const isAutoPublishingEnabled = $get('user.settings.isAutoPublishingEnabled', state); + const isAutoPublishingEnabled = state?.user?.settings?.isAutoPublishingEnabled ?? false; if (isAutoPublishingEnabled) { const baseWorkspace = baseWorkspaceSelector(state); const publishableNodesInDocument = publishableNodesInDocumentSelector(state); - yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map($get('contextPath')), baseWorkspace)); + yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map(node => node?.contextPath), baseWorkspace)); } } catch (error) { console.error('Failed to persist changes', error); @@ -54,7 +53,7 @@ export function * watchPersist() { // If there's already a pending request, don't start the new one; // the data will be stored in `changes` closure and when the current request finishes saving // it will be re-triggered by FINISH_SAVING - if (changes.length > 0 && !$get('ui.remote.isSaving', state)) { + if (changes.length > 0 && !state?.ui?.remote?.isSaving) { // we need to clear out the changes array before yield, so the best I could think of is this const clonedChanges = changes.slice(0); changes = []; diff --git a/packages/neos-ui-sagas/src/Publish/index.js b/packages/neos-ui-sagas/src/Publish/index.js index 6822c2d301..117ad31628 100644 --- a/packages/neos-ui-sagas/src/Publish/index.js +++ b/packages/neos-ui-sagas/src/Publish/index.js @@ -1,5 +1,4 @@ import {put, call, select, takeEvery, takeLatest, take, race} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -30,11 +29,11 @@ export function * watchPublish() { export function * watchToggleAutoPublish() { yield takeEvery(actionTypes.User.Settings.TOGGLE_AUTO_PUBLISHING, function * publishInitially() { const state = yield select(); - const isAutoPublishingEnabled = $get('user.settings.isAutoPublishingEnabled', state); + const isAutoPublishingEnabled = state?.user?.settings?.isAutoPublishingEnabled; if (isAutoPublishingEnabled) { const publishableNodesInDocument = publishableNodesInDocumentSelector(state); - yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map($get('contextPath')), 'live')); + yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map(node => node?.contextPath), 'live')); } }); } @@ -43,7 +42,9 @@ export function * watchChangeBaseWorkspace() { const {changeBaseWorkspace} = backend.get().endpoints; yield takeEvery(actionTypes.CR.Workspaces.CHANGE_BASE_WORKSPACE, function * change(action) { try { - const documentNode = yield select($get('cr.nodes.documentNode')); + const documentNode = yield select( + state => state?.cr?.nodes?.documentNode + ); const feedback = yield call(changeBaseWorkspace, action.payload, documentNode); yield put(actions.ServerFeedback.handleServerFeedback(feedback)); @@ -71,7 +72,7 @@ export function * discardIfConfirmed() { if (nextAction.type === actionTypes.CR.Workspaces.DISCARD_CONFIRMED) { yield put(actions.UI.Remote.startDiscarding()); - const nodesToBeDiscarded = $get('cr.workspaces.toBeDiscarded', state); + const nodesToBeDiscarded = state?.cr?.workspaces?.toBeDiscarded; try { const currentContentCanvasContextPath = yield select(selectors.CR.Nodes.documentNodeContextPathSelector); diff --git a/packages/neos-ui-sagas/src/UI/ContentCanvas/index.js b/packages/neos-ui-sagas/src/UI/ContentCanvas/index.js index 3d8e11b011..6a24155440 100644 --- a/packages/neos-ui-sagas/src/UI/ContentCanvas/index.js +++ b/packages/neos-ui-sagas/src/UI/ContentCanvas/index.js @@ -1,6 +1,6 @@ import {delay} from 'redux-saga'; import {takeLatest, put, select, take, race} from 'redux-saga/effects'; -import {$get} from 'plow-js'; + import {getGuestFrameDocument} from '@neos-project/neos-ui-guest-frame/src/dom'; import {actionTypes, actions} from '@neos-project/neos-ui-redux-store'; @@ -11,9 +11,11 @@ import {actionTypes, actions} from '@neos-project/neos-ui-redux-store'; export function * watchNodeCreated() { yield takeLatest(actionTypes.UI.Remote.DOCUMENT_NODE_CREATED, function * nodeCreated(action) { const {contextPath} = action.payload; - const node = yield select($get(['cr', 'nodes', 'byContextPath', contextPath])); + const node = yield select( + state => state?.cr?.nodes?.byContextPath?.[contextPath] + ); yield put(actions.CR.Nodes.setDocumentNode(contextPath)); - yield put(actions.UI.ContentCanvas.setSrc($get('uri', node))); + yield put(actions.UI.ContentCanvas.setSrc(node?.uri)); }); } /** @@ -44,7 +46,9 @@ export function * watchStopLoading({globalRegistry, store}) { export function * watchReload() { yield takeLatest(actionTypes.UI.ContentCanvas.RELOAD, function * (action) { const {uri} = action.payload; - const currentIframeUrl = yield select($get('ui.contentCanvas.src')); + const currentIframeUrl = yield select( + state => state?.ui?.contentCanvas?.src + ); [].slice.call(document.querySelectorAll(`iframe[name=neos-content-main]`)).forEach(iframe => { const iframeWindow = iframe.contentWindow || iframe; @@ -65,7 +69,9 @@ export function * watchControlOverIFrame() { yield take(actionTypes.System.READY); while (true) { //eslint-disable-line - const src = yield select($get('ui.contentCanvas.src')); + const src = yield select( + state => state?.ui?.contentCanvas?.src + ); const waitForNextAction = yield race([ take(actionTypes.UI.ContentCanvas.SET_SRC), take(actionTypes.UI.ContentCanvas.REQUEST_REGAIN_CONTROL), diff --git a/packages/neos-ui-sagas/src/UI/ContentTree/index.js b/packages/neos-ui-sagas/src/UI/ContentTree/index.js index a68d024ac1..e597864db0 100644 --- a/packages/neos-ui-sagas/src/UI/ContentTree/index.js +++ b/packages/neos-ui-sagas/src/UI/ContentTree/index.js @@ -1,5 +1,4 @@ import {takeLatest, put, select, takeEvery} from 'redux-saga/effects'; -import {$get, $contains} from 'plow-js'; import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store'; import {isNodeCollapsed} from '@neos-project/neos-ui-redux-store/src/CR/Nodes/helpers'; @@ -17,7 +16,9 @@ export function * watchReloadTree({globalRegistry}) { yield put(actions.UI.ContentTree.startLoading()); - const documentNodeContextPath = yield select($get('cr.nodes.documentNode')); + const documentNodeContextPath = yield select( + state => state?.cr?.nodes?.documentNode + ); const self = yield q(documentNodeContextPath).get(); const directChildNodes = yield q(documentNodeContextPath).children(FILTER_BOTH).get(); const consecutiveChildNodes = yield q(directChildNodes).find(FILTER_BOTH).get(); @@ -34,7 +35,9 @@ export function * watchReloadTree({globalRegistry}) { export function * watchNodeFocus({configuration}) { yield takeLatest(actionTypes.CR.Nodes.FOCUS, function * loadContentNodeRootLine(action) { const {contextPath} = action.payload; - const documentNodeContextPath = yield select($get('cr.nodes.documentNode')); + const documentNodeContextPath = yield select( + state => state?.cr?.nodes?.documentNode + ); let parentContextPath = contextPath; @@ -51,11 +54,15 @@ export function * watchNodeFocus({configuration}) { // we reached the top level, where we need to abort the loop to avoid infinite spinning. break; } + + // eslint-disable-next-line require-atomic-updates parentContextPath = parentNode.parent; const getNodeByContextPathSelector = selectors.CR.Nodes.makeGetNodeByContextPathSelector(parentContextPath); const node = yield select(getNodeByContextPathSelector); - const isToggled = yield select($contains(parentContextPath, 'ui.contentTree.toggled')); + const isToggled = yield select( + state => state?.ui?.contentTree?.toggled?.includes(parentContextPath) + ); const isCollapsed = (node ? isNodeCollapsed(node, isToggled, documentNode, loadingDepth) : false); if (!node || isCollapsed) { @@ -71,20 +78,22 @@ export function * watchToggle({globalRegistry}) { const state = yield select(); const contextPath = action.payload; - const children = $get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state); + const children = state?.cr?.nodes?.byContextPath?.[contextPath]?.children; if (!children) { return; } const checkIfChildrenAreFullyLoadedRecursively = contextPath => { - return $get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state) - .filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'content') || nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'contentCollection')) - .every( + const children = state?.cr?.nodes?.byContextPath?.[contextPath]?.children; + + return children + ?.filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'content') || nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'contentCollection')) + ?.every( childEnvelope => - $get(['cr', 'nodes', 'byContextPath', $get('contextPath', childEnvelope)], state) && - checkIfChildrenAreFullyLoadedRecursively($get('contextPath', childEnvelope)) - ); + state?.cr?.nodes?.byContextPath?.[childEnvelope?.contextPath] && + checkIfChildrenAreFullyLoadedRecursively(childEnvelope?.contextPath) + ) ?? true; }; const childrenAreFullyLoaded = checkIfChildrenAreFullyLoadedRecursively(contextPath); @@ -120,7 +129,7 @@ export function * watchRequestChildrenForContextPath({globalRegistry}) { if (childNodes && parentNodes) { const nodes = parentNodes.concat(childNodes).reduce((nodeMap, node) => { - nodeMap[$get('contextPath', node)] = node; + nodeMap[node?.contextPath] = node; return nodeMap; }, {}); yield put(actions.CR.Nodes.merge(nodes)); @@ -142,11 +151,12 @@ export function * watchCurrentDocument({globalRegistry, configuration}) { } const state = yield select(); - const childrenAreFullyLoaded = $get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state) - .filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'content') || nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'contentCollection')) - .every( - childEnvelope => Boolean($get(['cr', 'nodes', 'byContextPath', $get('contextPath', childEnvelope)], state)) - ); + const children = state?.cr?.nodes?.byContextPath?.[contextPath]?.children; + const childrenAreFullyLoaded = children + ?.filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'content') || nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'contentCollection')) + ?.every( + childEnvelope => Boolean(state?.cr?.nodes?.byContextPath?.[childEnvelope?.contextPath]) + ) ?? true; if (!childrenAreFullyLoaded) { yield put(actions.UI.ContentTree.setAsLoading(contextPath)); @@ -159,7 +169,7 @@ export function * watchCurrentDocument({globalRegistry, configuration}) { [] ).get(); const nodeMap = nodes.reduce((nodeMap, node) => { - nodeMap[$get('contextPath', node)] = node; + nodeMap[node?.contextPath] = node; return nodeMap; }, {}); diff --git a/packages/neos-ui-sagas/src/UI/EditPreviewMode/index.js b/packages/neos-ui-sagas/src/UI/EditPreviewMode/index.js index d124e79c78..0807f4cfd4 100644 --- a/packages/neos-ui-sagas/src/UI/EditPreviewMode/index.js +++ b/packages/neos-ui-sagas/src/UI/EditPreviewMode/index.js @@ -1,5 +1,4 @@ import {takeLatest, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import {actionTypes} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -11,7 +10,9 @@ import {getGuestFrameWindow} from '@neos-project/neos-ui-guest-frame/src/dom'; export function * watchEditPreviewModesChanged() { yield takeLatest(actionTypes.UI.EditPreviewMode.SET, function * editPreviewModeSet(action) { const {editPreviewMode} = action.payload; - const currentIframeUrl = yield select($get('ui.contentCanvas.src')); + const currentIframeUrl = yield select( + state => state?.ui?.contentCanvas?.src + ); yield backend.get().endpoints.setUserPreferences('contentEditing.editPreviewMode', editPreviewMode); diff --git a/packages/neos-ui-sagas/src/UI/Impersonate/index.js b/packages/neos-ui-sagas/src/UI/Impersonate/index.js index fd4e5af537..755e2e21eb 100644 --- a/packages/neos-ui-sagas/src/UI/Impersonate/index.js +++ b/packages/neos-ui-sagas/src/UI/Impersonate/index.js @@ -2,7 +2,6 @@ import {put, call, takeEvery} from 'redux-saga/effects'; import {actionTypes, actions} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; -import {$get} from 'plow-js'; export function * impersonateRestore({globalRegistry}) { const {impersonateRestore} = backend.get().endpoints; @@ -18,9 +17,9 @@ export function * impersonateRestore({globalRegistry}) { yield takeEvery(actionTypes.User.Impersonate.RESTORE, function * restore(action) { try { const feedback = yield call(impersonateRestore, action.payload); - const originUser = $get('origin.accountIdentifier', feedback); - const user = $get('impersonate.accountIdentifier', feedback); - const status = $get('status', feedback); + const originUser = feedback?.origin?.accountIdentifier; + const user = feedback?.impersonate?.accountIdentifier; + const status = feedback?.status; const restoreMessage = i18nRegistry.translate( 'impersonate.success.restoreUser', diff --git a/packages/neos-ui-sagas/src/UI/Inspector/index.js b/packages/neos-ui-sagas/src/UI/Inspector/index.js index 499535c44d..922ee390d8 100644 --- a/packages/neos-ui-sagas/src/UI/Inspector/index.js +++ b/packages/neos-ui-sagas/src/UI/Inspector/index.js @@ -1,5 +1,4 @@ import {take, race, put, call, select} from 'redux-saga/effects'; -import {$get} from 'plow-js'; import escapeRegExp from 'lodash.escaperegexp'; import {findNodeInGuestFrame} from '@neos-project/neos-ui-guest-frame/src/dom'; @@ -9,7 +8,7 @@ import {applySaveHooksForTransientValue} from '../../Changes/saveHooks'; const getFocusedNode = selectors.CR.Nodes.focusedSelector; const getTransientInspectorValues = state => { - const values = $get(['ui', 'inspector', 'valuesByNodePath'], state); + const values = state?.ui?.inspector?.valuesByNodePath; return values; }; @@ -85,13 +84,13 @@ export function * inspectorSaga({globalRegistry}) { function * flushInspector(inspectorRegistry) { const state = yield select(); const focusedNode = getFocusedNode(state); - let focusedNodeFusionPath = $get('cr.nodes.focused.fusionPath', state); + let focusedNodeFusionPath = state?.cr?.nodes?.focused?.fusionPath; if (!focusedNodeFusionPath) { - const focusedDomNode = findNodeInGuestFrame($get('contextPath', focusedNode)); + const focusedDomNode = findNodeInGuestFrame(focusedNode?.contextPath); focusedNodeFusionPath = focusedDomNode && focusedDomNode.getAttribute('data-__neos-fusion-path'); } const transientInspectorValues = getTransientInspectorValues(state); - const transientInspectorValuesForFocusedNodes = $get([$get('contextPath', focusedNode)], transientInspectorValues); + const transientInspectorValuesForFocusedNodes = transientInspectorValues?.[focusedNode?.contextPath]; // // Accumulate changes to be persisted @@ -111,12 +110,12 @@ function * flushInspector(inspectorRegistry) { // const change = { type: 'Neos.Neos.Ui:Property', - subject: $get('contextPath', focusedNode), + subject: focusedNode?.contextPath, payload: { propertyName, value, nodeDomAddress: { - contextPath: $get('contextPath', focusedNode), + contextPath: focusedNode?.contextPath, fusionPath: focusedNodeFusionPath } } @@ -131,10 +130,10 @@ function * flushInspector(inspectorRegistry) { // Update uris of all nodes in state if uriPathSegment has been changed // if (propertyName === 'uriPathSegment') { - const oldValue = $get('properties.uriPathSegment', focusedNode); + const oldValue = focusedNode?.properties?.uriPathSegment; const newValue = transientValue.value; if (oldValue !== newValue) { - const oldUri = $get('uri', focusedNode); + const oldUri = focusedNode?.uri; const oldUriFragment = oldUri.split('@')[0]; const newUriFragment = oldUriFragment.replace(new RegExp(escapeRegExp(oldValue) + '$'), newValue); yield put(actions.CR.Nodes.updateUri(oldUriFragment, newUriFragment)); diff --git a/packages/neos-ui-sagas/src/UI/PageTree/index.js b/packages/neos-ui-sagas/src/UI/PageTree/index.js index f53fb0b699..8260df6bdb 100644 --- a/packages/neos-ui-sagas/src/UI/PageTree/index.js +++ b/packages/neos-ui-sagas/src/UI/PageTree/index.js @@ -1,5 +1,4 @@ import {takeLatest, takeEvery, put, select} from 'redux-saga/effects'; -import {$get, $contains} from 'plow-js'; import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; @@ -12,11 +11,12 @@ export function * watchToggle({globalRegistry}) { const state = yield select(); const {contextPath} = action.payload; - const childrenAreFullyLoaded = $get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state) - .filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'document')) - .every( - childEnvelope => Boolean($get(['cr', 'nodes', 'byContextPath', $get('contextPath', childEnvelope)], state)) - ); + const children = state?.cr?.nodes?.byContextPath?.[contextPath]?.children; + const childrenAreFullyLoaded = children + ?.filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'document')) + ?.every( + childEnvelope => Boolean(state?.cr?.nodes?.byContextPath?.[childEnvelope?.contextPath]) + ) ?? true; if (!childrenAreFullyLoaded) { yield put(actions.UI.PageTree.requestChildren(contextPath)); @@ -49,7 +49,7 @@ export function * watchRequestChildrenForContextPath({configuration}) { if (childNodes && parentNodes) { const nodes = parentNodes.concat(childNodes).reduce((nodeMap, node) => { - nodeMap[$get('contextPath', node)] = node; + nodeMap[node?.contextPath] = node; return nodeMap; }, {}); @@ -104,6 +104,7 @@ export function * watchCurrentDocument({configuration}) { return; } + // eslint-disable-next-line require-atomic-updates parentContextPath = parentNode.parent; const getNodeByContextPathSelector = selectors.CR.Nodes.makeGetNodeByContextPathSelector(parentContextPath); let node = yield select(getNodeByContextPathSelector); @@ -113,7 +114,7 @@ export function * watchCurrentDocument({configuration}) { yield put(actions.UI.PageTree.setAsLoading(siteNodeContextPath)); const nodes = yield q(parentContextPath).get(); yield put(actions.CR.Nodes.merge(nodes.reduce((nodeMap, node) => { - nodeMap[$get('contextPath', node)] = node; + nodeMap[node?.contextPath] = node; return nodeMap; }, {}))); node = yield select(getNodeByContextPathSelector); @@ -121,7 +122,9 @@ export function * watchCurrentDocument({configuration}) { } // Calculate if the given node is collapsed, and if so the uncollapse it - const isToggled = yield select($contains(parentContextPath, 'ui.pageTree.toggled')); + const isToggled = yield select( + state => state?.ui?.pageTree?.toggled?.includes(parentContextPath) + ); const isCollapsed = isNodeCollapsed(node, isToggled, siteNode, loadingDepth); if (isCollapsed) { yield put(actions.UI.PageTree.toggle(parentContextPath)); @@ -160,9 +163,15 @@ export function * watchSearch({configuration}) { if (filterNodeType || searchQuery) { matchingNodes = yield query.search(searchQuery, effectiveFilterNodeType).getForTreeWithParents(); } else { - const clipboardNodeContextPath = yield select($get('cr.nodes.clipboard')); - const toggledNodes = yield select($get('ui.pageTree.toggled')); - const documentNodeContextPath = yield select($get('cr.nodes.documentNode')); + const clipboardNodeContextPath = yield select( + state => state?.cr?.nodes?.clipboard + ); + const toggledNodes = yield select( + state => state?.ui?.pageTree?.toggled + ); + const documentNodeContextPath = yield select( + state => state?.cr?.nodes?.documentNode + ); matchingNodes = yield q([contextPath, documentNodeContextPath]).neosUiDefaultNodes( configuration.nodeTree.presets.default.baseNodeType, @@ -182,7 +191,7 @@ export function * watchSearch({configuration}) { if (matchingNodes.length > 0) { const nodes = matchingNodes.reduce((map, node) => { - map[$get('contextPath', node)] = node; + map[node?.contextPath] = node; return map; }, {}); diff --git a/yarn.lock b/yarn.lock index 744e671b32..16e21f2c46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3940,7 +3940,6 @@ __metadata: "@neos-project/neos-ui-redux-store": "workspace:*" lodash.escaperegexp: ^4.1.2 mousetrap: ^1.6.3 - plow-js: ^2.2.0 redux-saga: ^0.15.0 redux-saga-test-plan: ^3.6.0 typescript: ^4.6.4 From 171e8d0ea78e4e8b9a0a10bdf1e82fc59e72754b Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Fri, 23 Dec 2022 13:53:33 +0100 Subject: [PATCH 02/15] TASK: Remove plow-js from `@neos-project/neos-ui-backend-connector` --- packages/neos-ui-backend-connector/package.json | 3 +-- packages/neos-ui-backend-connector/src/FlowQuery/index.ts | 8 ++++---- yarn.lock | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/neos-ui-backend-connector/package.json b/packages/neos-ui-backend-connector/package.json index d81d8909c5..23c17ec64e 100644 --- a/packages/neos-ui-backend-connector/package.json +++ b/packages/neos-ui-backend-connector/package.json @@ -19,8 +19,7 @@ }, "dependencies": { "@neos-project/neos-ts-interfaces": "workspace:*", - "@neos-project/utils-helpers": "workspace:*", - "plow-js": "^2.2.0" + "@neos-project/utils-helpers": "workspace:*" }, "license": "GNU GPLv3", "jest": { diff --git a/packages/neos-ui-backend-connector/src/FlowQuery/index.ts b/packages/neos-ui-backend-connector/src/FlowQuery/index.ts index e9bf7a2a7b..cdd23eb7f7 100644 --- a/packages/neos-ui-backend-connector/src/FlowQuery/index.ts +++ b/packages/neos-ui-backend-connector/src/FlowQuery/index.ts @@ -1,5 +1,5 @@ import * as operations from './Operations/index'; -import {$get} from 'plow-js'; + import fetchWithErrorHandling from '../FetchWithErrorHandling/index'; import {Node, NodeContextPath, ContextProperties} from '@neos-project/neos-ts-interfaces'; import {Routes} from '../Endpoints'; @@ -33,7 +33,7 @@ export const createNodeEnvelope = (node: NodeEnvelope | NodeContextPath) => { let contextPath = ''; if (typeof node === 'object') { - contextPath = $get(['contextPath'], node) || $get(['$node'], node); + contextPath = node?.contextPath || node?.$node; } else if (typeof node === 'string') { contextPath = node; } @@ -103,8 +103,8 @@ export default (routes: Routes) => { // const q = (context: ContextProperties | string, ignoreMiddleware: boolean = false) => { let finalContext: NodeContextPath[]; - if (typeof context === 'object' && typeof $get(['contextPath'], context) === 'string') { - finalContext = [$get(['contextPath'], context) as string]; + if (typeof context === 'object' && typeof context?.contextPath === 'string') { + finalContext = [context?.contextPath as string]; } else if (typeof context === 'string') { finalContext = [context]; } else if (Array.isArray(context)) { diff --git a/yarn.lock b/yarn.lock index 16e21f2c46..575df3e36b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3670,7 +3670,6 @@ __metadata: "@neos-project/jest-preset-neos-ui": "workspace:*" "@neos-project/neos-ts-interfaces": "workspace:*" "@neos-project/utils-helpers": "workspace:*" - plow-js: ^2.2.0 typescript: ^4.6.4 languageName: unknown linkType: soft From a8493411323294cd974d42b0317ec4affd7c951e Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Fri, 23 Dec 2022 15:41:52 +0100 Subject: [PATCH 03/15] TASK: Remove plow-js from `@neos-project/neos-ui-ckeditor5-bindings` --- .../neos-ui-ckeditor5-bindings/package.json | 3 +- .../src/EditorToolbar/LinkButton.js | 20 ++-- .../src/EditorToolbar/TableDropDown.js | 3 +- .../src/EditorToolbar/index.js | 9 +- .../src/manifest.config.js | 76 ++++++------ .../src/manifest.richtextToolbar.js | 112 +++++++++--------- yarn.lock | 1 - 7 files changed, 112 insertions(+), 112 deletions(-) diff --git a/packages/neos-ui-ckeditor5-bindings/package.json b/packages/neos-ui-ckeditor5-bindings/package.json index 60b57e4dc2..0a23f0ad4d 100644 --- a/packages/neos-ui-ckeditor5-bindings/package.json +++ b/packages/neos-ui-ckeditor5-bindings/package.json @@ -30,8 +30,7 @@ "@neos-project/utils-helpers": "workspace:*", "classnames": "^2.2.3", "lodash.debounce": "^4.0.8", - "lodash.omit": "^4.5.0", - "plow-js": "^2.2.0" + "lodash.omit": "^4.5.0" }, "peerDependencies": { "prop-types": "^15.5.10", diff --git a/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/LinkButton.js b/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/LinkButton.js index a11ed9afb0..0e0152a674 100644 --- a/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/LinkButton.js +++ b/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/LinkButton.js @@ -1,7 +1,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {connect} from 'react-redux'; -import {$get, $transform} from 'plow-js'; + import LinkInput from '@neos-project/neos-ui-editors/src/Library/LinkInput'; import {IconButton} from '@neos-project/react-ui-components'; @@ -10,8 +10,8 @@ import {selectors, actions} from '@neos-project/neos-ui-redux-store'; import style from './LinkButton.css'; -@connect($transform({ - isOpen: selectors.UI.ContentCanvas.isLinkEditorOpen +@connect(state => ({ + isOpen: selectors.UI.ContentCanvas.isLinkEditorOpen(state) }), { toggle: actions.UI.ContentCanvas.toggleLinkEditor }) @@ -35,7 +35,7 @@ export default class LinkButton extends PureComponent { handleLinkButtonClick = () => { if (this.props.isOpen) { - if ($get('link', this.props.formattingUnderCursor) !== undefined) { + if (this.props.formattingUnderCursor?.link !== undefined) { // We need to remove all attributes before unsetting the link this.props.executeCommand('linkTitle', false, false); this.props.executeCommand('linkRelNofollow', false, false); @@ -87,7 +87,7 @@ export default class LinkButton extends PureComponent { {isOpen ? (
this.handleClick(item.commandName)} > - + {this.props.i18nRegistry.translate(item.label)} ) :