Esempio n. 1
0
/**
 * Toggles the right sidebar out/in of the users viewport.
 */
const toggle = createAction(TOGGLE);

//
// Export the actions
//
export const actions = {
    toggle
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: payload => $set(
        'ui.rightSideBar',
        fromJSOrdered($get('ui.rightSideBar', payload) ? $get('ui.rightSideBar', payload) : {isHidden: false})
    ),
    [TOGGLE]: () => $toggle('ui.rightSideBar.isHidden')
});

//
// Export the selectors
//
export const selectors = {
    isHidden: $get('ui.rightSideBar.isHidden')
};
Esempio n. 2
0
    TOGGLE
};

/**
 * Toggles the edit mode panel's visibility.'
 */
const toggle = createAction(TOGGLE);

//
// Export the actions
//
export const actions = {
    toggle
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: payload => $set(
        'ui.editModePanel',
        Immutable.fromJS($get('ui.editModePanel', payload) ? $get('ui.editModePanel', payload) : {isHidden: true})
    ),
    [TOGGLE]: () => $toggle('ui.editModePanel.isHidden')
});

//
// Export the selectors
//
export const selectors = {};
Esempio n. 3
0
//
// Export the actions
//
export const actions = {
    toggle,
    startLoading,
    stopLoading,
    reloadTree
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: () => $set(
        'ui.contentTree',
        new Map({
            toggled: new Set(),
            isLoading: false
        })
    ),
    [START_LOADING]: () => $set('ui.contentTree.isLoading', true),
    [STOP_LOADING]: () => $set('ui.contentTree.isLoading', false),
    [TOGGLE]: ({contextPath}) => $toggle('ui.contentTree.toggled', contextPath)
});

//
// Export the selectors
//
export {selectors};
Esempio n. 4
0
import {Map} from 'immutable';
import {$set, $get} from 'plow-js';

import {handleActions} from '@neos-project/utils-redux';
import {actionTypes as system} from '../../System/index';

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'user.name',
        new Map({
            title: $get('user.name.title', state) || '',
            firstName: $get('user.name.firstName', state) || '',
            middleName: $get('user.name.middleName', state) || '',
            lastName: $get('user.name.lastName', state) || '',
            otherName: $get('user.name.otherName', state) || '',
            fullName: $get('user.name.fullName', state) || ''
        })
    )
});

//
// Export the selectors
//
export const selectors = {};
Esempio n. 5
0
//
// Export the actions
//
export const actions = {
    toggle,
    hide,
    toggleMenuGroup
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'ui.drawer',
        new Map({
            isHidden: $get('ui.drawer.isHidden', state) ? $get('ui.drawer.isHidden', state) : false,
            collapsedMenuGroups: $get('ui.drawer.collapsedMenuGroups', state) ? $get('ui.drawer.collapsedMenuGroups', state) : ['content']
        })
    ),
    [TOGGLE]: () => $toggle('ui.drawer.isHidden'),
    [HIDE]: () => $set('ui.drawer.isHidden', true),
    [TOGGLE_MENU_GROUP]: ({menuGroup}) => $toggle('ui.drawer.collapsedMenuGroups', menuGroup)
});

//
// Export the selectors
//
export const selectors = {};
Esempio n. 6
0
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'ui.addNodeModal',
        new Map({
            contextPath: '',
            fusionPath: '',
            toggledGroups: $get('ui.addNodeModal.toggledGroups', state) ? $get('ui.addNodeModal.toggledGroups', state) : []
        })
    ),
    [OPEN]: ({contextPath, fusionPath}) => {
        if (typeof contextPath !== 'string') {
            throw new Error(errorMessages.ERROR_INVALID_CONTEXTPATH);
        }
        if (typeof fusionPath !== 'string') {
            throw new Error(errorMessages.ERROR_INVALID_FUSIONPATH);
        }

        return $all(
            $set('ui.addNodeModal.contextPath', contextPath),
            $set('ui.addNodeModal.fusionPath', fusionPath)
        );
    },
    [CLOSE]: () => $all(
        $set('ui.addNodeModal.contextPath', ''),
        $set('ui.addNodeModal.fusionPath', '')
    ),
    [TOGGLE_GROUP]: groupId => $toggle('ui.addNodeModal.toggledGroups', groupId)
});
Esempio n. 7
0
    TOGGLE
};

