summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/chrome/abstract_web_client.js26
-rw-r--r--addons/web/static/src/js/chrome/web_client.js3
-rw-r--r--addons/web/static/src/js/core/py_utils.js6
-rw-r--r--addons/web/static/src/js/core/session.js23
-rw-r--r--addons/web/static/src/js/services/crash_manager.js6
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js8
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js81
-rw-r--r--addons/web/static/src/scss/switch_company_menu.scss24
-rw-r--r--addons/web/static/src/xml/base.xml38
-rw-r--r--addons/web/static/tests/views/basic_model_tests.js1
10 files changed, 174 insertions, 42 deletions
diff --git a/addons/web/static/src/js/chrome/abstract_web_client.js b/addons/web/static/src/js/chrome/abstract_web_client.js
index 68ac157868d..9566dbda850 100644
--- a/addons/web/static/src/js/chrome/abstract_web_client.js
+++ b/addons/web/static/src/js/chrome/abstract_web_client.js
@@ -21,9 +21,11 @@ var Dialog = require('web.Dialog');
var dom = require('web.dom');
var KeyboardNavigationMixin = require('web.KeyboardNavigationMixin');
var Loading = require('web.Loading');
+var local_storage = require('web.local_storage');
var RainbowMan = require('web.RainbowMan');
var ServiceProviderMixin = require('web.ServiceProviderMixin');
var session = require('web.session');
+var utils = require('web.utils');
var Widget = require('web.Widget');
var _t = core._t;
@@ -112,6 +114,26 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
this.on("change:title_part", this, this._title_changed);
this._title_changed();
+ var state = $.bbq.getState();
+ // If not set on the url, retrieve cids from the local storage
+ // of from the default company on the user
+ var current_company_id = session.user_companies.current_company[0]
+ if (!state.cids) {
+ state.cids = utils.get_cookie('cids') !== null ? utils.get_cookie('cids') : String(current_company_id);
+ }
+ var stateCompanyIDS = _.map(state.cids.split(','), function (cid) { return parseInt(cid) });
+ var userCompanyIDS = _.map(session.user_companies.allowed_companies, function(company) {return company[0]});
+ // Check that the user has access to all the companies
+ if (!_.isEmpty(_.difference(stateCompanyIDS, userCompanyIDS))) {
+ state.cids = String(current_company_id);
+ stateCompanyIDS = [current_company_id]
+ }
+ // Update the user context with this configuration
+ session.user_context.allowed_company_ids = stateCompanyIDS;
+ $.bbq.pushState(state);
+ // Update favicon
+ $("link[type='image/x-icon'").attr('href', '/web/image/res.company/' + String(stateCompanyIDS[0]) + '/favicon/')
+
return session.is_bound
.then(function () {
self.$el.toggleClass('o_rtl', _t.database.parameters.direction === "rtl");
@@ -167,7 +189,7 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
}
}, 0);
});
- window.addEventListener('blur', function (e) { self._hideAccessKeyOverlay(); });
+ window.addEventListener('blur', function (e) {self._hideAccessKeyOverlay(); });
core.bus.on('click', this, function (ev) {
$('.tooltip').remove();
if (!$(ev.target).is('input[type=file]')) {
@@ -437,7 +459,7 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
* @param {OdooEvent} e
*/
_onPushState: function (e) {
- this.do_push_state(e.data.state);
+ this.do_push_state(_.extend(e.data.state, {'cids': $.bbq.getState().cids}));
},
/**
* This function must be implemented by actual webclient to scroll either to
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js
index 392d534f372..19ce0a92d41 100644
--- a/addons/web/static/src/js/chrome/web_client.js
+++ b/addons/web/static/src/js/chrome/web_client.js
@@ -87,7 +87,8 @@ return AbstractWebClient.extend({
// If the url's state is empty, we execute the user's home action if there is one (we
// show the first app if not)
- if (_.isEmpty($.bbq.getState(true))) {
+ var state = $.bbq.getState(true);
+ if (_.keys(state).length === 1 && _.keys(state)[0] === "cids") {
return self._rpc({
model: 'res.users',
method: 'read',
diff --git a/addons/web/static/src/js/core/py_utils.js b/addons/web/static/src/js/core/py_utils.js
index 296ab5c3089..2e673171a8f 100644
--- a/addons/web/static/src/js/core/py_utils.js
+++ b/addons/web/static/src/js/core/py_utils.js
@@ -89,7 +89,11 @@ function wrap_context(context) {
for (var k in context) {
if (!context.hasOwnProperty(k)) { continue; }
var val = context[k];
-
+ // Don't add a test case like ``val === undefined``
+ // this is intended to prevent letting crap pass
+ // on the context without even knowing it.
+ // If you face an issue from here, try to sanitize
+ // the context upstream instead
if (val === null) { continue; }
if (val.constructor === Array) {
context[k] = wrapping_list.fromJSON(val);
diff --git a/addons/web/static/src/js/core/session.js b/addons/web/static/src/js/core/session.js
index 2874a2ea559..21103a9529a 100644
--- a/addons/web/static/src/js/core/session.js
+++ b/addons/web/static/src/js/core/session.js
@@ -5,6 +5,7 @@ var ajax = require('web.ajax');
var concurrency = require('web.concurrency');
var config = require('web.config');
var core = require('web.core');
+var local_storage = require('web.local_storage');
var mixins = require('web.mixins');
var utils = require('web.utils');
@@ -305,6 +306,12 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
options.headers["X-Debug-Mode"] = $.deparam($.param.querystring()).debug;
}
+ // we add here the user context for ALL queries, mainly to pass
+ // the allowed_company_ids key
+ if (params && params.kwargs) {
+ params.kwargs.context = _.extend(params.kwargs.context || {}, this.user_context);
+ }
+
// TODO: remove
if (! _.isString(url)) {
_.extend(options, url);
@@ -359,6 +366,22 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
});
},
+ setCompanies: function (main_company_id, company_ids) {
+ var hash = $.bbq.getState()
+ hash.cids = company_ids.sort(function(a, b) {
+ if (a === main_company_id) {
+ return -1;
+ } else if (b === main_company_id) {
+ return 1;
+ } else {
+ return a - b;
+ }
+ }).join(',');
+ utils.set_cookie('cids', hash.cids || String(main_company_id));
+ $.bbq.pushState({'cids': hash.cids}, 0);
+ location.reload();
+ },
+
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js
index a29e21ca8ca..ff699af3262 100644
--- a/addons/web/static/src/js/services/crash_manager.js
+++ b/addons/web/static/src/js/services/crash_manager.js
@@ -231,8 +231,12 @@ var RedirectWarningHandler = Dialog.extend(ExceptionHandler, {
title: _.str.capitalize(error.type) || _t("Odoo Warning"),
buttons: [
{text: error.data.arguments[2], classes : "btn-primary", click: function() {
- window.location.href = '#action='+error.data.arguments[1];
+ $.bbq.pushState({
+ 'action': error.data.arguments[1],
+ 'cids': $.bbq.getState().cids,
+ }, 2);
self.destroy();
+ location.reload();
}},
{text: _t("Cancel"), click: function() { self.destroy(); }, close: true}
],
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index a79fabd48d6..6aa884bbacf 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -3423,12 +3423,20 @@ var BasicModel = AbstractModel.extend({
evalContext.parent = this._getRecordEvalContext(parent, forDomain);
}
}
+ // Uses "current_company_id" because "company_id" would conflict with all the company_id fields
+ // in general, the actual "company_id" field of the form should be used for m2o domains, not this fallback
+ if (session.user_context.allowed_company_ids) {
+ var current_company = session.user_context.allowed_company_ids[0];
+ } else {
+ var current_company = session.user_companies ? session.user_companies.current_company[0] : false;
+ }
return _.extend({
active_id: evalContext.id || false,
active_ids: evalContext.id ? [evalContext.id] : [],
active_model: element.model,
current_date: moment().format('YYYY-MM-DD'),
id: evalContext.id || false,
+ current_company_id: current_company,
}, session.user_context, element.context, evalContext);
},
/**
diff --git a/addons/web/static/src/js/widgets/switch_company_menu.js b/addons/web/static/src/js/widgets/switch_company_menu.js
index a389ee268cd..0939c8b1c8b 100644
--- a/addons/web/static/src/js/widgets/switch_company_menu.js
+++ b/addons/web/static/src/js/widgets/switch_company_menu.js
@@ -18,40 +18,48 @@ var _t = core._t;
var SwitchCompanyMenu = Widget.extend({
template: 'SwitchCompanyMenu',
events: {
- 'click .dropdown-item[data-menu]': '_onClick',
+ 'click .dropdown-item[data-menu] div.log_into': '_onSwitchCompanyClick',
+ 'click .dropdown-item[data-menu] div.toggle_company': '_onToggleCompanyClick',
},
/**
* @override
*/
init: function () {
+ var self = this;
this._super.apply(this, arguments);
this.isMobile = config.device.isMobile;
- this._onClick = _.debounce(this._onClick, 1500, true);
+ this._onSwitchCompanyClick = _.debounce(this._onSwitchCompanyClick, 1500, true);
+ this.allowed_company_ids = String(session.user_context.allowed_company_ids).split(',');
+ this.user_companies = session.user_companies.allowed_companies;
+ this.toggle_company = session.toggle_company;
+
+ var hash = $.bbq.getState()
+ if (!hash.cids || hash.cids === undefined) {
+ hash.cids = String(session.user_companies.current_company[0]);
+ }
+ this.current_company = parseInt(hash.cids.split(',')[0]);
+ this.current_company_name = _.find(session.user_companies.allowed_companies, function (company) {
+ return company[0] === self.current_company;
+ })[1];
},
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
/**
- * @override
+ * @private
+ * @param {MouseEvent} ev
*/
- start: function () {
- var companiesList = '';
- if (this.isMobile) {
- companiesList = '<li class="bg-info">' +
- _t('Tap on the list to change company') + '</li>';
- }
- else {
- this.$('.oe_topbar_name').text(session.user_companies.current_company[1]);
+ _onSwitchCompanyClick: function (ev) {
+ ev.preventDefault();
+ var companyID = $(ev.currentTarget).parent().data('company-id');
+ var hash = $.bbq.getState()
+ var allowed_company_ids = _.map(hash.cids.split(','), function(company_id) {return parseInt(company_id);});
+ if ($($(ev.currentTarget).parent()).find('.fa-square-o').length) {
+ allowed_company_ids.push(companyID);
}
- _.each(session.user_companies.allowed_companies, function(company) {
- var a = '';
- if (company[0] === session.user_companies.current_company[0]) {
- a = '<i class="fa fa-check mr8"></i>';
- } else {
- a = '<span style="margin-right: 24px;"/>';
- }
- companiesList += '<a role="menuitem" href="#" class="dropdown-item" data-menu="company" data-company-id="' +
- company[0] + '">' + a + company[1] + '</a>';
- });
- this.$('.dropdown-menu').html(companiesList);
- return this._super();
+ session.setCompanies(companyID, [companyID]);
},
//--------------------------------------------------------------------------
@@ -62,22 +70,25 @@ var SwitchCompanyMenu = Widget.extend({
* @private
* @param {MouseEvent} ev
*/
- _onClick: function (ev) {
- ev.preventDefault();
- var companyID = $(ev.currentTarget).data('company-id');
- this._rpc({
- model: 'res.users',
- method: 'write',
- args: [[session.uid], {'company_id': companyID}],
- })
- .then(function() {
- location.reload();
- });
+ _onToggleCompanyClick: function (ev) {
+ var companyID = $(ev.currentTarget).parent().data('company-id');
+ var hash = $.bbq.getState()
+ var allowed_company_ids = _.map(hash.cids.split(','), function(company_id) {return parseInt(company_id);});
+ var current_company_id = allowed_company_ids[0];
+ if ($(ev.currentTarget).find('.fa-square-o')) {
+ allowed_company_ids.push(companyID);
+ } else {
+ allowed_company_ids.splice(allowed_company_ids.indexOf(companyID), 1);
+ }
+ session.setCompanies(current_company_id, allowed_company_ids);
},
+
});
-if (session.user_companies) {
+
+if (session.display_switch_company_menu) {
SystrayMenu.Items.push(SwitchCompanyMenu);
}
+
return SwitchCompanyMenu;
});
diff --git a/addons/web/static/src/scss/switch_company_menu.scss b/addons/web/static/src/scss/switch_company_menu.scss
new file mode 100644
index 00000000000..cae7c3d6522
--- /dev/null
+++ b/addons/web/static/src/scss/switch_company_menu.scss
@@ -0,0 +1,24 @@
+
+.o_main_navbar {
+ .o_switch_company_menu {
+ .dropdown-item {
+ cursor: pointer;
+
+ &:hover {
+ background-color: white;
+ }
+
+ .toggle_company {
+ &:hover {
+ background-color: #e9ecef;
+ }
+ }
+
+ .log_into {
+ &:hover {
+ background-color: #e9ecef;
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 84af548222b..bb8e5e1c81a 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1559,9 +1559,43 @@
<t t-name="SwitchCompanyMenu">
<li class="o_switch_company_menu">
<a role="button" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" href="#" aria-label="Dropdown menu" title="Dropdown menu">
- <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}"/>
+ <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}">
+ <t t-if="!widget.isMobile"><t t-raw="widget.current_company_name"/></t>
+ </span>
</a>
- <div class="dropdown-menu dropdown-menu-right" role="menu"/>
+ <div class="dropdown-menu dropdown-menu-right" role="menu">
+ <t t-if="widget.isMobile">
+ <li class="bg-info">Tap on the list to change company</li>
+ </t>
+ <t t-foreach="widget.user_companies" t-as="company">
+ <span role="menuitem" href="#" class="dropdown-item d-flex align-items-center py-0 px-0" data-menu="company" t-att-data-company-id="company[0]">
+ <div class="d-flex flex-grow-1 align-items-center py-0 log_into pl-3" t-att-style="company[0] === widget.current_company ? 'background-color: lightgrey;' : ''">
+ <t t-if="widget.allowed_company_ids.includes(company[0].toString())">
+ <span class='mr-3 company_label'>
+ <t t-esc="company[1]"/>
+ </span>
+ </t>
+ <t t-if="!widget.allowed_company_ids.includes(company[0].toString())">
+ <span class='mr-3 company_label text-muted'>
+ <t t-esc="company[1]"/>
+ </span>
+ </t>
+ </div>
+ <t t-if="widget.toggle_company">
+ <div class="ml-auto pl-3 pr-3 border border-top-0 border-right-0 border-bottom-0 toggle_company">
+ <span style="height: 2rem;">
+ <t t-if="widget.allowed_company_ids.includes(company[0].toString())">
+ <i class="fa fa-fw fa-check-square pt-2"></i>
+ </t>
+ <t t-if="!widget.allowed_company_ids.includes(company[0].toString())">
+ <i class="fa fa-fw fa-square-o pt-2"></i>
+ </t>
+ </span>
+ </div>
+ </t>
+ </span>
+ </t>
+ </div>
</li>
</t>
diff --git a/addons/web/static/tests/views/basic_model_tests.js b/addons/web/static/tests/views/basic_model_tests.js
index d840210d4ff..8bc9a01465e 100644
--- a/addons/web/static/tests/views/basic_model_tests.js
+++ b/addons/web/static/tests/views/basic_model_tests.js
@@ -1929,6 +1929,7 @@ odoo.define('web.basic_model_tests', function (require) {
active_model: "partner",
bar: 1,
category: [12],
+ current_company_id: false,
current_date: moment().format('YYYY-MM-DD'),
date: "2017-01-25",
display_name: "first partner",