cmsmon
Version:
179 lines (165 loc) • 8.48 kB
JavaScript
;
const path = require('path');
const unless = require('express-unless');
const _ = require('lodash');
require('generator-bind').polyfill();
const JsonFn = require('json-fn');
module.exports = (cms) => {
cms.data.ngEn.push(ng => {
ng.angular.module('cms.main', [])
.directive('cmsElement', function ($compile, $rootScope) {
return {
restrict: "A",
// replace: true,
scope: {
path: '@cmsPath',
element: '=cmsElement'
},
controller: function ($scope) {
// expose api
this.getPath = () => `${$scope.path}.containers`;
this.getContainer = name => _.find($scope.element.containers, {name});
},
link: function (scope, element) {
if (!scope.model) {
$rootScope.fns.push({
fn: function*(scope, element) {
const {type, ref} = scope.element;
const {template, fn, serverFn, Model} = cms.Types[type];
let model = yield Model.findById(ref);
if (model) model = model.toJSON()
_.assign(scope, {model, fn, serverFn});
// process ServerFn
convertServerFn(serverFn, scope, $rootScope, serverFnData => {
$rootScope.typesBuilder.setServerFnData(type, serverFnData);
});
element.html(template);
$compile(element.contents())(scope);
$rootScope.typesBuilder.addElement(type, model);
}, args: [scope, element]
});
}
}
}
})
.directive('cmsContainer', function ($compile, $rootScope) {
return {
require: '^^?cmsElement',
restrict: "A",
// replace: true,
scope: {
name: '@cmsContainer'
},
template: `<div ng-repeat="element in elements" cms-element="element" cms-path="{{path}}.elements[{{$index}}]"></div>`,
link: function (scope, element, attrs, elementController) {
const elementPath = elementController ? elementController.getPath() : null;
scope.path = `${elementPath ? elementPath + '.' : ''}${scope.name}`;
const container = _.get($rootScope.containers, scope.path);
scope.elements = container ? container.elements : null;
if (!container) {
console.warn('there is no container');
}
}
}
})
.directive('cmsWrapper', function ($compile, $rootScope) {
return {
restrict: "A",
replace: true,
scope: {
name: '@cmsWrapper'
},
link: function (scope, element) {
if (cms.Wrapper.list[scope.name]) {
// programmatic wrapper (in code)
const {template, fn, serverFn} = cms.Wrapper.list[scope.name];
// scope.fn = fn;
convertServerFn(serverFn, scope, $rootScope, serverFnData => {
$rootScope.typesBuilder.setServerFnDataForWrapper(scope.name, serverFnData)
});
element.html(template);
$compile(element.contents())(scope);
} else {
// user created wrapper (in database)
$rootScope.fns.push({fn: processWrapper, args: [scope, element]});
}
function* processWrapper(scope, _element) {
const model = (yield cms.Types.Wrapper.Model.findOne({name: scope.name})).toJSON();
const {list, element, Fn} = model;
let template;
if (list) {
const {BindType, layout, query} = list;
// resolve list
yield* $rootScope.typesBuilder.getFullList(BindType);
if (layout) {
// use default element's template
scope.layout = layout;
template = `
<div ng-repeat="element in result track by $index">
<div cms-fragment="{{layout.ID}}" model="element"></div>
</div>
`
} else {
scope.e = {type: BindType}
template = `
<br>
<div ng-repeat="element in result track by $index">
<div cms-element="{type:type,ref:element._id}"></div>
</div>
`
}
} else if (!element.null) {
const {BindType, layout, model, query} = element;
_.assign(scope, {model, layout, type: BindType});
template = `<br><div cms-element="{type:type,ref:vm.element.element.model._id}"></div>`
}
_element.html(template);
$compile(_element.contents())(scope);
$rootScope.typesBuilder.addElement('Wrapper', model);
}
}
}
})
.config(['$compileProvider', function ($compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/.*/);
$compileProvider.aHrefSanitizationWhitelist(/.*/);
}]);
ng.angular.module('cms.editable', [])
.directive('cmsEditable', function ($compile, $rootScope) {
return {
restrict: "A",
replace: true,
scope: {
cmsEditable: '='
},
template: '<span>{{cmsEditable}}</span>'
}
})
ng._modules.push('cms.main', 'cms.editable');
})
function convertServerFn(serverFn, scope, $rootScope, cb) {
scope.serverFnData = [];
if (serverFn) {
scope.serverFn = {};
for (const k of Object.keys(serverFn)) {
scope.serverFn[k] = function () {
const args = _.map(arguments, v => v);
const data = _.find(scope.serverFnData, v => JSON.stringify(v.args) === JSON.stringify(args) && v.k === k);
if (!data) {
// put into memory to run later
scope.serverFnData.push({args, k});
$rootScope.fns.push({
fn: function*(args, k, serverFn, scope, cb) {
const data = _.find(scope.serverFnData, v => JSON.stringify(v.args) === JSON.stringify(args) && v.k === k);
data.result = yield* serverFn[k](...args);
if (cb) cb(scope.serverFnData);
}, args: [args, k, serverFn, scope, cb]
});
} else {
return data.result;
}
}
}
}
}
}