/* * Axelor Business Solutions * * Copyright (C) 2005-2019 Axelor (). * * 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 . */ (function() { "use strict"; var ui = angular.module('axelor.ui'); ui.RefFieldCtrl = RefFieldCtrl; function RefFieldCtrl($scope, $element, DataSource, ViewService, initCallback) { var field = $scope.getViewDef($element), params = { model: field.target || $element.attr('x-target'), views: field.views || {}, domain: field.domain, context: field.context }, views = {}; if (field.jsonTarget) { params.context = _.extend({}, params.context, { jsonModel: field.jsonTarget }); } if (!$element.is('fieldset')) { _.each(field.views, function(view){ views[view.type] = view; }); var formView = null, gridView = null, summaryView = null; if (field.summaryView === "" || field.summaryView === "true") { summaryView = views.form; } if (field.gridView) { gridView = { type: 'grid', name: field.gridView }; } if (field.formView) { formView = { type: 'form', name: field.formView }; } if (field.summaryView === "" || field.summaryView === "true") { summaryView = views.form || formView || { type: 'form' }; } else if (field.summaryView) { summaryView = { type: "form", name: field.summaryView }; } views.form = formView || views.form; views.grid = gridView || views.grid; params.summaryView = angular.copy(summaryView); params.summaryViewDefault = params.summaryView || views.form; params.views = _.compact([views.grid, views.form]); $scope._viewParams = params; } ui.ViewCtrl($scope, DataSource, ViewService); $scope.ngModel = null; $scope.editorCanSave = true; $scope.editorCanReload = field.canReload; if (initCallback) { initCallback.call(this); } var editor = null; var selector = null; var embedded = null; $scope.createNestedEditor = function() { return null; }; /** * Show/Hide the nested editor according to the show parameter, if * undefined then toggle. * */ $scope.showNestedEditor = function showNestedEditor(show) { if (!params.summaryView) { return; } if (embedded === null) { embedded = $scope.createNestedEditor(); } var es = embedded.data('$scope'); if (es !== null) { es.visible = (show === undefined ? !es.visible : show); embedded.toggle(es.visible); } return embedded; }; $scope.showPopupEditor = function(record) { if (!record && this.isReadonly()) { return; } if (editor == null) { editor = ViewService.compile('
')($scope); editor.data('$target', $element); } var popup = editor.isolateScope(); popup.show(record); popup._afterPopupShow = function() { if (record == null) { popup.$broadcast("on:new"); } }; }; function _showEditor(record) { if (!$scope._isPopup && field.editWindow === "blank" && record && record.id > 0) { var checkVersion = "" + axelor.config["view.form.check-version"]; var context = ($scope.selectedTab || {}).context || {}; if (context.__check_version !== undefined) { checkVersion = "" + context.__check_version; } var tab = { action: _.uniqueId('$act'), title: field.title, model: field.target, recordId: record.id, views: [{ type: 'form', name: field.formView }, { type: 'grid', name: field.gridView }] }; if (checkVersion) { tab.context = { __check_version: checkVersion }; } return $scope.$root.openTab(tab); } if ($scope.editorCanReload && record && record.id) { var parent = $scope.$parent; if (parent && parent.canSave()) { var opts = { callOnSave: field.callOnSave }; return parent.onSave(opts).then(function(){ $scope.showPopupEditor(record); }); } } return $scope.showPopupEditor(record); } $scope.showEditor = function(record) { var perm = record ? "read" : "create"; var id = (record||{}).id; if (perm === 'read' && (!id || id < 0)) { return _showEditor(record); } return $scope.isPermitted(perm, record, function(){ _showEditor(record); }); }; $scope.parentReload = function() { var parent = $scope.$parent; if (parent) { parent.reload(); } }; $scope.showSelector = function() { if (this.isReadonly()) { return; } function doShow() { if (selector == null) { selector = $('
').attr('x-select-mode', $scope.selectMode || "multi"); selector = ViewService.compile(selector)($scope); selector.data('$target', $element); } var popup = selector.isolateScope(); popup._domain = $scope._domain; // make sure that popup uses my domain (#1233) popup.show(); } var onSelect = this.$events.onSelect; if (onSelect) { onSelect().then(function(){ doShow(); }); } else { doShow(); } }; $scope.$on("on:edit", function(record){ var domain = ($scope.field||field).domain; var context = ($scope.field||field).context; if (domain !== undefined) $scope._domain = domain; if (context !== undefined) $scope._context = context; }); $scope.setDomain = function(domain, context) { if (domain !== undefined) $scope._domain = domain; if (context !== undefined) $scope._context = context; }; $scope.getDomain = function() { return { _domain: $scope._domain, _context: $scope._context }; }; var fetchDS = (function () { var fds = null; return function () { if (fds) return fds; var ds = $scope._dataSource; return fds = DataSource.create(ds._model, { domain: ds._domain, context: ds._context }); }; })(); $scope.fetchData = function(value, success) { var records = $.makeArray(value), ids = []; _.each(records, function(item) { if (_.isNumber(item)) { return ids.push(item); } if (_.isNumber(item.id) && item.id > 0 && _.isUndefined(item.version) && _.isUndefined(item.$fetched)) { return ids.push(item.id); } }); if (ids.length === 0) { return success(value); } var fields = $scope.selectFields(); function doFetch(view) { var domain = "self.id in (:_field_ids)"; var context = _.pick($scope.getContext(), ['id', '_model']); var sortBy = view.sortBy || view.orderBy; if (sortBy) { sortBy = sortBy.split(","); } if (view.canMove && fields.indexOf('sequence') === -1) { fields.push('sequence'); } context._field = field.name; context._field_ids = ids; return fetchDS().search({ fields: fields, sortBy: fetchDS()._sortBy || sortBy, archived: true, limit: -1, domain: domain, context: context }).success(function(records, page){ // only edited records should have version property var items = _.map(records, function(item){ item.$version = item.version; item.$fetched = false; delete item.version; return item; }); success(items, page); }); } if ($scope.isHidden()) { return doFetch($scope.view || {}); } return $scope._viewPromise.then(function(view) { return doFetch(view || {}); }); }; $scope.fetchSelection = function(request, response) { var fn = fetchSelection.bind(this); var onSelect = this.$events.onSelect; if (onSelect) { return onSelect(true).then(function() { return fn(request, response); }); } return fn(request, response); }; function fetchSelection(request, response) { /* jshint validthis: true */ var field = this.field; var nameField = field.targetName || 'id', fields = field.targetSearch || [], filter = {}, limit = field.limit || (axelor.device.small ? 6 : 10), sortBy = field.orderBy; fields = ["id", nameField].concat(fields); fields = _.chain(fields).compact().unique().value(); _.each(fields, function(name){ if (name !== "id" && request.term) { filter[name] = request.term; } }); var domain = this._domain, context = this._context; if (domain !== undefined && this.getContext) { context = _.extend({}, context, this.getContext()); } if (sortBy) { sortBy = sortBy.split(","); } var params = { filter: filter, fields: fields, sortBy: sortBy, limit: limit }; if (domain !== undefined) { params.domain = domain; params.context = context; } fetchDS().search(params).success(function(records, page){ var trKey = '$t:' + nameField; var items = _.map(records, function(record) { return { label: record[trKey] || record[nameField], value: record }; }); response(items, page); }); } $scope.createOnTheFly = function (term, popup, onSaveCallback) { var field = $scope.field; var targetFields = null; var requiredFields = (field.create||"").split(/,\s*/); function createItem(fields, term, popup) { var ds = $scope._dataSource, data = { $forceDirty: true }, missing = false; _.each(fields, function(field) { if (field.name === "name") return data["name"] = term; if (field.name === "code") return data["code"] = term; if (field.nameColumn) return data[field.name] = term; if (requiredFields.indexOf(field.name) > -1) { return data[field.name] = term; } if (field.required) { missing = true; } }); if (popup || missing || _.isEmpty(data)) { return $scope.showPopupEditor(data); } return ds.save(data).success(onSaveCallback); } if (targetFields) { return createItem(targetFields, term, popup); } return $scope.loadView("form").success(function(fields, view){ targetFields = fields; return createItem(fields, term, popup); }); }; $scope.attachTagEditor = function attachTagEditor(scope, element, attrs) { var field = scope.field; var input = null; if (!field.target) { return; } function onTagEdit(e, item) { var elem = $(e.target); var field = scope.field; var value = item[field.targetName]; function onKeyDown(e) { // enter key if (e.keyCode === 13) { item[field.targetName] = input.val(); saveAndSelect(item); hideEditor(); } // escape if (e.keyCode === 27) { hideEditor(); } } function hideEditor(forceSave) { $(document).off('mousedown.tag-editor'); $(input).off('keydown.tag-editor').hide(); if (forceSave && value !== input.val()) { item[field.targetName] = input.val(); saveAndSelect(item); } } if (input === null) { input = $('').appendTo(element); } input.val(value) .width(element.width() - 6) .show().focus() .position({ my: 'left top', at: 'left+3 top+3', of: element }); $(input).on('keydown.tag-editor', onKeyDown); $(document).on('mousedown.tag-editor', function (e) { if (!input.is(e.target)) { hideEditor(true); } }); } function saveAndSelect(record) { var ds = scope._dataSource; var data = _.extend({}, record, { version: record.version || record.$version }); ds.save(data).success(function (rec) { scope.select(rec); }); } scope.onTagEdit = onTagEdit; }; $scope.canSelect = function() { var canSelect = $scope.attr('canSelect'); if (canSelect !== undefined) return canSelect; if ($scope.selectEnable !== undefined) return $scope.selectEnable; return true; }; $scope.canNew = function() { return $scope.attr('canNew') !== false; }; $scope.canEdit = function() { return !$scope.isReadonly(); }; $scope.canView = function() { return $scope.attr('canView') !== false; }; $scope.canRemove = function() { return $scope.attr('canRemove') !== false; }; $scope.select = function(value) { }; $scope.onNew = function() { $scope.showEditor(null); }; $scope.onEdit = function() { }; $scope.onSelect = function() { $scope.showSelector(); }; $scope.onRemove = function() { }; var hasPermission = $scope.hasPermission; $scope.hasPermission = function(perm) { if (hasPermission && !hasPermission.apply($scope, arguments)) { return false; } if (!field.perms) return true; var perms = field.perms; var permitted = perms[perm]; if (!permitted) { return false; } return true; }; } })();