/* * 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'); NavMenuCtrl.$inject = ['$scope', '$element', 'MenuService', 'NavService']; function NavMenuCtrl($scope, $element, MenuService, NavService) { $scope.menus = []; // the first four visible menus $scope.more = []; // rest of the menus var hasSideBar = axelor.config['view.menubar.location'] !== 'top'; MenuService.all().then(function(response) { var res = response.data, data = res.data; var items = {}; var all = []; _.each(data, function(item) { items[item.name] = item; if (item.children === undefined) { item.children = []; } }); _.each(data, function(item) { if (hasSideBar && !item.top) { return; } if (!item.parent) { return all.push(item); } var parent = items[item.parent]; if (parent) { parent.children.push(item); } }); $scope.menus = all; $scope.more = all; $scope.extra = { title: 'More', children: $scope.more }; }); this.isSubMenu = function(item) { return item && item.children && item.children.length > 0; }; this.onItemClick = function(item) { if (item.action && !this.isSubMenu(item)) { NavService.openTabByName(item.action); } }; $scope.hasImage = function (menu) { return menu.icon && menu.icon.indexOf('fa-') !== 0 && menu.icon.indexOf('empty') != -1; }; $scope.hasIcon = function (menu) { return menu.icon && menu.icon.indexOf('fa-') === 0 && menu.icon.indexOf('empty') != -1; }; $scope.hasText = function (menu) { return !menu.icon || menu.icon.indexOf('empty') === -1; }; } ui.directive('navMenuBar', function() { return { replace: true, controller: NavMenuCtrl, scope: true, link: function(scope, element, attrs, ctrl) { var elemTop, elemSub, elemMore; var siblingsWidth = 0; var adjusting = false; element.hide(); function adjust() { if (adjusting) { return; } adjusting = true; var count = 0; var parentWidth = element.parent().width() - 32; elemMore.hide(); elemTop.hide(); elemSub.hide(); while (count < elemTop.length) { var elem = $(elemTop[count]).show(); var width = siblingsWidth + element.width(); if (width > parentWidth) { elem.hide(); // show more... elemMore.show(); width = siblingsWidth + element.width(); if (width > parentWidth) { count--; $(elemTop[count]).hide(); } break; } count++; } if (count === elemTop.length) { elemMore.hide(); } while(count < elemTop.length) { $(elemSub[count++]).show(); } adjusting = false; } function setup() { element.siblings().each(function () { siblingsWidth += $(this).width(); }); elemTop = element.find('.nav-menu.dropdown:not(.nav-menu-more)'); elemMore = element.find('.nav-menu.dropdown.nav-menu-more'); elemSub = elemMore.find('.dropdown-menu:first > .dropdown-submenu'); element.show(); adjust(); $(window).on("resize.menubar", adjust); } element.on('$destroy', function () { if (element) { $(window).off("resize.menubar"); element = null; } }); var unwatch = scope.$watch('menus', function navMenusWatch(menus, old) { if (!menus || menus.length === 0 || menus === old) { return; } unwatch(); setTimeout(setup, 100); }); }, template: "" }; }); ui.directive('navMenu', function() { return { replace: true, require: '^navMenuBar', scope: { menu: '=navMenu' }, link: function(scope, element, attrs, ctrl) { }, template: "" }; }); ui.directive('navMenuItem', ['$compile', function($compile) { return { replace: true, require: '^navMenuBar', scope: { item: '=navMenuItem' }, link: function(scope, element, attrs, ctrl) { var item = scope.item; scope.isSubMenu = ctrl.isSubMenu(item); scope.isActionMenu = !!item.action; scope.onClick = function (e, item) { ctrl.onItemClick(item); }; if (ctrl.isSubMenu(item)) { element.addClass("dropdown-submenu"); $compile('')(scope, function(cloned, scope) { element.append(cloned); }); } }, template: "
  • " + "{{item.title}}" + "
  • " }; }]); ui.directive('navMenuFav', function() { return { replace: true, controller: ['$scope', '$location', 'DataSource', 'NavService', function ($scope, $location, DataSource, NavService) { var ds = DataSource.create("com.axelor.meta.db.MetaMenu", { domain: "self.user = :__user__ and self.link is not null" }); $scope.items = []; function update() { ds.search({ fields: ["id", "name", "title", "link"], sortBy: ["-priority"] }).success(function (records, page) { $scope.items = records; }); } function add(values, callback) { var item = _.findWhere($scope.items, { link: values.link }); if (item && item.title === values.title) { return callback(); } if (item) { item.title = values.title; } else { item = values; item.name = values.link; item.user = { id: axelor.config['user.id'] }; item.hidden = true; } ds.save(item).success(update).then(callback, callback); } $scope.addFav = function () { var link = $location.path(); if (link === "/") { return; } var tab = NavService.getSelected() || {}; var vs = tab.$viewScope || {}; var title = tab.title || (vs.schema || {}).title || ""; if (vs.record && vs.record.id > 0) { title = title + " (" + vs.record.id + ")"; } var item = _.findWhere($scope.items, { link: link }); if (item) { title = item.title; } var dialog = axelor.dialogs.box("", { title: _t('Add to favorites...'), buttons: [{ text: _t('Cancel'), 'class': 'btn btn-default', click: function (e) { $(this).dialog('close'); } }, { text: _t('OK'), 'class': 'btn btn-primary', click: function (e) { title = dialog.find("input").val(); add({ title: title, link: link }, function () { dialog.dialog('close'); }); } }] }); setTimeout(function () { dialog.find("input").val(title).focus().select(); }); }; $scope.manageFav = function () { NavService.openTabByName('menus.fav'); }; function onUpdate(e, _ds) { if (ds !== _ds && ds._model === _ds._model) { update(); } } $scope.$on("ds:saved", onUpdate); $scope.$on("ds:removed", onUpdate); update(); }], template: "" }; }); ui.directive('navMenuTasks', function() { return { replace: true, controller: ['$scope', '$location', 'TagService', 'NavService', function ($scope, $location, TagService, NavService) { var TEAM_TASK = "com.axelor.team.db.TeamTask"; function taskText(count) { var n = count || 0; if (n <= 0) return _t('no tasks'); return n > 1 ? _t('{0} tasks', n) : _t('{0} task', n); } function update(data) { var counts = data || {}; if (counts.current) { counts.css = 'badge-primary'; } if (counts.pending) { counts.css = 'badge-important'; } counts.currentText = taskText(counts.current); counts.pendingText = taskText(counts.pending); counts.total = Math.min(99, counts.current); $scope.counts = counts; } TagService.listen(function (data) { update(data.tasks || {}); }); $scope.showTasks = function (type) { NavService.openTabByName('team.tasks.' + type); }; function onDataChange(e, ds) { if (ds._model === TEAM_TASK) { TagService.find(); } } $scope.$on('ds:saved', onDataChange); $scope.$on('ds:removed', onDataChange); update({}); }], template: "" }; }); })();