Files
ERP/sophal/js/form/form.input.json.js

432 lines
12 KiB
JavaScript

/*
* Axelor Business Solutions
*
* Copyright (C) 2005-2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
(function() {
"use strict";
var ui = angular.module('axelor.ui');
ui.formWidget('PanelJson', {
showTitle: false,
transclude: true,
template: "<div class='panel-json' ui-transclude></div>"
});
ui.formInput('JsonField', 'String', {
showTitle: false,
link: function (scope, element, attrs, model) {
var field = scope.field;
var jsonFields = field.jsonFields || [];
var jsonNames = _.pluck(jsonFields, 'name');
var jsonFix = {};
jsonFields.forEach(function (item) {
if (item.widget && item.showTitle === undefined) {
var widget = ui.getWidgetDef(item.widget);
if (widget) {
item.showTitle = widget.showTitle;
}
}
});
var defaultValues = {};
var parentUnwatch = null;
var selfUnwatch = null;
scope.formPath = scope.formPath ? scope.formPath + "." + field.name : field.name;
scope.record = {};
jsonFields.forEach(function (item) {
if (item.target === 'com.axelor.meta.db.MetaJsonRecord' &&
item.targetName && item.targetName.indexOf('attrs.') === 0) {
jsonFix[item.name] = function (v) {
if (v) {
v[item.targetName.substring(6)] = v[item.targetName];
}
return v;
};
}
if (item.contextField && item.contextFieldValue) {
if (item.showIf === undefined && item.hideIf === undefined && item.hidden) {
return;
}
var condition = "($record." + item.contextField + ".id === " + item.contextFieldValue + ")";
if (item.showIf) condition += " && (" + item.showIf + ")";
if (item.hideIf) condition += " && !(" + item.hideIf + ")";
item.showIf = condition;
item.hideIf = null;
}
});
function getDefaultValues() {
jsonFields.forEach(function (item) {
if (item.defaultValue === undefined) return;
var value = item.defaultValue;
switch(item.type) {
case 'integer':
value = +(value);
break;
case 'date':
case 'datetime':
value = value === 'now' ? new Date() : moment(value).toDate();
break;
}
defaultValues[item.name] = value;
});
return angular.copy(defaultValues);
}
function unwatchParent() {
if (parentUnwatch) {
parentUnwatch();
parentUnwatch = null;
}
}
function unwatchSelf() {
if (selfUnwatch) {
selfUnwatch();
selfUnwatch = null;
}
}
function watchParent() {
unwatchParent();
parentUnwatch = scope.$watch('$parent.record.' + field.name, function jsonParentWatch(value, old) {
if (value === old) return;
onRender();
});
}
function watchSelf() {
unwatchSelf();
selfUnwatch = scope.$watch('record', function jsonRecordWatch(record, old) {
if (record !== old) {
onUpdate();
}
}, true);
}
function format(name, value) {
var func = jsonFix[name];
return func ? func(value) : value;
}
function onUpdate() {
var rec = null;
_.each(scope.record, function (v, k) {
if (k.indexOf('$') === 0 || v === null || v === undefined) return;
if (_.isArray(v)) {
if (v.length == 0) return;
v = v.map(function (x) {
return x.id ? { id: x.id } : x;
});
}
if (rec === null) {
rec = {};
}
rec[k] = format(k, v);
});
unwatchParent();
if (scope.$parent.record[field.name] || rec) {
scope.$parent.record[field.name] = rec ? angular.toJson(rec) : rec;
}
watchParent();
}
function onRender() {
var record = scope.$parent.record || {};
var value = record[field.name];
unwatchSelf();
if (value) {
scope.record = angular.fromJson(value);
} else {
scope.record = getDefaultValues();
if (!_.isEmpty(scope.record)) {
record[field.name] = angular.toJson(scope.record);
}
onUpdate();
}
scope._jsonContext = { '$record': record };
record['$' + field.name] = scope.record;
watchSelf();
}
scope.$on('on:new', onRender);
scope.$on('on:edit', function () {
if (scope.viewType === 'form' || (!scope.viewType && scope._isPopup)) onRender();
});
scope.updateJsonValues = function (values) {
var rec = null;
_.each(values, function (v, k) {
if (jsonNames.indexOf(k) === -1 && scope.fields[k]) {
scope.$parent.record[k] = v;
} else {
if (rec === null) {
rec = {};
}
rec[k] = v;
}
});
if (rec) {
scope.record = _.extend({}, scope.record, rec);
}
};
watchParent();
// hide parent panel if no jsonFields defined
scope.$evalAsync(function () {
var parent = scope.$parent.field || {};
if (parent.type === 'panel' && _.size(parent.items) === 1 && _.isEmpty(field.jsonFields)) {
element.parents('.panel:first').addClass('hide').hide();
}
});
scope.$on('on:update-context', function (e, context) {
if (context && !context[field.name]) {
context[field.name] = angular.toJson(scope.record || {});
}
});
}
});
ui.formInput('JsonRaw', 'String', {
showTitle: false,
link: function (scope, element, attrs, model) {
scope.placeHolderKey = _t('name');
scope.placeHolderVal = _t('value');
scope.items = [];
scope.onAdd = function () {
var last = _.last(scope.items);
if (last && !(_.trim(last.name) && _.trim(last.value))) return;
scope.items.push({});
};
scope.onRemove = function (index) {
if (scope.items.length > 0) {
scope.items.splice(index, 1);
}
};
var unwatch = null;
function doWatch () {
if (unwatch) {
unwatch();
}
unwatch = scope.$watch('items', function jsonItemsWatch(items, old) {
if (items === old) return;
var record = null;
_.each(items, function (item) {
if (!_.trim(item.name) || !_.trim(item.value)) return;
if (record === null) {
record = {};
}
record[item.name] = item.value;
});
model.$setViewValue(record ? angular.toJson(record) : null);
}, true);
}
model.$render = function () {
var value = model.$viewValue;
if (value) {
value = angular.fromJson(value);
} else {
value = {};
}
scope.items = _.map(_.keys(value), function (name) {
return { name: name, value: value[name] || '' };
});
doWatch();
};
},
template_readonly:
"<div class='json-editor'>" +
"<table class='form-layout'>" +
"<tr ng-repeat='(i, item) in items'>" +
"<td class='form-label'>" +
"<strong class='display-text'>{{item.name}}</strong>:" +
"</td>" +
"<td class='form-item'>" +
"<span class='display-text'>{{item.value}}</span>" +
"</td>" +
"</tr>" +
"</table>" +
"</div>",
template_editable:
"<div class='json-editor'>" +
"<table class='form-layout'>" +
"<tr ng-repeat='(i, item) in items'>" +
"<td class='form-item'><span class='form-item-container'>" +
"<input type='text' placeholder='{{placeHolderKey}}' ng-model='item.name'></span>" +
"</td>" +
"<td class='form-item'><span class='form-item-container'>" +
"<input type='text' placeholder='{{placeHolderVal}}' ng-model='item.value'></span>" +
"</td>" +
"<td><a href='' ng-click='onRemove(i)'><i class='fa fa-minus'></i></a></td>" +
"</tr>" +
"</table>" +
"<a href='' ng-click='onAdd()'><i class='fa fa-plus'></i></a>" +
"</div>"
});
ui.formInput('JsonRefSelect', {
css: 'multi-object-select',
controller: ['$scope', 'ViewService', function($scope, ViewService) {
$scope.createElement = function(id, name, selectionList) {
var elemGroup = $('<div ui-group ui-table-layout cols="2" x-widths="150,*"></div>');
var elemSelect = $('<input ui-select showTitle="false">')
.attr("name", name + "$model")
.attr("x-for-widget", id)
.attr("ng-model", "record." + name + ".model");
var elemSelects = $('<div></div>').attr('ng-switch', "record." + name + ".model");
var elemItems = _.map(selectionList, function(s) {
return $('<input ui-json-ref-item ng-switch-when="' + s.value +'">')
.attr('ng-model', 'record.' + name)
.attr('name', name)
.attr('x-target', s.value);
});
elemGroup
.append($('<div></div>').append(elemSelect))
.append(elemSelects.append(elemItems));
return ViewService.compile(elemGroup)($scope);
};
}],
link: function(scope, element, attrs, model) {
this._super.apply(this, arguments);
var name = scope.field.name;
var selectionList = scope.field.selectionList;
scope.fieldsCache = {};
scope.refFireEvent = function (name) {
var handler = scope.$events[name];
if (handler) {
return handler();
}
};
var elem = scope.createElement(element.attr('id'), name, selectionList);
setTimeout(function() {
element.append(elem);
});
scope.$watch("record." + name + ".model", function jsonModelWatch(value, old) {
if (value === old || old === undefined) return;
if (scope.record && scope.record[name]) {
scope.record[name] = _.pick(scope.record[name], 'model');
if (!scope.record[name].model) {
delete scope.record[name];
}
}
});
},
template_editable: null,
template_readonly: null
});
ui.formInput('JsonRefItem', 'ManyToOne', {
showTitle: false,
link: function(scope, element, attrs, model) {
this._super.apply(this, arguments);
if (scope.field.targetName) {
return this._link.apply(this, arguments);
}
var self = this;
var target = element.attr('x-target');
var data = (_.findWhere(scope.$parent.field.selectionList, {value: target})||{}).data || {};
function doLink(fields) {
var name = false,
search = [];
_.each(fields, function(f) {
if (f.nameColumn) name = f.name;
if (f.name === "name") search.push("name");
if (f.name === "code") search.push("code");
});
if (!name && _.contains(search, "name")) {
name = "name";
}
_.extend(scope.field, {
target: scope._model,
targetName: name,
targetSearch: search,
domain: data.domain
});
self._link(scope, element, attrs, model);
}
if (scope.fieldsCache[scope._model]) {
doLink(scope.fieldsCache[scope._model]);
} else {
scope.loadFields().success(function (fields) {
scope.fieldsCache[scope._model] = fields;
doLink(fields);
});
}
},
_link: function(scope, element, attrs, model) {
var name = element.attr('name');
scope.getValue = function () {
return scope.record[name];
};
var __setValue = scope.setValue;
scope.setValue = function (value) {
var val = _.pick(scope.record[name], 'model');
val = _.extend(val, value);
__setValue.call(scope, val);
};
function doSelect() {
var value = (scope.record || {})[name];
scope.select(value);
}
scope.$watch("record", doSelect);
}
});
})();