Files
ERP/sophal/js/view/view.portal.js

392 lines
9.8 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');
PortalCtrl.$inject = ['$scope', '$element'];
function PortalCtrl($scope, $element) {
var view = $scope._views.portal;
if (view.items) {
$scope.$timeout(function () {
$scope.parse(view);
});
} else {
$scope.loadView('portal', view.name).success(function(fields, schema){
$scope.parse(schema);
});
}
$scope.$applyAsync(function(){
if (view.deferred)
view.deferred.resolve($scope);
});
$scope.parse = function(schema) {
};
$scope.show = function(promise) {
$scope.updateRoute();
};
$scope.onShow = function() {
};
$scope.getContext = function() {
return _.extend({}, $scope._context);
};
$scope.getRouteOptions = function() {
return {
mode: 'portal',
args: []
};
};
$scope.setRouteOptions = function(options) {
if (!$scope.isNested) {
$scope.updateRoute();
}
};
}
var tmplPortlet =
'<div ui-view-portlet '+
'x-action="{{p.action}}" '+
'x-can-search="{{p.canSearch}}" '+
'x-col-span="{{p.colSpan}}" '+
'x-row-span="{{p.rowSpan}}" ' +
'x-height="{{p.height}}"></div>';
var tmplTabs =
"<div ui-portal-tabs x-schema='p'></div>";
ui.directive('uiViewPortal', ['$compile', function($compile) {
return {
scope: true,
controller: PortalCtrl,
link: function(scope, element, attrs) {
function init() {
element.sortable({
handle: ".portlet-header",
items: "> .portlet, > .portal-tabs",
forceHelperSize: true,
forcePlaceholderSizeType: true,
activate2: function(event, ui) {
var width = ui.placeholder.width();
var height = ui.placeholder.height();
ui.placeholder.width(width - 4);
ui.placeholder.height(height - 4);
ui.placeholder.css({
'left': '2px',
'top': '2px',
'margin-right': '4px'
});
},
deactivate: function(event, ui) {
axelor.$adjustSize();
}
});
}
scope.parse = function(schema) {
scope.portletCols = schema.cols || 2;
scope.portlets = schema.items;
_.each(scope.portlets, function (item) {
var tmpl = item.type === 'tabs' ? tmplTabs : tmplPortlet;
var child = scope.$new();
child.p = item;
var elem = $compile(tmpl)(child);
element.append(elem);
});
setTimeout(init);
};
},
replace: true,
transclude: true,
template: '<div class="portal" ng-transclude></div>'
};
}]);
PortletCtrl.$inject = ['$scope', '$element', 'MenuService', 'DataSource', 'ViewService'];
function PortletCtrl($scope, $element, MenuService, DataSource, ViewService) {
var self = this;
function init() {
ui.ViewCtrl.call(self, $scope, DataSource, ViewService);
$scope.show = function() {
};
$scope.onShow = function() {
};
}
$scope.initPortlet = function(action, options) {
MenuService.action(action, options).success(function(result){
if (_.isEmpty(result.data)) {
return;
}
var view = result.data[0].view;
$scope._viewParams = view;
$scope._viewAction = action;
init();
$scope.title = view.title;
$scope.parsePortlet(view);
});
};
$scope.$on('on:attrs-change:refresh', function(e) {
e.preventDefault();
if ($scope.onRefresh) {
$scope.onRefresh();
}
});
$scope.$on('on:tab-reload', function(e) {
if ($scope.onRefresh) {
$scope.onRefresh();
}
});
}
function setPortletSize(scope, element, attrs) {
var cols = scope.portletCols;
var colSpan = +attrs.colSpan || 1;
var rowSpan = +attrs.rowSpan || 1;
var width = 100;
var height = (+attrs.height || 250) * rowSpan;
width = (width / cols) * colSpan;
element.width(width + '%').height(height);
}
ui.directive('uiViewPortlet', ['$compile', function($compile){
return {
scope: true,
controller: PortletCtrl,
link: function(scope, element, attrs) {
var lazy = true;
(function () {
var counter = 0;
return function checkLoading() {
scope.waitForActions(function () {
if (counter < 10 && element.parent().is(":hidden")) {
counter++;
return setTimeout(checkLoading, 100);
}
lazy = !element.parent().is(".portal");
var unwatch = scope.$watch(function portalVisibleWatch() {
var action = attrs.action;
if (!action) {
return;
}
if (element.parent().is(":hidden")) {
lazy = true;
return;
}
unwatch();
unwatch = null;
var ctx;
if (scope.getContext) {
ctx = scope.getContext();
}
scope.initPortlet(action, {
context: ctx
});
});
});
};
})()();
scope.parsePortlet = _.once(function(view) {
scope.noFilter = attrs.canSearch != "true";
var template = $compile($('<div ui-portlet-' + view.viewType + '></div>'))(scope);
element.find('.portlet-content:first').append(template);
scope.show();
if (scope.portletCols) {
setPortletSize(scope, element, attrs);
}
// if lazy, load data
if (scope.onRefresh && lazy) {
scope.onRefresh();
}
});
scope.onPortletToggle = function(event) {
var e = $(event.target);
e.toggleClass('fa-chevron-up fa-chevron-down');
element.toggleClass('portlet-minimized');
if (e.hasClass('fa-chevron-up')) {
axelor.$adjustSize();
}
};
scope.doNext = function() {
if (this.canNext()) this.onNext();
};
scope.doPrev = function() {
if (this.canPrev()) this.onPrev();
};
},
replace: true,
template:
'<div class="portlet">'+
'<div class="portlet-body stackbar">'+
'<div class="portlet-header navbar">'+
'<div class="navbar-inner">'+
'<div class="container-fluid">'+
'<span class="brand" ng-bind-html="title"></span>'+
'<ul class="nav pull-right">'+
'<li class="portlet-pager" ng-show="showPager">'+
'<span class="portlet-pager-text">{{pagerText()}}</span>'+
'<span class="icons-bar">'+
'<i ng-click="doPrev()" ng-class="{disabled: !canPrev()}" class="fa fa-step-backward"></i>'+
'<i ng-click="doNext()" ng-class="{disabled: !canNext()}" class="fa fa-step-forward"></i>'+
'</span>'+
'</li>'+
'<li class="divider-vertical"></li>'+
'<li>'+
'<span class="icons-bar">'+
'<i title="{{\'Refresh\' | t}}" ng-click="onRefresh()" class="fa fa-refresh"></i>'+
'<i title="{{\'Toggle\' | t}}" ng-click="onPortletToggle($event)" class="fa fa-chevron-up"></i>'+
'</span>'+
'</li>'+
'</ul>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="portlet-content"></div>'+
'</div>'+
'</div>'
};
}]);
ui.directive('uiPortalTabs', function() {
return {
scope: {
schema: '='
},
replace: true,
link: function(scope, element, attrs) {
var schema = scope.schema;
var first = _.first(schema.tabs);
if (first) {
first.active = true;
}
scope.tabClick = function (tab) {
_.each(schema.tabs, function (item) {
item.active = false;
});
tab.active = true;
axelor.$adjustSize();
};
scope.tabs = schema.tabs;
scope.portletCols = scope.$parent.portletCols;
setPortletSize(scope, element, {
colSpan: schema.colSpan,
rowSpan: schema.rowSpan,
height: schema.height
});
element.height('auto');
},
template:
"<div class='tabbable-tabs portal-tabs'>" +
"<ul class='nav nav-tabs nav-tabs-scrollable'>" +
"<li ng-repeat='tab in tabs' ng-class='{active: tab.active}'>" +
"<a href='' ng-click='tabClick(tab)' >{{tab.title}}</a>" +
"</li>" +
"</ul>" +
"<div class='tab-content portal-tab-content'>" +
"<div ng-repeat='tab in tabs' ng-class='{active: tab.active}' class='tab-pane'>" +
"<div ui-portal-tab x-schema='tab'></div>" +
"</div>" +
"</div>" +
"</div>"
};
});
ui.directive('uiPortalTab', function() {
return {
scope: {
schema: '='
},
controller: ['$scope', 'DataSource', 'ViewService', function ($scope, DataSource, ViewService) {
var view = $scope.schema;
var params = {
viewType: 'portal',
views: [ view ]
};
view.type = 'portal';
$scope._viewParams = params;
$scope.isNested = true;
$scope._model = null;
ui.ViewCtrl.apply(this, arguments);
}],
template: "<div ui-view-portal></div>"
};
});
})();