1 /*---------------------------------------------------------
3 *---------------------------------------------------------*/
4 openerp.web.chrome = function(openerp) {
5 var QWeb = openerp.web.qweb;
7 openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{
8 template: 'Notification',
9 identifier_prefix: 'notification-',
12 this._super.apply(this, arguments);
13 openerp.notification = this;
17 this._super.apply(this, arguments);
18 this.$element.notify({
23 notify: function(title, text) {
24 this.$element.notify('create', {
29 warn: function(title, text) {
30 this.$element.notify('create', 'oe_notification_alert', {
38 openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog# */{
40 identifier_prefix: 'dialog',
42 * @constructs openerp.web.Dialog
43 * @extends openerp.web.OldWidget
46 * @param dialog_options
48 init: function (parent, dialog_options) {
51 this.dialog_options = {
61 beforeClose: function () { self.on_close(); }
64 if (f.substr(0, 10) == 'on_button_') {
65 this.dialog_options.buttons[f.substr(10)] = this[f];
69 this.set_options(dialog_options);
72 set_options: function(options) {
73 options = options || {};
74 options.width = this.get_width(options.width || this.dialog_options.width);
75 options.min_width = this.get_width(options.min_width || this.dialog_options.min_width);
76 options.max_width = this.get_width(options.max_width || this.dialog_options.max_width);
77 options.height = this.get_height(options.height || this.dialog_options.height);
78 options.min_height = this.get_height(options.min_height || this.dialog_options.min_height);
79 options.max_height = this.get_height(options.max_height || this.dialog_options.max_width);
81 if (options.width !== 'auto') {
82 if (options.width > options.max_width) options.width = options.max_width;
83 if (options.width < options.min_width) options.width = options.min_width;
85 if (options.height !== 'auto') {
86 if (options.height > options.max_height) options.height = options.max_height;
87 if (options.height < options.min_height) options.height = options.min_height;
89 if (!options.title && this.dialog_title) {
90 options.title = this.dialog_title;
92 _.extend(this.dialog_options, options);
94 get_width: function(val) {
95 return this.get_size(val.toString(), $(window.top).width());
97 get_height: function(val) {
98 return this.get_size(val.toString(), $(window.top).height());
100 get_size: function(val, available_size) {
101 if (val === 'auto') {
103 } else if (val.slice(-1) == "%") {
104 return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
106 return parseInt(val, 10);
110 this.$dialog = $(this.$element).dialog(this.dialog_options);
114 open: function(dialog_options) {
115 // TODO fme: bind window on resize
117 this.$element.html(this.render());
119 this.set_options(dialog_options);
120 this.$dialog.dialog(this.dialog_options).dialog('open');
124 // Closes the dialog but leave it in a state where it could be opened again.
125 this.$dialog.dialog('close');
127 on_close: function() {
132 this.$dialog.dialog('destroy');
137 openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({
140 openerp.connection.on_rpc_error.add(this.on_rpc_error);
142 on_rpc_error: function(error) {
144 if (error.data.fault_code) {
145 var split = ("" + error.data.fault_code).split('\n')[0].split(' -- ');
146 if (split.length > 1) {
147 error.type = split.shift();
148 error.data.fault_code = error.data.fault_code.substr(error.type.length + 4);
151 if (error.code === 200 && error.type) {
152 this.on_managed_error(error);
154 this.on_traceback(error);
157 on_managed_error: function(error) {
158 $('<div>' + QWeb.render('DialogWarning', {error: error}) + '</div>').dialog({
159 title: "OpenERP " + _.str.capitalize(error.type),
162 $(this).dialog("close");
167 on_traceback: function(error) {
168 var dialog = new openerp.web.Dialog(this, {
169 title: "OpenERP " + _.str.capitalize(error.type),
177 $(this).dialog("close");
181 dialog.$element.html(QWeb.render('DialogTraceback', {error: error}));
185 openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{
188 * @constructs openerp.web.Loading
189 * @extends openerp.web.Widget
194 init: function(parent) {
197 this.blocked_ui = false;
198 this.session.on_rpc_request.add_first(this.on_rpc_event, 1);
199 this.session.on_rpc_response.add_last(this.on_rpc_event, -1);
201 on_rpc_event : function(increment) {
203 if (!this.count && increment === 1) {
205 this.long_running_timer = setTimeout(function () {
206 self.blocked_ui = true;
211 this.count += increment;
212 if (this.count > 0) {
213 //this.$element.html(QWeb.render("Loading", {}));
214 this.$element.html("Loading ("+this.count+")");
215 this.$element.show();
216 this.widget_parent.$element.addClass('loading');
219 clearTimeout(this.long_running_timer);
220 // Don't unblock if blocked by somebody else
221 if (self.blocked_ui) {
222 this.blocked_ui = false;
225 this.$element.fadeOut();
226 this.widget_parent.$element.removeClass('loading');
231 openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database# */{
233 * @constructs openerp.web.Database
234 * @extends openerp.web.Widget
240 init: function(parent, element_id, option_id) {
241 this._super(parent, element_id);
242 this.$option_id = $('#' + option_id);
243 this.unblockUIFunction = $.unblockUI;
247 this.$element.html(QWeb.render("Database", this));
250 var fetch_db = this.rpc("/web/database/get_list", {}, function(result) {
251 self.db_list = result.db_list;
253 var fetch_langs = this.rpc("/web/session/get_lang_list", {}, function(result) {
255 self.display_error(result);
258 self.lang_list = result.lang_list;
260 $.when(fetch_db, fetch_langs).then(function () {self.do_create();});
262 this.$element.find('#db-create').click(this.do_create);
263 this.$element.find('#db-drop').click(this.do_drop);
264 this.$element.find('#db-backup').click(this.do_backup);
265 this.$element.find('#db-restore').click(this.do_restore);
266 this.$element.find('#db-change-password').click(this.do_change_password);
267 this.$element.find('#back-to-login').click(function() {
273 this.$option_id.empty();
276 .find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login')
283 this.$element.closest(".openerp")
284 .removeClass("login-mode")
285 .addClass("database_block");
288 this.$element.closest(".openerp")
289 .addClass("login-mode")
290 .removeClass("database_block")
293 * Converts a .serializeArray() result into a dict. Does not bother folding
294 * multiple identical keys into an array, last key wins.
296 * @param {Array} array
298 to_object: function (array) {
300 _(array).each(function (record) {
301 result[record.name] = record.value;
306 * Waits until the new database is done creating, then unblocks the UI and
307 * logs the user in as admin
309 * @param {Number} db_creation_id identifier for the db-creation operation, used to fetch the current installation progress
310 * @param {Object} info info fields for this database creation
311 * @param {String} info.db name of the database being created
312 * @param {String} info.password super-admin password for the database
314 wait_for_newdb: function (db_creation_id, info) {
316 self.rpc('/web/database/progress', {
318 password: info.password
319 }, function (result) {
320 var progress = result[0];
321 // I'd display a progress bar, but turns out the progress status
322 // the server report kind-of blows goats: it's at 0 for ~75% of
323 // the installation, then jumps to 75%, then jumps down to either
324 // 0 or ~40%, then back up to 75%, then terminates. Let's keep that
325 // mess hidden behind a not-very-useful but not overly weird
328 setTimeout(function () {
329 self.wait_for_newdb(db_creation_id, info);
334 var admin = result[1][0];
335 setTimeout(function () {
336 self.widget_parent.do_login(
337 info.db, admin.login, admin.password);
344 * Blocks UI and replaces $.unblockUI by a noop to prevent third parties
345 * from unblocking the UI
347 blockUI: function () {
349 $.unblockUI = function () {};
352 * Reinstates $.unblockUI so third parties can play with blockUI, and
355 unblockUI: function () {
356 $.unblockUI = this.unblockUIFunction;
360 * Displays an error dialog resulting from the various RPC communications
361 * failing over themselves
363 * @param {Object} error error description
364 * @param {String} error.title title of the error dialog
365 * @param {String} error.error message of the error dialog
367 display_error: function (error) {
368 return $('<div>').dialog({
373 $(this).dialog("close");
376 }).html(error.error);
378 do_create: function() {
380 self.$option_id.html(QWeb.render("Database.CreateDB", self));
381 self.$option_id.find("form[name=create_db_form]").validate({
382 submitHandler: function (form) {
383 var fields = $(form).serializeArray();
385 self.rpc("/web/database/create", {'fields': fields}, function(result) {
388 self.display_error(result);
391 self.db_list.push(self.to_object(fields)['db_name']);
393 self.widget_parent.set_db_list(self.db_list);
394 var form_obj = self.to_object(fields);
395 self.wait_for_newdb(result, {
396 password: form_obj['super_admin_pwd'],
397 db: form_obj['db_name']
403 do_drop: function() {
405 self.$option_id.html(QWeb.render("DropDB", self));
406 self.$option_id.find("form[name=drop_db_form]").validate({
407 submitHandler: function (form) {
409 fields = $form.serializeArray(),
410 $db_list = $form.find('select[name=drop_db]'),
413 if (!confirm("Do you really want to delete the database: " + db + " ?")) {
416 self.rpc("/web/database/drop", {'fields': fields}, function(result) {
418 self.display_error(result);
421 $db_list.find(':selected').remove();
422 self.db_list.splice(_.indexOf(self.db_list, db, true), 1);
423 self.widget_parent.set_db_list(self.db_list);
424 self.do_notify("Dropping database", "The database '" + db + "' has been dropped");
429 do_backup: function() {
432 .html(QWeb.render("BackupDB", self))
433 .find("form[name=backup_db_form]").validate({
434 submitHandler: function (form) {
436 self.session.get_file({
438 error: function (body) {
439 var error = body.firstChild.data.split('|');
445 complete: $.proxy(self, 'unblockUI')
450 do_restore: function() {
452 self.$option_id.html(QWeb.render("RestoreDB", self));
454 self.$option_id.find("form[name=restore_db_form]").validate({
455 submitHandler: function (form) {
458 url: '/web/database/restore',
461 success: function (body) {
462 // TODO: ui manipulations
463 // note: response objects don't work, but we have the
464 // HTTP body of the response~~
466 // If empty body, everything went fine
467 if (!body) { return; }
469 if (body.indexOf('403 Forbidden') !== -1) {
471 title: 'Access Denied',
472 error: 'Incorrect super-administrator password'
476 title: 'Restore Database',
477 error: 'Could not restore the database'
481 complete: $.proxy(self, 'unblockUI')
486 do_change_password: function() {
488 self.$option_id.html(QWeb.render("Change_DB_Pwd", self));
490 self.$option_id.find("form[name=change_pwd_form]").validate({
492 old_pwd: "Please enter your previous password",
493 new_pwd: "Please enter your new password",
495 required: "Please confirm your new password",
496 equalTo: "The confirmation does not match the password"
499 submitHandler: function (form) {
500 self.rpc("/web/database/change_password", {
501 'fields': $(form).serializeArray()
502 }, function(result) {
504 self.display_error(result);
507 self.do_notify("Changed Password", "Password has been changed successfully");
514 openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
515 remember_credentials: true,
518 identifier_prefix: 'oe-app-login-',
520 * @constructs openerp.web.Login
521 * @extends openerp.web.Widget
527 init: function(parent) {
529 this.has_local_storage = typeof(localStorage) != 'undefined';
530 this.selected_db = null;
531 this.selected_login = null;
533 if (this.has_local_storage && this.remember_credentials) {
534 this.selected_db = localStorage.getItem('last_db_login_success');
535 this.selected_login = localStorage.getItem('last_login_login_success');
536 if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) {
537 this.selected_password = localStorage.getItem('last_password_login_success');
541 var qs = jQuery.deparam(jQuery.param.querystring());
543 this.selected_db = qs.db;
546 this.selected_login = qs.login;
552 this.database = new openerp.web.Database(
553 this, "oe_database", "oe_db_options");
554 this.database.start();
556 this.$element.find('#oe-db-config').click(function() {
557 self.database.show();
560 this.$element.find("form").submit(this.on_submit);
562 this.rpc("/web/database/get_list", {}, function(result) {
563 self.set_db_list(result.db_list);
565 function(error, event) {
566 if (error.data.fault_code === 'AccessDenied') {
567 event.preventDefault();
573 this.database.stop();
576 set_db_list: function (list) {
577 this.$element.find("[name=db]").replaceWith(
578 openerp.web.qweb.render('Login_dblist', {
579 db_list: list, selected_db: this.selected_db}))
581 on_login_invalid: function() {
582 this.$element.closest(".openerp").addClass("login-mode");
584 on_login_valid: function() {
585 this.$element.closest(".openerp").removeClass("login-mode");
587 on_submit: function(ev) {
589 var $e = this.$element;
590 var db = $e.find("form [name=db]").val();
591 var login = $e.find("form input[name=login]").val();
592 var password = $e.find("form input[name=password]").val();
594 this.do_login(db, login, password);
597 * Performs actual login operation, and UI-related stuff
599 * @param {String} db database to log in
600 * @param {String} login user login
601 * @param {String} password user password
603 do_login: function (db, login, password) {
605 this.session.session_login(db, login, password, function() {
606 if(self.session.session_is_valid()) {
607 if (self.has_local_storage) {
608 if(self.remember_credentials) {
609 localStorage.setItem('last_db_login_success', db);
610 localStorage.setItem('last_login_login_success', login);
611 if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) {
612 localStorage.setItem('last_password_login_success', password);
615 localStorage.setItem('last_db_login_success', '');
616 localStorage.setItem('last_login_login_success', '');
617 localStorage.setItem('last_password_login_success', '');
620 self.on_login_valid();
622 self.$element.addClass("login_invalid");
623 self.on_login_invalid();
627 do_ask_login: function(continuation) {
628 this.on_login_invalid();
630 .removeClass("login_invalid");
631 this.on_login_valid.add({
634 callback: continuation || function() {}
637 on_logout: function() {
638 this.session.logout();
642 openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{
644 identifier_prefix: 'oe-app-header-',
646 * @constructs openerp.web.Header
647 * @extends openerp.web.Widget
651 init: function(parent) {
653 this.qs = "?" + jQuery.param.querystring();
655 this.update_promise = $.Deferred().resolve();
660 do_update: function () {
662 var fct = function() {
663 self.$content.remove();
664 if (!self.session.uid)
666 var func = new openerp.web.Model(self.session, "res.users").get_func("read");
667 return func(self.session.uid, ["name", "company_id"]).pipe(function(res) {
668 self.$content = $(QWeb.render("Header-content", {widget: self, user: res}));
669 self.$content.appendTo(self.$element);
670 self.$element.find(".logout").click(self.on_logout);
671 self.$element.find("a.preferences").click(self.on_preferences);
672 self.$element.find(".about").click(self.on_about);
673 return self.shortcut_load();
676 this.update_promise = this.update_promise.pipe(fct, fct);
678 on_about: function() {
680 self.rpc("/web/webclient/version_info", {}).then(function(res) {
681 var $help = $(QWeb.render("About-Page", {version_info: res}));
682 $help.dialog({autoOpen: true,
683 modal: true, width: 960, title: "About"});
686 shortcut_load :function(){
688 sc = self.session.shortcuts,
689 shortcuts_ds = new openerp.web.DataSet(this, 'ir.ui.view_sc');
690 // TODO: better way to communicate between sections.
691 // sc.bindings, because jquery does not bind/trigger on arrays...
695 'add': function (e, attrs) {
696 shortcuts_ds.create(attrs, function (out) {
698 'data-shortcut-id':out.result,
699 'data-id': attrs.res_id
701 .appendTo(self.$element.find('.oe-shortcuts ul'));
702 attrs.id = out.result;
706 'remove-current': function () {
707 var menu_id = self.session.active_id;
708 var $shortcut = self.$element
709 .find('.oe-shortcuts li[data-id=' + menu_id + ']');
710 var shortcut_id = $shortcut.data('shortcut-id');
712 shortcuts_ds.unlink([shortcut_id]);
713 var sc_new = _.reject(sc, function(shortcut){ return shortcut_id === shortcut.id});
714 sc.splice(0, sc.length);
715 sc.push.apply(sc, sc_new);
719 return this.rpc('/web/session/sc_list', {}, function(shortcuts) {
720 sc.splice(0, sc.length);
721 sc.push.apply(sc, shortcuts);
723 self.$element.find('.oe-shortcuts')
724 .html(QWeb.render('Shortcuts', {'shortcuts': shortcuts}))
725 .undelegate('li', 'click')
727 .delegate('li', 'click', function(e) {
729 var id = $(this).data('id');
730 self.session.active_id = id;
731 self.rpc('/web/menu/action', {'menu_id':id}, function(ir_menu_data) {
732 if (ir_menu_data.action.length){
733 self.on_action(ir_menu_data.action[0][2]);
740 on_action: function(action) {
742 on_preferences: function(){
744 var action_manager = new openerp.web.ActionManager(this);
745 var dataset = new openerp.web.DataSet (this,'res.users',this.context);
746 dataset.call ('action_get','',function (result){
747 self.rpc('/web/action/load', {action_id:result}, function(result){
748 action_manager.do_action(_.extend(result['result'], {
749 res_id: self.session.uid,
750 res_model: 'res.users',
752 action_buttons: false,
755 views_switcher: false,
761 this.dialog = new openerp.web.Dialog(this,{
763 title: 'Preferences',
767 "Change password": function(){
768 self.change_password();
771 $(this).dialog('destroy');
774 var inner_viewmanager = action_manager.inner_viewmanager;
775 inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save()
778 window.location.reload();
783 this.dialog.start().open();
784 action_manager.appendTo(this.dialog);
785 action_manager.render(this.dialog);
788 change_password :function() {
790 this.dialog = new openerp.web.Dialog(this,{
792 title : 'Change Password',
796 this.dialog.start().open();
797 this.dialog.$element.html(QWeb.render("Change_Pwd", self));
798 this.dialog.$element.find("form[name=change_password_form]").validate({
799 submitHandler: function (form) {
800 self.rpc("/web/session/change_password",{
801 'fields': $(form).serializeArray()
802 }, function(result) {
804 self.display_error(result);
807 self.session.logout();
813 display_error: function (error) {
814 return $('<div>').dialog({
819 $(this).dialog("close");
822 }).html(error.error);
824 on_logout: function() {
828 openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
830 * @constructs openerp.web.Menu
831 * @extends openerp.web.Widget
835 * @param secondary_menu_id
837 init: function(parent, element_id, secondary_menu_id) {
838 this._super(parent, element_id);
839 this.secondary_menu_id = secondary_menu_id;
840 this.$secondary_menu = $("#" + secondary_menu_id);
843 if (window.localStorage) {
844 this.folded = localStorage.getItem('oe_menu_folded') === 'true';
846 this.float_timeout = 700;
849 this.$secondary_menu.addClass(this.folded ? 'oe_folded' : 'oe_unfolded');
851 do_reload: function() {
852 this.rpc("/web/menu/load", {}, this.on_loaded);
854 on_loaded: function(data) {
856 this.$element.html(QWeb.render("Menu", { widget : this }));
857 this.$secondary_menu.html(QWeb.render("Menu.secondary", { widget : this }));
858 this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click);
859 this.$secondary_menu.find('.oe_toggle_secondary_menu').click(this.on_toggle_fold);
861 on_toggle_fold: function() {
862 this.$secondary_menu.toggleClass('oe_folded').toggleClass('oe_unfolded');
864 this.$secondary_menu.find('.oe_secondary_menu.active').show();
866 this.$secondary_menu.find('.oe_secondary_menu').hide();
868 this.folded = !this.folded;
869 if (window.localStorage) {
870 localStorage.setItem('oe_menu_folded', this.folded.toString());
873 on_menu_click: function(ev, id) {
875 var $clicked_menu, manual = false;
878 // We can manually activate a menu with it's id (for hash url mapping)
880 $clicked_menu = this.$element.find('a[data-menu=' + id + ']');
881 if (!$clicked_menu.length) {
882 $clicked_menu = this.$secondary_menu.find('a[data-menu=' + id + ']');
885 $clicked_menu = $(ev.currentTarget);
886 id = $clicked_menu.data('menu');
889 if (this.do_menu_click($clicked_menu, manual) && id) {
890 this.session.active_id = id;
891 this.rpc('/web/menu/action', {'menu_id': id}, this.on_menu_action_loaded);
894 ev.stopPropagation();
898 do_menu_click: function($clicked_menu, manual) {
899 var $sub_menu, $main_menu,
900 active = $clicked_menu.is('.active'),
901 sub_menu_visible = false;
903 if (this.$secondary_menu.has($clicked_menu).length) {
904 $sub_menu = $clicked_menu.parents('.oe_secondary_menu');
905 $main_menu = this.$element.find('a[data-menu=' + $sub_menu.data('menu-parent') + ']');
907 $sub_menu = this.$secondary_menu.find('.oe_secondary_menu[data-menu-parent=' + $clicked_menu.attr('data-menu') + ']');
908 $main_menu = $clicked_menu;
911 sub_menu_visible = $sub_menu.is(':visible');
912 this.$secondary_menu.find('.oe_secondary_menu').hide();
914 $('.active', this.$element.add(this.$secondary_menu)).removeClass('active');
915 $main_menu.add($clicked_menu).add($sub_menu).addClass('active');
917 if (!(this.folded && manual)) {
918 this.do_show_secondary($sub_menu, $main_menu);
921 if ($main_menu != $clicked_menu) {
922 if ($clicked_menu.is('.submenu')) {
923 $sub_menu.find('.submenu.opened').each(function() {
924 if (!$(this).next().has($clicked_menu).length && !$(this).is($clicked_menu)) {
925 $(this).removeClass('opened').next().hide();
928 $clicked_menu.toggleClass('opened').next().toggle();
929 } else if ($clicked_menu.is('.leaf')) {
930 $sub_menu.toggle(!this.folded);
933 } else if (this.folded) {
934 if (active && sub_menu_visible) {
944 do_show_secondary: function($sub_menu, $main_menu) {
947 var css = $main_menu.position(),
948 fold_width = this.$secondary_menu.width() + 2,
949 window_width = $(window).width();
951 css.left -= Math.round(($sub_menu.width() - $main_menu.width()) / 2);
952 css.left = css.left < fold_width ? fold_width : css.left;
953 if ((css.left + $sub_menu.width()) > window_width) {
958 $sub_menu.mouseenter(function() {
959 clearTimeout($sub_menu.data('timeoutId'));
960 }).mouseleave(function(evt) {
961 var timeoutId = setTimeout(function() {
965 }, self.float_timeout);
966 $sub_menu.data('timeoutId', timeoutId);
971 on_menu_action_loaded: function(data) {
973 if (data.action.length) {
974 var action = data.action[0][2];
975 self.on_action(action);
977 self.on_action({type: 'null_action'});
980 on_action: function(action) {
984 openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClient */{
986 * @constructs openerp.web.WebClient
987 * @extends openerp.web.Widget
991 init: function(element_id) {
992 this._super(null, element_id);
993 openerp.webclient = this;
996 if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
997 this.$element.addClass("kitten-mode-activated");
999 this.$element.html(QWeb.render("Interface", params));
1001 this.notification = new openerp.web.Notification(this);
1002 this.loading = new openerp.web.Loading(this);
1003 this.crashmanager = new openerp.web.CrashManager();
1005 this.header = new openerp.web.Header(this);
1006 this.login = new openerp.web.Login(this);
1007 this.header.on_logout.add(this.login.on_logout);
1008 this.header.on_action.add(this.on_menu_action);
1010 this.session.on_session_invalid.add(this.login.do_ask_login);
1011 this.session.on_session_valid.add_last(this.header.do_update);
1012 this.session.on_session_invalid.add_last(this.header.do_update);
1013 this.session.on_session_valid.add_last(this.on_logged);
1014 this.session.on_session_invalid.add_last(this.on_logged_out);
1016 this.menu = new openerp.web.Menu(this, "oe_menu", "oe_secondary_menu");
1017 this.menu.on_action.add(this.on_menu_action);
1019 this.url_internal_hashchange = false;
1020 this.url_external_hashchange = false;
1021 jQuery(window).bind('hashchange', this.on_url_hashchange);
1025 this._super.apply(this, arguments);
1026 this.notification.prependTo(this.$element);
1027 this.loading.appendTo($('#oe_loading'));
1028 this.header.appendTo($("#oe_header"));
1029 this.session.start();
1030 this.login.appendTo($('#oe_login'));
1033 do_reload: function() {
1034 this.session.session_restore();
1035 this.menu.do_reload();
1037 do_notify: function() {
1038 var n = this.notification;
1039 n.notify.apply(n, arguments);
1041 do_warn: function() {
1042 var n = this.notification;
1043 n.warn.apply(n, arguments);
1045 on_logged: function() {
1046 this.menu.do_reload();
1047 if(this.action_manager)
1048 this.action_manager.stop();
1049 this.action_manager = new openerp.web.ActionManager(this);
1050 this.action_manager.appendTo($("#oe_app"));
1052 if (openerp._modules_loaded) { // TODO: find better option than this
1053 this.bind_statechange();
1055 this.session.on_modules_loaded.add({ // XXX what about a $.Deferred ?
1056 callback: $.proxy(this, 'bind_statechange'),
1063 state_change_event: 'hashchange',
1065 bind_statechange: function() {
1066 $(window).bind(this.state_change_event, this.on_state_change);
1068 var state = $.bbq.getState(true);
1069 if (! _.isEmpty(state)) {
1070 $(window).trigger(this.state_change_event);
1072 this.action_manager.do_action({type: 'ir.actions.client', tag: 'default_home'});
1076 on_logged_out: function() {
1077 if(this.action_manager)
1078 this.action_manager.stop();
1079 this.action_manager = null;
1080 $(window).unbind(this.state_change_event, this.on_state_change);
1083 on_state_change: function(event) {
1084 // as this method is bound to a event via jQuery, the argument is the jQuery Event.. we need to get the current state
1085 var state = event.getState(true); // = bbq.getState, in fact only deparam the hash
1086 return this._super(state);
1091 do_push_state: function(state, extend) {
1093 var hash = $.deparam.fragment(true);
1094 state = _.extend({}, hash, state);
1096 var url = '#' + $.param(state);
1097 $.bbq.pushState(url); // will set the hash, so will call on_state_change
1100 default_home: function () {
1103 * Bundles the execution of the home action
1105 * @param {Number} action action id
1106 * @param {openerp.web.DataSet} dataset action executor
1108 execute_home_action: function (action, dataset) {
1110 this.rpc('/web/action/load', {
1112 context: dataset.get_context()
1114 var action = meh.result;
1115 action.context = _.extend(action.context || {}, {
1117 active_ids: [false],
1118 active_model: dataset.model
1120 self.action_manager.do_action(action);
1124 on_menu_action: function(action) {
1125 this.action_manager.do_action(action);
1127 do_about: function() {
1134 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: