/* * 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.directive('uiDeleteButton', [function () { return { link: function (scope, element, attrs) { }, replace: true, template: "
" + "" + "" + "" + "
" }; }]); ui.directive('uiUpdateButton', ['$compile', function ($compile) { return { scope: { handler: '=' }, link: function (scope, element, attrs) { var menu = element.find('.update-menu'), toggleButton = null; scope.visible = false; scope.onMassUpdate = function (e) { if (menu && menu.is(':visible')) { hideMenu(); return; } toggleButton = $(e.currentTarget); toggleButton.addClass("active"); scope.onShow(e, menu); $(document).on('mousedown.update-menu', onMouseDown); scope.$applyAsync(function () { scope.visible = true; }); }; scope.onCancel = function () { hideMenu(); }; scope.canMassUpdate = function () { return true; }; if (scope.handler && scope.handler.canMassUpdate) { scope.canMassUpdate = scope.handler.canMassUpdate; } function hideMenu() { $(document).off('mousedown.update-menu', onMouseDown); if (toggleButton) { toggleButton.removeClass("active"); } scope.$applyAsync(function () { scope.visible = false; }); return menu.hide(); } function onMouseDown(e) { var all = $(menu).add(toggleButton); if (all.is(e.target) || all.has(e.target).length > 0) { return; } all = $('.ui-widget-overlay,.ui-datepicker:visible,.ui-dialog:visible,.ui-menu:visible'); if (all.is(e.target) || all.has(e.target).length > 0) { return; } if(menu){ hideMenu(); } } // append box after the button scope.$timeout(function () { element.parents('.view-container').after(menu); }); scope.$on('$destroy', function() { $(document).off('mousedown.update-menu', onMouseDown); if (menu) { menu.remove(); menu = null; } }); }, replace: true, template: "" }; }]); ui.directive('uiUpdateDummy', function () { return { require: '^uiUpdateForm', scope: { record: '=' }, controller: ['$scope', '$element', 'DataSource', 'ViewService', function($scope, $element, DataSource, ViewService) { var parent = $scope.$parent; var handler = parent.handler; $scope._viewParams = { model: handler._model, views: [] }; ui.ViewCtrl($scope, DataSource, ViewService); ui.FormViewCtrl.call(this, $scope, $element); function prepare(fields) { var schema = { cols: 1, type: 'form', items: _.values(fields) }; $scope.fields = fields; $scope.schema = schema; $scope.schema.loaded = true; } var initialized = false; $scope.show = function () { if (initialized) return; initialized = true; var unwatch = parent.$watch('fields', function massFieldsWatch(fields) { if (_.isEmpty(fields)) return; unwatch(); prepare(fields); }); }; $scope.setEditable(); $scope.show(); }], link: function (scope, element, attrs) { element.hide(); }, template: "
" }; }); ui.directive('uiUpdateForm', function () { function findFields(fields, items) { var all = {}; var accept = function (field) { var name = field.name; if (!field.massUpdate) return; if (/^(id|version|selected|archived|((updated|created)(On|By)))$/.test(name)) return; if (field.large || field.unique) return; switch (field.type) { case 'one-to-many': case 'many-to-many': case 'binary': return; } if (field.target) { field.canNew = false; field.canEdit = false; } field.hidden = false; field.required = false; field.readonly = false; field.onChange = null; field.placeholder = field.placeholder || field.title; all[name] = field; }; _.each(fields, function (field, name) { accept(field); }); _.each(items, function (item) { var field = fields[item.name]; if (field) { accept(_.extend({}, field, item, { type: field.type })); } }); return all; } return { replace: true, controller: ['$scope', 'ViewService', function ($scope, ViewService) { $scope.filters = [{}]; $scope.options = []; $scope.onInit = _.once(function (view) { var handler = $scope.handler; var promise = ViewService.getFields(handler._model); promise.success(function (fields) { $scope.fields = findFields(fields, view.items); $scope.options = _.sortBy(_.values($scope.fields), 'title'); $scope.record = {}; }); }); $scope.addFilter = function (filter) { var all = $scope.filters; var last = _.last(all); if (last && !last.field) return; if (all.length > 0 && all.length === $scope.options.length) return; $scope.filters.push(filter || {}); $scope.updateSelection(); }; $scope.removeFilter = function(filter) { var index = $scope.filters.indexOf(filter); if (index > -1) { $scope.filters.splice(index, 1); } if ($scope.filters.length === 0) { $scope.addFilter(); } }; $scope.notSelected = function (filter) { return function (opt) { return filter.field === opt.name || !opt.selected; }; }; var values = null; var canUpdate = false; function updateValues(record) { var keys = _.pluck($scope.filters, 'field'), vals = {}; _.each(keys, function (key) { if (key) { vals[key] = (record || {})[key]; if (vals[key] === undefined) { vals[key] = null; } } }); values = vals; canUpdate = !_.isEmpty(values); } $scope.updateSelection = function updateSelection () { var selected = _.pluck($scope.filters, 'field'); _.each($scope.options, function (opt) { opt.selected = selected.indexOf(opt.name) > -1; }); updateValues($scope.record); }; $scope.$watch('record', updateValues, true); $scope.canUpdate = function () { return canUpdate; }; $scope.updateAll = false; $scope.applyUpdate = function () { var handler = $scope.handler; var ds = handler._dataSource; function doUpdate() { var promise, items; items = _.map(handler.selection, function(index) { return handler.dataView.getItem(index); }); items = _.pluck(items, "id"); if ($scope.updateAll) { items = null; } else if (items.length === 0) { return $scope.onCancel(); } promise = ds.updateMass(values, items); promise.success(function () { handler.onRefresh(); $scope.onCancel(); }); } var count; if ($scope.updateAll) { count = ds._page.total; } else if(handler.selection && handler.selection.length > 0) { count = handler.selection.length; } else { return; } var message = _t('Do you really want to update all {0} record(s)?', count); axelor.dialogs.confirm(message, function (confirmed) { if (confirmed) { doUpdate(); } }); }; }], link: function (scope, element, attrs) { scope.onSelect = function (name) { scope.updateSelection(); setTimeout(adjustEditors); }; scope.clearFilter = function() { scope.filters.length = 0; scope.addFilter(); scope.record = {}; adjustEditors(); }; scope.remove = function(filter) { scope.removeFilter(filter); adjustEditors(); }; scope.onCancel = function () { if (scope.$parent.onCancel) { scope.$parent.onCancel(); } }; function adjustEditors() { element.find('[x-place-for] [x-field]').each(function () { var editor = $(this); var parent = editor.data('$parent'); editor.appendTo(parent); }); _.each(scope.filters, function (filter) { adjustEditor(filter.field); }); } function adjustEditor(name) { var span = element.find('[x-place-for=' + name + ']'); var editor = element.find('[x-field=' + name + '].form-item-container,[x-field=' + name + '].boolean-item').first(); var parent = editor.data('$parent'); if (!parent) { parent = editor.parent(); editor.data('$parent', parent); } editor.appendTo(span); } }, template: "
" + "Mass Update " + "
" + "" + "" + "" + "" + "" + "" + "
" + "" + "" + "" + "" + "" + "" + "
" + "" + "
"+ "
" }; }); ui.directive('uiUpdateMenu', function () { return { replace: true, scope: { handler: '=' }, link: function (scope, element, attrs) { scope.$parent.onShow = function (event, menu) { scope.handler._viewPromise.then(function (view) { var elem = $(event.currentTarget); if (scope.onInit) { scope.onInit(view); } menu.show(); menu.position({ my: "left top", at: "left bottom", of: elem }); }); }; }, template: "
" + "
" + "
" + "
" + " " + " " + " " + "
" + "
" }; }); })();