taburetkin/marionette.yat

View on GitHub
coms/api/actorApiMixin.js

Summary

Maintainability
A
2 hrs
Test Coverage
import _ from 'underscore';
import ActorApi, { actorActions } from './actorApi';
import { comparator } from '../../utils/compare-utils';
import { isInstance } from '../../utils/is-utils';
import { AsyncResult } from 'asyncresult-js';

function normalizeActionContext(callContext, ac) {
    if (ac && ac._normalized) {
        return ac;
    }
    if (ac && isInstance(ac.action, ActorApi)) {
        let context = ac.context || callContext;
        if (_.isFunction(context)) {
            context = context.call(callContext, callContext);
        }

        ac.name = ac.action.name;
        if (ac.order == null) {
            ac.order = ac.action.order;
        }
        let apiAction = ac.action;
        ac.exec = (...args) => {
            return apiAction.exec(context, ...args);
        }
        ac.execAsync = (...args) => {
            return apiAction.execAsync(context, ...args);
        }
        ac._normalized = true;
        return ac;
    }
}
function createRawContext(arg, store) {
    if (isInstance(arg, ActorApi)) {
        return { action: arg };
    } else if (_.isString(arg) && isInstance(store[arg], ActorApi)) {
        return { action: store[arg] };
    } else if (_.isObject(arg)) {

        if (arg._normalized) return arg;

        let actionContext = _.clone(arg);
        if (isInstance(actionContext.action, ActorApi)) {
            return actionContext;
        }

        let action = store[actionContext.name];
        if (isInstance(action, ActorApi)) {
            actionContext.action = action;
            return actionContext;
        }
    }
}
function toActionContext(callContext, arg, store) {
    let rawAc = createRawContext(arg, store);
    return normalizeActionContext(callContext, rawAc);
}

export default Base => Base.extend({
    getApiActionsStore() {
        return actorActions;
    },
    _extractApiActionsFromStore() {
        if (!this.apiActions) return [];
        let actions = _.reduce(this.apiActions, (memo, action, key) => {
            let ac = this._toActionContext(action);
            if (ac) {
                memo.push(ac);
            }
            return memo;
        }, []);
        return actions;
    },
    _toActionContext(arg) {
        let store = this.getApiActionsStore();
        return toActionContext(this, arg, store);
    },
    getApiActions(options = {}) {
        let actions = this._extractApiActionsFromStore();
        let predicate = options.predicate;

        let founded = _.filter(actions, ac => (!predicate || predicate(ac)) && ac.action.isAvailable(options));
        if (options.sort) {
            founded.sort(comparator('action.order'))
        }
        return founded;
    },
    getApiAction(name, options = {}) {
        if (isInstance(name, ActorApi)) {
            return name.isAvailabe() && this._toActionContext(name);
        }
        if (name && isInstance(name.action, ActorApi)) {
            return name.action.isAvailabe() && this._toActionContext(name);
        }
        let predicate = ac => ac.name == name;
        if (options.predicate) {
            let givenPredicate = options.predicate;
            predicate = action => givenPredicate(action) && predicate(action);
        }
        options.predicate = predicate;
        let actions = this.getApiActions(options);
        return actions[0];
    },
    executeAction(arg, ...rest) {
        let action = this.getApiAction(arg);
        if (!action) {
            console.warn('executeAction failed on cid ' + this.cid, arg); //eslint-disable-line
            return;
        }
        return action.exec(...rest);
    },
    executeActionAsync(arg, ...rest) {
        let action = this.getApiAction(arg);
        if (!action) {
            console.warn('executeAction failed on cid ' + this.cid, arg); //eslint-disable-line
            return AsyncResult.fail('action:notfound');
        }
        return action.execAsync(...rest);
    },
});