Source: public/src/store/TreeNode.js

/** @module store/TreeNode */

import { ajax } from '../util';
import { types, flow, getRoot } from "mobx-state-tree";
import $ from 'jquery';
import { uuid } from 'react-aiot';

/**
 * The store holding general data for folders. The properties are read-only.
 * 
 * @see React AIOT TreeNode documentation for properties and defaults
 * @class TreeNode
 */
const TreeNode = types.model('RMLTreeNode', {
    id: types.identifier(types.union(types.string, types.number)),
    hash: '',
    className: types.optional(types.frozen),
    icon: types.optional(types.frozen),
    iconActive: types.optional(types.frozen),
    childNodes: types.optional(types.array(types.late(() => TreeNode))),
    title: types.frozen,
    count: 0,
    attr: types.optional(types.frozen),
    isTreeLinkDisabled: false,
    selected: false,
    $busy: false,
    $busyOrder: false,
    $droppable: true,
    $visible: true,
    $rename: false,
    $create: types.optional(types.frozen),
    contentCustomOrder: 0,
    lastOrderBy: '',
    orderAutomatically: false,
    //searchSelected: false,
    //expandedState: true,
    //displayChildren: true,
    //selectedIds: [],
    //onRenameClose: undefined,
    //onAddClose: undefined,
    //onSelect: undefined,
    //onNodePressF2: undefined,
    //onExpand: undefined,
    //onUlRef: undefined
    properties: types.optional(types.frozen),
    isQueried: true
}).actions(self => ({
    afterAttach() {
        getRoot(self)._afterAttachTreeNode(self);
    },
    
    beforeDestroy() {
        getRoot(self)._beforeDestroyTreeNode(self);
    },
    
    /**
     * Update this node attributes.
     * 
     * @param {function} callback The callback with one argument (node draft)
     * @param {boolean} [setHash] If true the hash node is changed so a rerender is forced
     * @memberof module:store/TreeNode~TreeNode
     * @instance
     */
    setter(callback, setHash = false) {
        callback(self);
        setHash && (self.hash = uuid());
    },
    
    /**
     * Rename folder.
     * 
     * @param {string} inputValue The new name
     * @returns {object} Server response
     * @throws Error
     * @memberof module:store/TreeNode~TreeNode
     * @instance
     * @async
     */
    setName: flow(function*(inputValue) {
        self.setter(node => { node.$busy = true });
        
        try {
            let result;
            const { id, name, cnt, children, ...rest } = result = yield ajax('folders/' + self.id, {
                method: 'PUT',
                data: {
                    name: inputValue
                }
            });
            self.setter(node => {
                node.title = name;
                node.properties = $.merge(node.properties, rest);
                node.$busy = false;
            });
            return result;
        } catch(e) {
            self.setter(node => { node.$busy = false }, self.id);
            throw e;
        }
    }),
    
    /**
     * Apply an order to the folder.
     * 
     * @param {string} id The sortable id
     * @param {boolean} [automatically=false] If true the order is applied automatically if new files are added to the folder
     * @memberof module:store/TreeNode~TreeNode
     * @instance
     * @async
     */
    applyOrder: flow(function*(id, automatically = false) {
        self.setter(node => { node.$busyOrder = true });
        
        try {
            const result = yield ajax('folders/content/sortables', {
                method: 'POST',
                data: {
                    id,
                    applyTo: self.id,
                    automatically
                }
            });
            result && id !== 'reindex' && id !== 'last' && (self.contentCustomOrder = 1, self.lastOrderBy = id);
            result && automatically && (self.orderAutomatically = true);
            id === 'original' && result && (self.contentCustomOrder = 0, 
                self.orderAutomatically = false);
            id === 'deactivate' && result && (self.orderAutomatically = false);
        }catch(e) {
            throw e;
        }finally{
            self.setter(node => { node.$busyOrder = false });
        }
    }), 
    
    /**
     * Permanently delete folder.
     * 
     * @returns {string|int} The parent id
     * @throws Error
     * @memberof module:store/TreeNode~TreeNode
     * @instance
     * @async
     */
    trash: flow(function*() {
        self.setter(node => { node.$busy = true });
        
        try {
            yield ajax('folders/' + self.id, {
                method: 'DELETE'
            });
            self.setter(node => { node.$visible = false });
        }catch(e) {
            throw e;
        }finally{
            self.setter(node => { node.$busy = false });
        }
    })
}));

export default TreeNode;