/**
 * Toggles the fullscreen mode on/off.
 */
const toggle = createAction(TOGGLE);

//
// Export the actions
//
export const actions = {
    toggle
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: payload => $set(
        'ui.fullScreen',
        fromJSOrdered($get('ui.fullScreen', payload) ? $get('ui.fullScreen', payload) : {isFullScreen: false})
    ),
    [TOGGLE]: () => $toggle('ui.fullScreen.isFullScreen')
});

//
// Export the selectors
//
export const selectors = {};
Esempio n. 8
0
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'cr.nodes',
        new Map({
            byContextPath: Immutable.fromJS($get('cr.nodes.byContextPath', state)) || new Map(),
            siteNode: $get('cr.nodes.siteNode', state) || '',
            focused: new Map({
                contextPath: '',
                fusionPath: ''
            }),
            toBeRemoved: '',
            clipboard: ''
        })
    ),
    [ADD]: ({nodeMap}) => $all(
        ...Object.keys(nodeMap).map(contextPath => $set(
            ['cr', 'nodes', 'byContextPath', contextPath],
            Immutable.fromJS(
                //
                // the data is passed from *the guest iFrame*. Because of this, at least in Chrome, Immutable.fromJS() does not do anything;
                // as the object has a different prototype than the default "Object". For this reason, we need to JSON-encode-and-decode
                // the data, to scope it relative to *this* frame.
                //
                JSON.parse(JSON.stringify(nodeMap[contextPath]))
            )
        ))
    ),
    [MERGE]: ({nodeMap}) => $all(
        ...Object.keys(nodeMap).map(contextPath => $merge(
            ['cr', 'nodes', 'byContextPath', contextPath],
            Immutable.fromJS(
                //
                // the data is passed from *the guest iFrame*. Because of this, at least in Chrome, Immutable.fromJS() does not do anything;
                // as the object has a different prototype than the default "Object". For this reason, we need to JSON-encode-and-decode
                // the data, to scope it relative to *this* frame.
                //
                JSON.parse(JSON.stringify(nodeMap[contextPath]))
            )
        ))
    ),
    [FOCUS]: ({contextPath, fusionPath}) => $set('cr.nodes.focused', new Map({contextPath, fusionPath})),
    [UNFOCUS]: () => $set('cr.nodes.focused', new Map({
        contextPath: '',
        fusionPath: ''
    })),
    [COMMENCE_REMOVAL]: contextPath => $set('cr.nodes.toBeRemoved', contextPath),
    [REMOVAL_ABORTED]: () => $set('cr.nodes.toBeRemoved', ''),
    [REMOVAL_CONFIRMED]: () => $set('cr.nodes.toBeRemoved', ''),
    [REMOVE]: contextPath => $drop(['cr', 'nodes', 'byContextPath', contextPath]),
    [COPY]: contextPath => $set('cr.nodes.clipboard', contextPath),
    [CUT]: contextPath => $set('cr.nodes.clipboard', contextPath),
    [PASTE]: () => $set('cr.nodes.clipboard', ''),
    [HIDE]: contextPath => $set(['cr', 'nodes', 'byContextPath', contextPath, 'properties', '_hidden'], true),
    [SHOW]: contextPath => $set(['cr', 'nodes', 'byContextPath', contextPath, 'properties', '_hidden'], false),
    [UPDATE_URI]: ({oldUriFragment, newUriFragment}) => state => {
        const allNodes = $get('cr.nodes.byContextPath', state);
        return $all(
            ...allNodes.map(node => {
                const nodeUri = $get('uri', node);
                if (
                    nodeUri &&
                    // Make sure to not include false positives by checking that the given segment ends either with "/" or "@"
                    (nodeUri.includes(oldUriFragment + '/') || nodeUri.includes(oldUriFragment + '@'))
                ) {
                    const contextPath = $get('contextPath', node);
                    return $set(
                        ['cr', 'nodes', 'byContextPath', contextPath, 'uri'],
                        nodeUri
                            // node with changes uriPathSegment
                            .replace(oldUriFragment + '@', newUriFragment + '@')
                            // descendant of a node with changed uriPathSegment
                            .replace(oldUriFragment + '/', newUriFragment + '/')
                    );
                }
                return null;
            }).filter(i => i).toArray(),
            state
        );
    }
});
Esempio n. 9
0
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'cr.nodes',
        new Map({
            byContextPath: fromJSOrdered($get('cr.nodes.byContextPath', state)) || new Map(),
            siteNode: $get('cr.nodes.siteNode', state) || '',
            focused: new Map({
                contextPath: '',
                fusionPath: ''
            }),
            toBeRemoved: '',
            clipboard: $get('cr.nodes.clipboard', state) || '',
            clipboardMode: $get('cr.nodes.clipboardMode', state) || ''
        })
    ),
    [ADD]: ({nodeMap}) => $all(
        ...Object.keys(nodeMap).map(contextPath => $set(
            ['cr', 'nodes', 'byContextPath', contextPath],
            fromJSOrdered(
                //
                // the data is passed from *the guest iFrame*. Because of this, at least in Chrome, fromJSOrdered() does not do anything;
                // as the object has a different prototype than the default "Object". For this reason, we need to JSON-encode-and-decode
                // the data, to scope it relative to *this* frame.
                //
                JSON.parse(JSON.stringify(nodeMap[contextPath]))
            )
        ))
    ),
    [MOVE]: ({nodeToBeMoved: sourceNodeContextPath, targetNode: targetNodeContextPath, position}) => state => {
        // Determine base node into which we'll be inserting
        let baseNodeContextPath;
        if (position === 'into') {
            baseNodeContextPath = targetNodeContextPath;
        } else {
            baseNodeContextPath = parentNodeContextPath(targetNodeContextPath);
        }

        const sourceNodeParentContextPath = parentNodeContextPath(sourceNodeContextPath);
        const originalSourceChildren = $get(['cr', 'nodes', 'byContextPath', sourceNodeParentContextPath, 'children'], state);
        const sourceIndex = originalSourceChildren.findIndex(child => $get('contextPath', child) === sourceNodeContextPath);
        const childRepresentationOfSourceNode = originalSourceChildren.get(sourceIndex);

        let processedChildren = $get(['cr', 'nodes', 'byContextPath', baseNodeContextPath, 'children'], state);

        const transformations = [];
        if (sourceNodeParentContextPath === baseNodeContextPath) {
            // If moving into the same parent, delete source node from it
            processedChildren = processedChildren.delete(sourceIndex);
        } else {
            // Else add an extra transformation to delete the source node from its parent
            const processedSourceChildren = originalSourceChildren.delete(sourceIndex);
            transformations.push($set(['cr', 'nodes', 'byContextPath', sourceNodeParentContextPath, 'children'], processedSourceChildren));
        }

        // Add source node to the children of the base node, at the right position
        if (position === 'into') {
            processedChildren = processedChildren.push(childRepresentationOfSourceNode);
        } else {
            const targetIndex = processedChildren.findIndex(child => $get('contextPath', child) === targetNodeContextPath);
            const insertIndex = position === 'before' ? targetIndex : targetIndex + 1;
            processedChildren = processedChildren.insert(insertIndex, childRepresentationOfSourceNode);
        }
        transformations.push($set(['cr', 'nodes', 'byContextPath', baseNodeContextPath, 'children'], processedChildren));

        // Run all transformations
        return $all(...transformations, state);
    },
    [MERGE]: ({nodeMap}) => $all(
        ...Object.keys(nodeMap).map(contextPath => $merge(
            ['cr', 'nodes', 'byContextPath', contextPath],
            fromJSOrdered(
                //
                // the data is passed from *the guest iFrame*. Because of this, at least in Chrome, fromJSOrdered() does not do anything;
                // as the object has a different prototype than the default "Object". For this reason, we need to JSON-encode-and-decode
                // the data, to scope it relative to *this* frame.
                //
                JSON.parse(JSON.stringify(nodeMap[contextPath]))
            )
        )),
        ...Object.keys(nodeMap).filter(contextPath => nodeMap[contextPath].children !== undefined).map(contextPath => $set(
            ['cr', 'nodes', 'byContextPath', contextPath, 'children'],
            fromJSOrdered(
                //
                // the data is passed from *the guest iFrame*. Because of this, at least in Chrome, fromJSOrdered() does not do anything;
                // as the object has a different prototype than the default "Object". For this reason, we need to JSON-encode-and-decode
                // the data, to scope it relative to *this* frame.
                //
                JSON.parse(JSON.stringify(nodeMap[contextPath].children))
            )
        )),
        ...Object.keys(nodeMap).filter(contextPath => nodeMap[contextPath].matchesCurrentDimensions !== undefined).map(contextPath => $set(
            ['cr', 'nodes', 'byContextPath', contextPath, 'matchesCurrentDimensions'],
            nodeMap[contextPath].matchesCurrentDimensions
        )),
    ),
    [FOCUS]: ({contextPath, fusionPath}) => state => $all(
        $set('cr.nodes.focused', new Map({contextPath, fusionPath})),
        // Set currentlyEditedPropertyName to currentlyEditedPropertyNameIntermediate and clear out currentlyEditedPropertyNameIntermediate
        // This is needed because SET_CURRENTLY_EDITED_PROPERTY_NAME if fired before SET_FOCUS, but we still want to clear out currentlyEditedPropertyName
        // when SET_FOCUS is triggered not from inline
        $set('ui.contentCanvas.currentlyEditedPropertyName', $get('ui.contentCanvas.currentlyEditedPropertyNameIntermediate', state)),
        $set('ui.contentCanvas.currentlyEditedPropertyNameIntermediate', ''),
        state
    ),
    [UNFOCUS]: () => $set('cr.nodes.focused', new Map({
        contextPath: '',
        fusionPath: ''
    })),
    [COMMENCE_REMOVAL]: contextPath => $set('cr.nodes.toBeRemoved', contextPath),
    [REMOVAL_ABORTED]: () => $set('cr.nodes.toBeRemoved', ''),
    [REMOVAL_CONFIRMED]: () => $set('cr.nodes.toBeRemoved', ''),
    [REMOVE]: contextPath => $drop(['cr', 'nodes', 'byContextPath', contextPath]),
    [SET_STATE]: ({siteNodeContextPath, documentNodeContextPath, nodes, merge}) => $all(
        $set('cr.nodes.siteNode', siteNodeContextPath),
        $set('ui.contentCanvas.contextPath', documentNodeContextPath),
        $set('cr.nodes.focused', new Map({
            contextPath: '',
            fusionPath: ''
        })),
        merge ? $merge('cr.nodes.byContextPath', fromJSOrdered(nodes)) : $set('cr.nodes.byContextPath', fromJSOrdered(nodes))
    ),
    [COPY]: contextPath => $all(
        $set('cr.nodes.clipboard', contextPath),
        $set('cr.nodes.clipboardMode', 'Copy')
    ),
    [CUT]: contextPath => $all(
        $set('cr.nodes.clipboard', contextPath),
        $set('cr.nodes.clipboardMode', 'Move')
    ),
    [COMMIT_PASTE]: clipboardMode => state => {
        if (clipboardMode === 'Move') {
            return $all(
                $set('cr.nodes.clipboard', ''),
                $set('cr.nodes.clipboardMode', ''),
                state
            );
        }
        return state;
    },
    [HIDE]: contextPath => $set(['cr', 'nodes', 'byContextPath', contextPath, 'properties', '_hidden'], true),
    [SHOW]: contextPath => $set(['cr', 'nodes', 'byContextPath', contextPath, 'properties', '_hidden'], false),
    [UPDATE_URI]: ({oldUriFragment, newUriFragment}) => state => {
        const allNodes = $get('cr.nodes.byContextPath', state);
        return $all(
            ...allNodes.map(node => {
                const nodeUri = $get('uri', node);
                if (
                    nodeUri &&
                    // Make sure to not include false positives by checking that the given segment ends either with "/" or "@"
                    (nodeUri.includes(oldUriFragment + '/') || nodeUri.includes(oldUriFragment + '@'))
                ) {
                    const contextPath = $get('contextPath', node);
                    return $set(
                        ['cr', 'nodes', 'byContextPath', contextPath, 'uri'],
                        nodeUri
                            // Node with changes uriPathSegment
                            .replace(oldUriFragment + '@', newUriFragment + '@')
                            // Descendant of a node with changed uriPathSegment
                            .replace(oldUriFragment + '/', newUriFragment + '/')
                    );
                }
                return null;
            }).filter(i => i).toArray(),
            state
        );
    }
});
Esempio n. 10
0
//
// Export the action types
//
export const actionTypes = {
};

