summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/chrome/web_client.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2017-03-05 10:05:56 +0100
committerAaron Bohy <aab@odoo.com>2017-04-11 19:44:38 +0200
commit905e01921f3c3ef43ace6fc537d1d8c0d280002c (patch)
tree265c43ab21c5401a5d9f0f3d64d86f1ac417451c /addons/web/static/src/js/chrome/web_client.js
parent54d4c73af4ad05c7640d28c1892247c9538b8017 (diff)
[REF] web, *: redesign all JS views
This commit introduce a full redesign of all JS views. We started basically from scratch. The goal was to unify all the various views under a common framework, to make them testable, to make then usable in different conditions (in studio, or in the frontend), and to make our lives easier. Some important points are: - we introduced new coding guidelines (camelCase, 80 chars width, ...) - we have a brand new testing framework (still QUnit based) - kanban view moved to the web addon - calendar view (formerly web_calender) moved to web as well - the tree view was removed - all new code should be documented We hope that this code is the start of a new era for the Odoo web client, we want to have a high quality codebase, well documented, well tested, well designed. Work done by the framework team: mostly aab, ged, chm, dmo, qsm
Diffstat (limited to 'addons/web/static/src/js/chrome/web_client.js')
-rw-r--r--addons/web/static/src/js/chrome/web_client.js178
1 files changed, 178 insertions, 0 deletions
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js
new file mode 100644
index 00000000000..17993c73638
--- /dev/null
+++ b/addons/web/static/src/js/chrome/web_client.js
@@ -0,0 +1,178 @@
+odoo.define('web.WebClient', function (require) {
+"use strict";
+
+var AbstractWebClient = require('web.AbstractWebClient');
+var core = require('web.core');
+var data_manager = require('web.data_manager');
+var framework = require('web.framework');
+var Menu = require('web.Menu');
+var Model = require('web.DataModel');
+var session = require('web.session');
+var SystrayMenu = require('web.SystrayMenu');
+var UserMenu = require('web.UserMenu');
+
+return AbstractWebClient.extend({
+ events: {
+ 'click .oe_logo_edit_admin': 'logo_edit',
+ 'click .oe_logo img': function(ev) {
+ ev.preventDefault();
+ return this.clear_uncommitted_changes().then(function() {
+ framework.redirect("/web" + (core.debug ? "?debug" : ""));
+ });
+ },
+ },
+ show_application: function() {
+ var self = this;
+
+ // Allow to call `on_attach_callback` and `on_detach_callback` when needed
+ this.action_manager.is_in_DOM = true;
+
+ this.toggle_bars(true);
+ this.set_title();
+ this.update_logo();
+
+ // Menu is rendered server-side thus we don't want the widget to create any dom
+ this.menu = new Menu(this);
+ this.menu.setElement(this.$el.parents().find('.oe_application_menu_placeholder'));
+ this.menu.on('menu_click', this, this.on_menu_action);
+
+ // Create the user menu (rendered client-side)
+ this.user_menu = new UserMenu(this);
+ var $user_menu_placeholder = $('body').find('.oe_user_menu_placeholder').show();
+ var user_menu_loaded = this.user_menu.appendTo($user_menu_placeholder);
+
+ // Create the systray menu (rendered server-side)
+ this.systray_menu = new SystrayMenu(this);
+ this.systray_menu.setElement(this.$el.parents().find('.oe_systray'));
+ var systray_menu_loaded = this.systray_menu.start();
+
+ // Start the menu once both systray and user menus are rendered
+ // to prevent overflows while loading
+ return $.when(systray_menu_loaded, user_menu_loaded).then(function() {
+ self.menu.start();
+ self.bind_hashchange();
+ });
+
+ },
+ toggle_bars: function(value) {
+ this.$('tr:has(td.navbar),.oe_leftbar').toggle(value);
+ },
+ update_logo: function(reload) {
+ var company = session.company_id;
+ var img = session.url('/web/binary/company_logo' + '?db=' + session.db + (company ? '&company=' + company : ''));
+ this.$('.o_sub_menu_logo img').attr('src', '').attr('src', img + (reload ? "#" + Date.now() : ''));
+ this.$('.oe_logo_edit').toggleClass('oe_logo_edit_admin', session.is_superuser);
+ },
+ logo_edit: function(ev) {
+ var self = this;
+ ev.preventDefault();
+ self.alive(new Model("res.users").call("read", [[session.uid], ["company_id"]])).then(function(data) {
+ self.rpc("/web/action/load", { action_id: "base.action_res_company_form" }).done(function(result) {
+ result.res_id = data[0].company_id[0];
+ result.target = "new";
+ result.views = [[false, 'form']];
+ result.flags = {
+ action_buttons: true,
+ headless: true,
+ };
+ self.action_manager.do_action(result).then(function () {
+ var form = self.action_manager.dialog_widget.views.form.controller;
+ form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
+ form.on('record_saved', self, function() {
+ self.action_manager.dialog_stop();
+ self.update_logo();
+ });
+ });
+ });
+ });
+ return false;
+ },
+ bind_hashchange: function() {
+ var self = this;
+ $(window).bind('hashchange', this.on_hashchange);
+
+ var state = $.bbq.getState(true);
+ if (_.isEmpty(state) || state.action === "login") {
+ self.menu.is_bound.done(function() {
+ new Model("res.users").call("read", [[session.uid], ["action_id"]]).done(function(result) {
+ var data = result[0];
+ if(data.action_id) {
+ self.action_manager.do_action(data.action_id[0]);
+ self.menu.open_action(data.action_id[0]);
+ } else {
+ var first_menu_id = self.menu.$el.find("a:first").data("menu");
+ if(first_menu_id) {
+ self.menu.menu_click(first_menu_id);
+ }
+ }
+ });
+ });
+ } else {
+ $(window).trigger('hashchange');
+ }
+ },
+ on_hashchange: function(event) {
+ if (this._ignore_hashchange) {
+ this._ignore_hashchange = false;
+ return;
+ }
+
+ var self = this;
+ this.clear_uncommitted_changes().then(function () {
+ var stringstate = event.getState(false);
+ if (!_.isEqual(self._current_state, stringstate)) {
+ var state = event.getState(true);
+ if(!state.action && state.menu_id) {
+ self.menu.is_bound.done(function() {
+ self.menu.menu_click(state.menu_id);
+ });
+ } else {
+ state._push_me = false; // no need to push state back...
+ self.action_manager.do_load_state(state, !!self._current_state).then(function () {
+ var action = self.action_manager.get_inner_action();
+ if (action) {
+ self.menu.open_action(action.action_descr.id);
+ }
+ });
+ }
+ }
+ self._current_state = stringstate;
+ }, function () {
+ if (event) {
+ self._ignore_hashchange = true;
+ window.location = event.originalEvent.oldURL;
+ }
+ });
+ },
+ on_menu_action: function(options) {
+ var self = this;
+ return this.menu_dm.add(data_manager.load_action(options.action_id))
+ .then(function (result) {
+ return self.action_mutex.exec(function() {
+ var completed = $.Deferred();
+ $.when(self.action_manager.do_action(result, {
+ clear_breadcrumbs: true,
+ action_menu_id: self.menu.current_menu,
+ })).fail(function() {
+ self.menu.open_menu(options.previous_menu_id);
+ }).always(function() {
+ completed.resolve();
+ });
+ setTimeout(function() {
+ completed.resolve();
+ }, 2000);
+ // We block the menu when clicking on an element until the action has correctly finished
+ // loading. If something crash, there is a 2 seconds timeout before it's unblocked.
+ return completed;
+ });
+ });
+ },
+ toggle_fullscreen: function(fullscreen) {
+ this._super(fullscreen);
+ if (!fullscreen) {
+ this.menu.reflow();
+ }
+ },
+});
+
+});