Skip to content

Commit

Permalink
FEATURE: Load content node children on toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebobo committed Jul 23, 2021
1 parent c80b7cf commit 7353580
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 4 deletions.
30 changes: 27 additions & 3 deletions packages/neos-ui-redux-store/src/UI/ContentTree/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import * as selectors from './selectors';
export interface State extends Readonly<{
toggled: NodeContextPath[];
isLoading: boolean;
loading: NodeContextPath[];
errors: NodeContextPath[];
}> {}

export const defaultState: State = {
toggled: [],
isLoading: false
isLoading: false,
loading: [],
errors: []
};

//
Expand All @@ -23,13 +27,19 @@ export enum actionTypes {
TOGGLE = '@neos/neos-ui/UI/ContentTree/TOGGLE',
START_LOADING = '@neos/neos-ui/UI/ContentTree/START_LOADING',
STOP_LOADING = '@neos/neos-ui/UI/ContentTree/STOP_LOADING',
RELOAD_TREE = '@neos/neos-ui/UI/ContentTree/RELOAD_TREE'
RELOAD_TREE = '@neos/neos-ui/UI/ContentTree/RELOAD_TREE',
REQUEST_CHILDREN = '@neos/neos-ui/UI/ContentTree/REQUEST_CHILDREN',
SET_AS_LOADING = '@neos/neos-ui/UI/ContentTree/SET_AS_LOADING',
SET_AS_LOADED = '@neos/neos-ui/UI/ContentTree/SET_AS_LOADED',
}

const toggle = (contextPath: NodeContextPath) => createAction(actionTypes.TOGGLE, contextPath);
const startLoading = () => createAction(actionTypes.START_LOADING);
const stopLoading = () => createAction(actionTypes.STOP_LOADING);
const reloadTree = () => createAction(actionTypes.RELOAD_TREE);
const requestChildren = (contextPath: NodeContextPath, {unCollapse = true, activate = false} = {}) => createAction(actionTypes.REQUEST_CHILDREN, {contextPath, opts: {unCollapse, activate}});
const setAsLoading = (contextPath: NodeContextPath) => createAction(actionTypes.SET_AS_LOADING, {contextPath});
const setAsLoaded = (contextPath: NodeContextPath) => createAction(actionTypes.SET_AS_LOADED, {contextPath});

//
// Export the actions
Expand All @@ -38,7 +48,10 @@ export const actions = {
toggle,
startLoading,
stopLoading,
reloadTree
reloadTree,
requestChildren,
setAsLoading,
setAsLoaded
};

export type Action = ActionType<typeof actions>;
Expand All @@ -65,6 +78,17 @@ export const reducer = (state: State = defaultState, action: InitAction | Action
}
break;
}
case actionTypes.SET_AS_LOADING: {
const contextPath = action.payload.contextPath;
draft.errors = draft.errors.filter(i => i !== contextPath);
draft.loading.push(contextPath);
break;
}
case actionTypes.SET_AS_LOADED: {
const contextPath = action.payload.contextPath;
draft.loading = draft.loading.filter(i => i !== contextPath);
break;
}
}
});

Expand Down
68 changes: 67 additions & 1 deletion packages/neos-ui-sagas/src/UI/ContentTree/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {takeLatest, put, select} from 'redux-saga/effects';
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';
Expand Down Expand Up @@ -63,3 +63,69 @@ export function * watchNodeFocus({configuration}) {
}
});
}

export function * watchToggle({globalRegistry}) {
const nodeTypesRegistry = globalRegistry.get('@neos-project/neos-ui-contentrepository');
yield takeLatest(actionTypes.UI.ContentTree.TOGGLE, function * toggleTreeNode(action) {
const state = yield select();
const contextPath = action.payload;

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))
);

if (!childrenAreFullyLoaded) {
yield put(actions.UI.ContentTree.requestChildren(contextPath));
}
});
}

export function * watchRequestChildrenForContextPath({globalRegistry}) {
yield takeEvery(actionTypes.UI.ContentTree.REQUEST_CHILDREN, function * requestChildrenForContextPath(action) {
// TODO: Call yield put(actions.UI.ContentTree.requestChildren(contextPath));
const nodeTypesRegistry = globalRegistry.get('@neos-project/neos-ui-contentrepository');
const {contextPath, opts} = action.payload;
const {activate} = opts;
const {q} = backend.get();
let parentNodes;
let childNodes;
yield put(actions.UI.ContentTree.setAsLoading(contextPath));

try {
const query = q(contextPath);

parentNodes = yield query.getForTree();

const nodeTypeFilter = `${nodeTypesRegistry.getRole('contentCollection')},${nodeTypesRegistry.getRole('content')}`;
childNodes = yield query.neosUiFilteredChildren(nodeTypeFilter).getForTree();
} catch (err) {
yield put(actions.UI.ContentTree.invalidate(contextPath));
yield put(actions.UI.FlashMessages.add('loadChildNodesError', err.message, 'error'));
}

yield put(actions.UI.ContentTree.setAsLoaded(contextPath));

if (childNodes && parentNodes) {
const nodes = parentNodes.concat(childNodes).reduce((nodeMap, node) => {
nodeMap[$get('contextPath', node)] = node;
return nodeMap;
}, {});

// The nodes loaded from the server for the tree representation are NOT the full
// nodes with all properties; but merely contain as little properties as needed
// for the tree.
// In order to not OVERRIDE the properties we already know, we need to merge
// the data which the nodes already in the system; and not override them completely.
yield put(actions.CR.Nodes.merge(nodes));

//
// ToDo: Set the ContentCanvas src / contextPath
//
if (activate) {
yield put(actions.UI.ContentTree.focus(contextPath));
}
}
});
}
2 changes: 2 additions & 0 deletions packages/neos-ui-sagas/src/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ manifest('main.sagas', {}, globalRegistry => {

sagasRegistry.set('neos-ui/UI/ContentTree/watchNodeFocus', {saga: uiContentTree.watchNodeFocus});
sagasRegistry.set('neos-ui/UI/ContentTree/watchReloadTree', {saga: uiContentTree.watchReloadTree});
sagasRegistry.set('neos-ui/UI/ContentTree/watchToggle', {saga: uiContentTree.watchToggle});
sagasRegistry.set('neos-ui/UI/ContentTree/watchRequestChildrenForContextPath', {saga: uiContentTree.watchRequestChildrenForContextPath});

sagasRegistry.set('neos-ui/UI/EditPreviewMode/watchEditPreviewModesChanged', {saga: uiEditPreviewMode.watchEditPreviewModesChanged});

Expand Down

0 comments on commit 7353580

Please sign in to comment.