//
// Export the actions
//
export const actions = {
};

//
// Export the reducer
//
export const reducer = handleActions({});

const contextForNodeLinking = createSelector(
    [
        $get('cr.workspaces.personalWorkspace.name'),
        $get('cr.nodes.siteNode'),
        $get('cr.contentDimensions.active')
    ],
    (
        activeWorkspace,
        siteNodePath,
        activeContentDimensions
    ) => {
        return fromJSOrdered({
            workspaceName: activeWorkspace,
            contextNode: siteNodePath,
Esempio n. 11
0
//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: () => $set(
        'ui.inspector',
        new Map({
            valuesByNodePath: new Map()
        })
    ),
    [COMMIT]: ({propertyId, value, hooks}) => state => {
        const focusedNodePath = nodes.focusedNodePathSelector(state);
        const setValueForProperty = (data, state) =>
            $set(['ui', 'inspector', 'valuesByNodePath', focusedNodePath, propertyId], data, state);

        if (value !== null && hooks) {
            return setValueForProperty(Immutable.fromJS({value, hooks}), state);
        }

        if (value !== null) {
            return setValueForProperty(Immutable.fromJS({value}), state);
        }

        return $drop(['ui', 'inspector', 'valuesByNodePath', focusedNodePath, propertyId], state);
    },

    [DISCARD]: clearReducer,
    [CLEAR]: clearReducer
});

//
// Export the selectors
Esempio n. 12
0
import {map, keys} from 'ramda';

import {handleActions} from '@neos-project/utils-redux';

import * as ContentDimensions from './ContentDimensions/index';
import * as Images from './Images/index';
import * as Nodes from './Nodes/index';
import * as Workspaces from './Workspaces/index';

const all = {ContentDimensions, Images, Nodes, Workspaces};

//
// Export the actionTypes
//
export const actionTypes = map(a => a.actionTypes, all);

//
// Export the actions
//
export const actions = map(a => a.actions, all);

//
// Export the reducer
//
export const reducer = handleActions(map(k => all[k].reducer, keys(all)));

//
// Export the selectors
//
export const selectors = map(a => a.selectors, all);
Esempio n. 13
0
/**
 * Toggles the auto publishing mode for the current logged in user.
 */
const toggleAutoPublishing = createAction(TOGGLE_AUTO_PUBLISHING);

//
// Export the actions
//
export const actions = {
    toggleAutoPublishing
};

//
// Export the reducer
//
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'user.settings',
        new Map({
            isAutoPublishingEnabled: Boolean($get('user.settings.isAutoPublishingEnabled', state))
        })
    ),
    [TOGGLE_AUTO_PUBLISHING]: () => $toggle('user.settings.isAutoPublishingEnabled')
});

//
// Export the selectors
//
export const selectors = {};
Esempio n. 14
0
export const reducer = handleActions({
    [system.INIT]: () => $set(
        'ui.inspector',
        new Map({
            shouldPromptToHandleUnappliedChanges: false,
            secondaryInspectorIsOpen: false,
            valuesByNodePath: new Map()
        })
    ),
    [COMMIT]: ({propertyId, value, hooks}) => state => {
        const focusedNode = nodes.focusedSelector(state);
        const focusedNodePath = $get('contextPath', focusedNode);
        const currentPropertyValue = $get(['properties', propertyId], focusedNode);
        const setValueForProperty = (data, state) =>
            $set(['ui', 'inspector', 'valuesByNodePath', focusedNodePath, propertyId], data, state);
        const transientValueDiffers = (value !== null) && (value !== currentPropertyValue);

        if (transientValueDiffers && hooks) {
            return setValueForProperty(fromJSOrdered({value, hooks}), state);
        }

        if (transientValueDiffers) {
            return setValueForProperty(fromJSOrdered({value}), state);
        }

        return $drop(['ui', 'inspector', 'valuesByNodePath', focusedNodePath, propertyId], state);
    },

    [DISCARD]: clearReducer,
    [CLEAR]: clearReducer,
    [ESCAPE]: () => $set('ui.inspector.shouldPromptToHandleUnappliedChanges', true),
    [RESUME]: () => $set('ui.inspector.shouldPromptToHandleUnappliedChanges', false),

    [SECONDARY_OPEN]: () => $set('ui.inspector.secondaryInspectorIsOpen', true),
    [SECONDARY_CLOSE]: () => $set('ui.inspector.secondaryInspectorIsOpen', false),
    [SECONDARY_TOGGLE]: () => $toggle('ui.inspector.secondaryInspectorIsOpen')
});
Esempio n. 15
0
export const reducer = handleActions({
    [system.INIT]: state => $set(
        'ui.contentCanvas',
        new Map({
            contextPath: $get('ui.contentCanvas.contextPath', state) || '',
            previewUrl: '',
            src: $get('ui.contentCanvas.src', state) || '',
            formattingUnderCursor: new Map(),
            currentlyEditedPropertyName: '',
            currentlyEditedPropertyNameIntermediate: '',
            isLoading: true,
            focusedProperty: '',
            backgroundColor: $get('ui.contentCanvas.backgroundColor', state),
            shouldScrollIntoView: false
        })
    ),
    [SET_CONTEXT_PATH]: ({contextPath, siteNode}) => state => {
        if ($get('ui.contentCanvas.contextPath', state) !== contextPath) {
            // If context path changed, ensure to reset the "focused node". Otherwise, when switching
            // to different Document nodes and having a (content) node selected previously, the Inspector
            // does not properly refresh. We just need to ensure that everytime we switch pages, we
            // reset the focused (content) node of the page.
            state = $set('cr.nodes.focused', new Map({
                contextPath: '',
                fusionPath: ''
            }), state);
        }

        state = $set('ui.contentCanvas.contextPath', contextPath, state);

        if (siteNode) {
            // !! HINT: set site node in case it is defined in SET_CONTEXT_PATH; otherwise the dimension switcher does not work.
            state = $set('cr.nodes.siteNode', siteNode, state);
        }

        return state;
    },
    [SET_PREVIEW_URL]: ({previewUrl}) => $set('ui.contentCanvas.previewUrl', previewUrl),
    [SET_SRC]: ({src}) => $set('ui.contentCanvas.src', src),
    [FORMATTING_UNDER_CURSOR]: ({formatting}) => $set('ui.contentCanvas.formattingUnderCursor', new Map(formatting)),
    [SET_CURRENTLY_EDITED_PROPERTY_NAME]: ({propertyName}) => $all(
        $set('ui.contentCanvas.currentlyEditedPropertyName', propertyName),
        // See SET_FOCUS why it's needed
        $set('ui.contentCanvas.currentlyEditedPropertyNameIntermediate', propertyName)
    ),
    [STOP_LOADING]: () => $set('ui.contentCanvas.isLoading', false),
    [START_LOADING]: () => $set('ui.contentCanvas.isLoading', true),
    [REQUEST_SCROLL_INTO_VIEW]: activate => $set('ui.contentCanvas.shouldScrollIntoView', activate),
    [REQUEST_REGAIN_CONTROL]: () => $set('ui.contentCanvas.src', '')
});