X-Git-Url: http://git.inspyration.org/?a=blobdiff_plain;f=addons%2Fweb%2Fstatic%2Fsrc%2Fjs%2Fviews.js;h=e6d404701a1b6bc272bc78a057b1030b3b36f7fd;hb=648ea3e7ca278796ac781f1ba918235fe31cbf4a;hp=78f365c1a16436849bcea3f031abbda5fbee0ee5;hpb=11c0136907b0b5bd96fd4e53e481c5542f0be7f4;p=odoo%2Fodoo.git diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 78f365c..e6d4047 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -2,11 +2,11 @@ * OpenERP web library *---------------------------------------------------------*/ -openerp.web.views = function(session) { -var QWeb = session.web.qweb, - _t = session.web._t; +openerp.web.views = function(instance) { +var QWeb = instance.web.qweb, + _t = instance.web._t; -session.web.ActionManager = session.web.Widget.extend({ +instance.web.ActionManager = instance.web.Widget.extend({ init: function(parent) { this._super(parent); this.inner_action = null; @@ -15,6 +15,10 @@ session.web.ActionManager = session.web.Widget.extend({ this.dialog_viewmanager = null; this.client_widget = null; }, + start: function() { + this._super.apply(this, arguments); + this.breadcrumb = new instance.web.BreadCrumb(this); + }, dialog_stop: function () { if (this.dialog) { this.dialog_viewmanager.destroy(); @@ -24,6 +28,7 @@ session.web.ActionManager = session.web.Widget.extend({ } }, content_stop: function () { + // TODO: problem with bread crumb here. Check if those references are needed if (this.inner_viewmanager) { this.inner_viewmanager.destroy(); this.inner_viewmanager = null; @@ -36,6 +41,7 @@ session.web.ActionManager = session.web.Widget.extend({ do_push_state: function(state) { if (this.getParent() && this.getParent().do_push_state) { if (this.inner_action) { + state['title'] = this.inner_action.name; state['model'] = this.inner_action.res_model; if (this.inner_action.id) { state['action_id'] = this.inner_action.id; @@ -52,8 +58,8 @@ session.web.ActionManager = session.web.Widget.extend({ if (run_action) { this.null_action(); action_loaded = this.do_action(state.action_id); - session.webclient.menu.has_been_loaded.then(function() { - session.webclient.menu.open_action(state.action_id); + instance.webclient.menu.has_been_loaded.then(function() { + instance.webclient.menu.open_action(state.action_id); }); } } else if (state.model && state.id) { @@ -77,7 +83,14 @@ session.web.ActionManager = session.web.Widget.extend({ }); } else if (state.client_action) { this.null_action(); - this.ir_actions_client(state.client_action); + var action = state.client_action; + if(_.isString(action)) { + action = { + tag: action, + params: state, + }; + } + this.ir_actions_client(action); } $.when(action_loaded || null).then(function() { @@ -124,32 +137,36 @@ session.web.ActionManager = session.web.Widget.extend({ .contains(action.res_model)) { var old_close = on_close; on_close = function () { - session.webclient.do_reload().then(old_close); + instance.webclient.do_reload().then(old_close); }; } if (action.target === 'new') { - if (this.dialog == null) { - this.dialog = new session.web.Dialog(this, { width: '80%' }); + if (this.dialog === null) { + this.dialog = new instance.web.Dialog(this, { width: '80%' }); if(on_close) this.dialog.on_close.add(on_close); } else { this.dialog_viewmanager.destroy(); } this.dialog.dialog_title = action.name; - this.dialog_viewmanager = new session.web.ViewManagerAction(this, action); + this.dialog_viewmanager = new instance.web.ViewManagerAction(this.dialog, action); this.dialog_viewmanager.appendTo(this.dialog.$element); + this.dialog_viewmanager.$element.addClass("oe_view_manager_" + action.target); this.dialog.open(); } else { + this.dialog_stop(); + //this.content_stop(); + this.breadcrumb.hide_items(); if(action.menu_id) { return this.getParent().do_action(action, function () { - session.webclient.menu.open_menu(action.menu_id); + instance.webclient.menu.open_menu(action.menu_id); }); } - this.dialog_stop(); - this.content_stop(); this.inner_action = action; - this.inner_viewmanager = new session.web.ViewManagerAction(this, action); + var inner_viewmanager = this.inner_viewmanager = new instance.web.ViewManagerAction(this, action); + this.breadcrumb.push_actionmanager(inner_viewmanager); this.inner_viewmanager.appendTo(this.$element); + this.inner_viewmanager.$element.addClass("oe_view_manager_" + action.target); } }, ir_actions_act_window_close: function (action, on_closed) { @@ -168,10 +185,16 @@ session.web.ActionManager = session.web.Widget.extend({ }); }, ir_actions_client: function (action) { - this.content_stop(); + //this.content_stop(); this.dialog_stop(); - var ClientWidget = session.web.client_actions.get_object(action.tag); - (this.client_widget = new ClientWidget(this, action.params)).appendTo(this.$element); + this.breadcrumb.hide_items(); + var ClientWidget = instance.web.client_actions.get_object(action.tag); + this.client_widget = new ClientWidget(this, action.params); + this.breadcrumb.push({ + widget: this.client_widget, + title: action.name + }); + this.client_widget.appendTo(this.$element); }, ir_actions_report_xml: function(action, on_closed) { var self = this; @@ -192,7 +215,7 @@ session.web.ActionManager = session.web.Widget.extend({ } self.dialog_stop(); }, - error: session.webclient.crashmanager.on_rpc_error + error: instance.webclient.crashmanager.on_rpc_error }) }); }, @@ -204,7 +227,106 @@ session.web.ActionManager = session.web.Widget.extend({ } }); -session.web.ViewManager = session.web.Widget.extend({ +instance.web.BreadCrumb = instance.web.CallbackEnabled.extend({ + init: function(parent) { + this._super(parent); + this.action_manager = parent; + this.items = []; + this.action_manager.$element.on('click', '.oe_breadcrumb_item', this.on_item_clicked); + }, + push: function(item) { + item.show = item.show || function() { + item.widget.$element.show(); + }; + item.hide = item.hide || function() { + item.widget.$element.hide(); + }; + item.destroy = item.destroy || function() { + item.widget.destroy(); + }; + item.get_title = item.get_title || function() { + return item.title || item.widget.get('title'); + }; + console.log("breadcrumb push", item); + this.items.push(item); + }, + push_actionmanager: function(am, view_type) { + var self = this; + var bookmarked_view = view_type || am.active_view || am.views_src[0].view_type; + this.push({ + widget: am, + show: function() { + am.$element.show(); + if (am.active_view !== bookmarked_view) { + am.on_mode_switch(bookmarked_view); + am.set_title(); + } + }, + get_title: function() { + return am.views[bookmarked_view].controller.get('title'); + } + }); + if (bookmarked_view !== 'form') { + am.on_mode_switch.add_first(function(mode) { + if (mode === 'form') { + self.push_actionmanager(am, 'form'); + } else { + // select previous to form and remove form + } + }); + } + }, + pop: function() { + this.remove_item(this.items.length - 1); + this.select_item(this.items.length - 1); + }, + get_title: function() { + return QWeb.render('BreadCrumb', { widget: this }); + }, + hide_items: function() { + _.each(this.items, function(i) { + i.hide(); + }); + }, + on_item_clicked: function(ev) { + var $e = $(ev.target); + var index = $e.data('index'); + this.select_item(index); + }, + select_item: function(index) { + for (var i = index + 1; i < this.items.length; i += 1) { + this.remove_item(i); + } + var item = this.items[index]; + if (item) { + item.show(); + } else { + console.warn("Breadcrumb: Can't select item at index", index); + } + }, + remove_item: function(index) { + console.log("Breadcrumb remove index", index); + var item = this.items.splice(index, 1)[0]; + if (item) { + var dups = _.filter(this.items, function(it) { + return item.widget === it.widget; + }); + if (dups.length === 0) { + console.log("Breadcrumb Destroy", item); + item.destroy(); + } + } else { + console.warn("Breadcrumb: Can't remove item at index", index); + } + }, + clear: function() { + while (this.items.length) { + this.remove_item(0); + } + }, +}); + +instance.web.ViewManager = instance.web.Widget.extend({ template: "ViewManager", init: function(parent, dataset, views, flags) { this._super(parent); @@ -214,7 +336,7 @@ session.web.ViewManager = session.web.Widget.extend({ this.active_view = null; this.views_src = _.map(views, function(x) { if (x instanceof Array) { - var View = session.web.views.get_object(x[1], true); + var View = instance.web.views.get_object(x[1], true); return { view_id: x[0], view_type: x[1], @@ -226,7 +348,7 @@ session.web.ViewManager = session.web.Widget.extend({ }); this.views = {}; this.flags = flags || {}; - this.registry = session.web.views; + this.registry = instance.web.views; this.views_history = []; }, /** @@ -237,7 +359,7 @@ session.web.ViewManager = session.web.Widget.extend({ var self = this; this.$element.find('.oe_view_manager_switch a').click(function() { self.on_mode_switch($(this).data('view-type')); - }); + }).tipsy(); var views_ids = {}; _.each(this.views_src, function(view) { self.views[view.view_type] = $.extend({}, view, { @@ -245,7 +367,7 @@ session.web.ViewManager = session.web.Widget.extend({ controller : null, options : _.extend({ $buttons : self.$element.find('.oe_view_manager_buttons'), - $sidebar : self.$element.find('.oe_view_manager_sidebar'), + $sidebar : self.flags.sidebar ? self.$element.find('.oe_view_manager_sidebar') : undefined, $pager : self.$element.find('.oe_view_manager_pager'), action : self.action, action_views_ids : views_ids @@ -267,7 +389,7 @@ session.web.ViewManager = session.web.Widget.extend({ * @param {Boolean} [no_store=false] don't store the view being switched to on the switch stack * @returns {jQuery.Deferred} new view loading promise */ - on_mode_switch: function(view_type, no_store) { + on_mode_switch: function(view_type, no_store, view_options) { var self = this; var view = this.views[view_type]; var view_promise; @@ -280,35 +402,7 @@ session.web.ViewManager = session.web.Widget.extend({ this.active_view = view_type; if (!view.controller) { - // Lazy loading of views - var controllerclass = this.registry.get_object(view_type); - var options = _.clone(view.options); - if (view_type === "form") { - switch (this.action.target) { - case 'new': - case 'inline': - options.initial_mode = 'edit'; - break; - } - } - var controller = new controllerclass(this, this.dataset, view.view_id, options); - if (view.embedded_view) { - controller.set_embedded_view(view.embedded_view); - } - controller.do_switch_view.add_last(this.on_mode_switch); - controller.do_prev_view.add_last(this.on_prev_view); - var container = this.$element.find(".oe_view_manager_view_" + view_type); - view_promise = controller.appendTo(container); - this.views[view_type].controller = controller; - this.views[view_type].deferred.resolve(view_type); - $.when(view_promise).then(function() { - self.on_controller_inited(view_type, controller); - if (self.searchview - && self.flags.auto_search - && view.controller.searchable !== false) { - self.searchview.ready.then(self.searchview.do_search); - } - }); + view_promise = this.do_create_view(view_type); } else if (this.searchview && self.flags.auto_search && view.controller.searchable !== false) { @@ -320,7 +414,7 @@ session.web.ViewManager = session.web.Widget.extend({ } this.$element - .find('.oe_view_manager_switch a').parent().removeClass('active') + .find('.oe_view_manager_switch a').parent().removeClass('active'); this.$element .find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]') .parent().addClass('active'); @@ -329,19 +423,71 @@ session.web.ViewManager = session.web.Widget.extend({ _.each(_.keys(self.views), function(view_name) { var controller = self.views[view_name].controller; if (controller) { + var container = self.$element.find(".oe_view_manager_view_" + view_name + ":first"); if (view_name === view_type) { - controller.do_show(); + container.show(); + controller.do_show(view_options || {}); } else { + container.hide(); controller.do_hide(); } } }); - - self.$element.find('.oe_view_title_text:first').text( - self.display_title()); }); return view_promise; }, + do_create_view: function(view_type) { + // Lazy loading of views + var self = this; + var view = this.views[view_type]; + var controllerclass = this.registry.get_object(view_type); + var options = _.clone(view.options); + if (view_type === "form" && this.action) { + switch (this.action.target) { + case 'new': + case 'inline': + options.initial_mode = 'edit'; + break; + } + } + var controller = new controllerclass(this, this.dataset, view.view_id, options); + + controller.on("change:title", this, function() { + if (self.active_view === view_type) { + self.set_title(controller.get('title')); + } + }); + + if (view.embedded_view) { + controller.set_embedded_view(view.embedded_view); + } + controller.do_switch_view.add_last(_.bind(this.switch_view, this)); + + controller.do_prev_view.add_last(this.on_prev_view); + var container = this.$element.find(".oe_view_manager_view_" + view_type); + var view_promise = controller.appendTo(container); + this.views[view_type].controller = controller; + this.views[view_type].deferred.resolve(view_type); + return $.when(view_promise).then(function() { + self.on_controller_inited(view_type, controller); + if (self.searchview + && self.flags.auto_search + && view.controller.searchable !== false) { + self.searchview.ready.then(self.searchview.do_search); + } + }); + }, + set_title: function(title) { + this.$element.find('.oe_view_title_text:first').text(title); + }, + /** + * Method used internally when a view asks to switch view. This method is meant + * to be extended by child classes to change the default behavior, which simply + * consist to switch to the asked view. + */ + switch_view: function(view_type, no_store, options) { + return this.on_mode_switch(view_type, no_store, options); + }, /** * Returns to the view preceding the caller view in this manager's * navigation history (the navigation history is appended to via @@ -353,6 +499,7 @@ session.web.ViewManager = session.web.Widget.extend({ * @returns {$.Deferred} switching end signal */ on_prev_view: function (options) { + options = options || {}; var current_view = this.views_history.pop(); var previous_view = this.views_history[this.views_history.length - 1] || options['default']; if (options.created && current_view === 'form' && previous_view === 'list') { @@ -376,7 +523,7 @@ session.web.ViewManager = session.web.Widget.extend({ if (this.searchview) { this.searchview.destroy(); } - this.searchview = new session.web.SearchView(this, this.dataset, view_id, search_defaults, this.flags.search_view === false); + this.searchview = new instance.web.SearchView(this, this.dataset, view_id, search_defaults, this.flags.search_view === false); this.searchview.on_search.add(this.do_searchview_search); return this.searchview.appendTo(this.$element.find(".oe_view_manager_view_search")); @@ -390,8 +537,8 @@ session.web.ViewManager = session.web.Widget.extend({ contexts: [action_context].concat(contexts || []), group_by_seq: groupbys || [] }, function (results) { - self.dataset.context = results.context; - self.dataset.domain = results.domain; + self.dataset._model = new instance.web.Model( + self.dataset.model, results.context, results.domain); var groupby = results.group_by.length ? results.group_by : action_context.group_by; @@ -425,23 +572,15 @@ session.web.ViewManager = session.web.Widget.extend({ */ on_action_executed: function () { }, - display_title: function () { - var view = this.views[this.active_view]; - if (view) { - // ick - return view.controller.fields_view.arch.attrs.string; - } - return ''; - } }); -session.web.ViewManagerAction = session.web.ViewManager.extend({ +instance.web.ViewManagerAction = instance.web.ViewManager.extend({ template:"ViewManagerAction", /** - * @constructs session.web.ViewManagerAction - * @extends session.web.ViewManager + * @constructs instance.web.ViewManagerAction + * @extends instance.web.ViewManager * - * @param {session.web.ActionManager} parent parent object/widget + * @param {instance.web.ActionManager} parent parent object/widget * @param {Object} action descriptor for the action this viewmanager needs to manage its views. */ init: function(parent, action) { @@ -466,7 +605,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ this._super(parent, null, action.views, flags); this.session = parent.session; this.action = action; - var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain); + var dataset = new instance.web.DataSetSearch(this, action.res_model, action.context, action.domain); if (action.res_id) { dataset.ids.push(action.res_id); dataset.index = 0; @@ -477,7 +616,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ if (this.session.hidden_menutips) { return; } - this.session.hidden_menutips = {} + this.session.hidden_menutips = {}; }, /** * Initializes the ViewManagerAction: sets up the searchview (if the @@ -507,7 +646,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ this.$element.find('.oe_debug_view').change(this.on_debug_changed); if (this.action.help && !this.flags.low_profile) { - var Users = new session.web.DataSet(self, 'res.users'), + var Users = new instance.web.DataSet(self, 'res.users'), $tips = this.$element.find('.oe_view_manager_menu_tips'); $tips.delegate('blockquote button', 'click', function() { var $this = $(this); @@ -541,19 +680,19 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ current_view = this.views[this.active_view].controller; switch (val) { case 'fvg': - var dialog = new session.web.Dialog(this, { title: _t("Fields View Get"), width: '95%' }).open(); - $('
').text(session.web.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$element);
+                var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get"), width: '95%' }).open();
+                $('
').text(instance.web.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$element);
                 break;
             case 'perm_read':
                 var ids = current_view.get_selected_ids();
                 if (ids.length === 1) {
                     this.dataset.call('perm_read', [ids]).then(function(result) {
-                        var dialog = new session.web.Dialog(this, {
+                        var dialog = new instance.web.Dialog(this, {
                             title: _.str.sprintf(_t("View Log (%s)"), self.dataset.model),
                             width: 400
                         }, QWeb.render('ViewManagerDebugViewLog', {
                             perm : result[0],
-                            format : session.web.format_value
+                            format : instance.web.format_value
                         })).open();
                     });
                 }
@@ -578,7 +717,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({
                                 .append($('
').text(def)); }); }); - new session.web.Dialog(self, { + new instance.web.Dialog(self, { title: _.str.sprintf(_t("Model %s fields"), self.dataset.model), width: '95%'}, $root).open(); @@ -586,7 +725,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ break; case 'manage_views': if (current_view.fields_view && current_view.fields_view.arch) { - var view_editor = new session.web.ViewEditor(current_view, current_view.$element, this.dataset, current_view.fields_view.arch); + var view_editor = new instance.web.ViewEditor(current_view, current_view.$element, this.dataset, current_view.fields_view.arch); view_editor.start(); } else { this.do_warn(_t("Manage Views"), @@ -606,6 +745,17 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ case 'edit': this.do_edit_resource($option.data('model'), $option.data('id'), { name : $option.text() }); break; + case 'manage_filters': + this.do_action({ + res_model: 'ir.filters', + views: [[false, 'list'], [false, 'form']], + type: 'ir.actions.act_window', + context: { + search_default_my_filters: true, + search_default_model_id: this.dataset.model + } + }); + break; default: if (val) { console.log("No debug handler for ", val); @@ -631,12 +781,10 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ }, action || {}); this.do_action(action); }, - on_mode_switch: function (view_type, no_store) { + on_mode_switch: function (view_type, no_store, options) { var self = this; - return $.when(this._super(view_type, no_store)).then(function () { - self.shortcut_check(self.views[view_type]); - + return $.when(this._super.apply(this, arguments)).then(function () { var controller = self.views[self.active_view].controller, fvg = controller.fields_view, view_id = (fvg && fvg.view_id) || '--'; @@ -648,17 +796,20 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ self.$element.find('.oe_view_title_text').text(fvg.arch.attrs.string || fvg.name); } - var $title = self.$element.find('.oe_view_title_text'), - $search_prefix = $title.find('span.oe_searchable_view'); - if (controller.searchable !== false && self.flags.search_view !== false) { - if (!$search_prefix.length) { - $title.prepend('' + _t("Search: ") + ''); - } - } else { - $search_prefix.remove(); - } }); }, + do_create_view: function(view_type) { + var r = this._super.apply(this, arguments); + var view = this.views[view_type].controller; + view.set({ 'title': this.action.name }); + return r; + }, + set_title: function(title) { + var breadcrumb = this.getParent().breadcrumb; + if (breadcrumb) { + this.$element.find('.oe_breadcrumb_title:first').html(breadcrumb.get_title()); + } + }, do_push_state: function(state) { if (this.getParent() && this.getParent().do_push_state) { state["view_type"] = this.active_view; @@ -680,121 +831,63 @@ session.web.ViewManagerAction = session.web.ViewManager.extend({ self.views[self.active_view].controller.do_load_state(state, warm); }); }, - shortcut_check : function(view) { - var self = this; - var grandparent = this.getParent() && this.getParent().getParent(); - // display shortcuts if on the first view for the action - var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); - if (!this.action.name || - !(view.view_type === this.views_src[0].view_type - && view.view_id === this.views_src[0].view_id)) { - $shortcut_toggle.hide(); - return; - } - $shortcut_toggle.removeClass('oe-shortcut-remove').show(); - if (_(this.session.shortcuts).detect(function (shortcut) { - return shortcut.res_id === self.session.active_id; })) { - $shortcut_toggle.addClass("oe-shortcut-remove"); - } - this.shortcut_add_remove(); - }, - shortcut_add_remove: function() { - var self = this; - var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); - $shortcut_toggle - .unbind("click") - .click(function() { - if ($shortcut_toggle.hasClass("oe-shortcut-remove")) { - $(self.session.shortcuts.binding).trigger('remove-current'); - $shortcut_toggle.removeClass("oe-shortcut-remove"); - } else { - $(self.session.shortcuts.binding).trigger('add', { - 'user_id': self.session.uid, - 'res_id': self.session.active_id, - 'resource': 'ir.ui.menu', - 'name': self.action.name - }); - $shortcut_toggle.addClass("oe-shortcut-remove"); - } - }); - }, - display_title: function () { - return this.action.name; - } }); -session.web.Sidebar = session.web.Widget.extend({ +instance.web.Sidebar = instance.web.Widget.extend({ init: function(parent) { + var self = this; this._super(parent); var view = this.getParent(); - var view_manager = view.getParent(); - var action = view_manager.action; this.sections = [ { 'name' : 'print', 'label' : _t('Print'), }, - { 'name' : 'files', 'label' : _t('Attachement'), }, + { 'name' : 'files', 'label' : _t('Attachment'), }, { 'name' : 'other', 'label' : _t('More'), } ]; this.items = { 'print' : [], 'files' : [], - 'other' : [ - { label: _t("Import"), callback: view.on_sidebar_import }, - { label: _t("Export"), callback: view.on_sidebar_export } - ] - } + 'other' : [] + }; if (this.session.uid === 1) { var item = { label: _t("Translate"), callback: view.on_sidebar_translate, title: _t("Technical translation") }; this.items.other.push(item); } + this.fileupload_id = _.uniqueId('oe_fileupload'); + $(window).on(this.fileupload_id, function() { + var args = [].slice.call(arguments).slice(1); + if (args[0] && args[0].error) { + alert(args[0].error); + } else { + self.do_attachement_update(self.dataset, self.model_id); + } + $.unblockUI(); + }); }, start: function() { var self = this; this._super(this); this.redraw(); - this.$element.on('click','.oe_dropdown_toggle',function(event) { - $(this).parent().find('ul').toggle(); - return false; - }); this.$element.on('click','.oe_dropdown_menu li a', function(event) { var section = $(this).data('section'); var index = $(this).data('index'); - $(this).closest('ul').hide(); - console.log('click item',section,index); var item = self.items[section][index]; if (item.callback) { item.callback.apply(self, [item]); - } - if (item.action) { + } else if (item.action) { self.on_item_action_clicked(item); + } else if (item.url) { + return true; } - return false; + event.preventDefault(); }); }, redraw: function() { var self = this; self.$element.html(QWeb.render('Sidebar', {widget: self})); - this.$element.find('ul').hide(); - }, - add_default_sections: function() { - var self = this; - }, - add_section: function() { - var self = this; - }, - add_toolbar: function(toolbar) { - var self = this; - _.each(['print','action','relate'], function(type) { - var items = toolbar[type]; - if (items) { - for (var i = 0; i < items.length; i++) { - items[i] = { - label: items[i]['name'], - action: items[i], - classname: 'oe_sidebar_' + type - } - } - self.add_items(type=='print' ? 'print' : 'other', items); - } + + // Hides Sidebar sections when item list is empty + this.$('.oe_form_dropdown_section').each(function() { + $(this).toggle(!!$(this).find('li').length); }); }, /** @@ -829,12 +922,28 @@ session.web.Sidebar = session.web.Widget.extend({ this.redraw(); } }, + add_toolbar: function(toolbar) { + var self = this; + _.each(['print','action','relate'], function(type) { + var items = toolbar[type]; + if (items) { + for (var i = 0; i < items.length; i++) { + items[i] = { + label: items[i]['name'], + action: items[i], + classname: 'oe_sidebar_' + type + } + } + self.add_items(type=='print' ? 'print' : 'other', items); + } + }); + }, on_item_action_clicked: function(item) { var self = this; self.getParent().sidebar_context().then(function (context) { var ids = self.getParent().get_selected_ids(); if (ids.length == 0) { - session.web.dialog($("
").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true }); + instance.web.dialog($("
").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true }); return false; } var additional_context = _.extend({ @@ -857,16 +966,64 @@ session.web.Sidebar = session.web.Widget.extend({ }); }); }, + do_attachement_update: function(dataset, model_id) { + this.dataset = dataset; + this.model_id = model_id; + if (!model_id) { + this.on_attachments_loaded([]); + } else { + var dom = [ ['res_model', '=', dataset.model], ['res_id', '=', model_id], ['type', 'in', ['binary', 'url']] ]; + var ds = new instance.web.DataSetSearch(this, 'ir.attachment', dataset.get_context(), dom); + ds.read_slice(['name', 'url', 'type'], {}).then(this.on_attachments_loaded); + } + }, + on_attachments_loaded: function(attachments) { + var self = this; + var items = []; + var prefix = this.session.origin + '/web/binary/saveas?session_id=' + self.session.session_id + '&model=ir.attachment&field=datas&filename_field=name&id='; + _.each(attachments,function(a) { + a.label = a.name; + if(a.type === "binary") { + a.url = prefix + a.id + '&t=' + (new Date().getTime()); + } + }); + self.items['files'] = attachments; + self.redraw(); + this.$('.oe_sidebar_add_attachment .oe_form_binary_file').change(this.on_attachment_changed); + this.$element.find('.oe_sidebar_delete_item').click(this.on_attachment_delete); + }, + on_attachment_changed: function(e) { + var $e = $(e.target); + if ($e.val() !== '') { + this.$element.find('form.oe_form_binary_form').submit(); + $e.parent().find('input[type=file]').prop('disabled', true); + $e.parent().find('button').prop('disabled', true).find('img, span').toggle(); + this.$('.oe_sidebar_add_attachment span').text(_t('Uploading...')); + $.blockUI(); + } + }, + on_attachment_delete: function(e) { + var self = this; + e.preventDefault(); + e.stopPropagation(); + var self = this; + var $e = $(e.currentTarget); + if (confirm(_t("Do you really want to delete this attachment ?"))) { + (new instance.web.DataSet(this, 'ir.attachment')).unlink([parseInt($e.attr('data-id'), 10)]).then(function() { + self.do_attachement_update(self.dataset, self.model_id); + }); + } + } }); -session.web.TranslateDialog = session.web.Dialog.extend({ +instance.web.TranslateDialog = instance.web.Dialog.extend({ dialog_title: {toString: function () { return _t("Translations"); }}, init: function(view) { // TODO fme: should add the language to fields_view_get because between the fields view get // and the moment the user opens the translation dialog, the user language could have been changed this.view_language = view.session.user_context.lang; - this['on_button' + _t("Save")] = this.on_button_Save; - this['on_button' + _t("Close")] = this.on_button_Close; + this['on_button_' + _t("Save")] = this.on_btn_save; + this['on_button_' + _t("Close")] = this.on_btn_close; this._super(view, { width: '80%', height: '80%' @@ -879,14 +1036,14 @@ session.web.TranslateDialog = session.web.Dialog.extend({ this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name }); this.languages = null; this.languages_loaded = $.Deferred(); - (new session.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(), + (new instance.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(), [['translatable', '=', '1']])).read_slice(['code', 'name'], { sort: 'id' }).then(this.on_languages_loaded); }, start: function() { var self = this; this._super(); $.when(this.languages_loaded).then(function() { - self.$element.html(session.web.qweb.render('TranslateDialog', { widget: self })); + self.$element.html(instance.web.qweb.render('TranslateDialog', { widget: self })); self.$fields_form = self.$element.find('.oe_translation_form'); self.$fields_form.find('.oe_trad_field').change(function() { $(this).toggleClass('touched', ($(this).val() != $(this).attr('data-value'))); @@ -947,7 +1104,7 @@ session.web.TranslateDialog = session.web.Dialog.extend({ } }); }, - on_button_Save: function() { + on_btn_save: function() { var trads = {}, self = this, trads_mutex = new $.Mutex(); @@ -970,12 +1127,12 @@ session.web.TranslateDialog = session.web.Dialog.extend({ }); this.close(); }, - on_button_Close: function() { + on_btn_close: function() { this.close(); } }); -session.web.View = session.web.Widget.extend({ +instance.web.View = instance.web.Widget.extend({ template: "EmptyComponent", // name displayed in view switchers display_name: '', @@ -999,14 +1156,14 @@ session.web.View = session.web.Widget.extend({ $.async_when().then(function() {def.resolve(self.embedded_view);}); return def.pipe(this.on_loaded); } else { - var context = new session.web.CompoundContext(this.dataset.get_context()); + var context = new instance.web.CompoundContext(this.dataset.get_context()); if (! this.view_type) console.warn("view_type is not defined", this); return this.rpc("/web/view/load", { "model": this.dataset.model, "view_id": this.view_id, "view_type": this.view_type, - toolbar: this.options.sidebar, + toolbar: !!this.options.$sidebar, context: context }).pipe(this.on_loaded); } @@ -1023,14 +1180,13 @@ session.web.View = session.web.Widget.extend({ // All possible views options should be defaulted here $sidebar: null, sidebar_id: null, - sidebar: true, action: null, action_views_ids: {} }); }, open_translate_dialog: function(field) { if (!this.translate_dialog) { - this.translate_dialog = new session.web.TranslateDialog(this).start(); + this.translate_dialog = new instance.web.TranslateDialog(this).start(); } this.translate_dialog.open(field); }, @@ -1042,7 +1198,7 @@ session.web.View = session.web.Widget.extend({ * @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``) * @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'`` * @param {Object} [action_data.context=null] additional action context, to add to the current context - * @param {session.web.DataSet} dataset a dataset object used to communicate with the server + * @param {instance.web.DataSet} dataset a dataset object used to communicate with the server * @param {Object} [record_id] the identifier of the object on which the action is to be applied * @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action) */ @@ -1054,12 +1210,12 @@ session.web.View = session.web.Widget.extend({ return self.getParent().on_action_executed.apply(null, arguments); } }; - var context = new session.web.CompoundContext(dataset.get_context(), action_data.context || {}); + var context = new instance.web.CompoundContext(dataset.get_context(), action_data.context || {}); var handler = function (r) { var action = r.result; if (action && action.constructor == Object) { - var ncontext = new session.web.CompoundContext(context); + var ncontext = new instance.web.CompoundContext(context); if (record_id) { ncontext.add({ active_id: record_id, @@ -1108,13 +1264,12 @@ session.web.View = session.web.Widget.extend({ /** * Directly set a view to use instead of calling fields_view_get. This method must * be called before start(). When an embedded view is set, underlying implementations - * of session.web.View must use the provided view instead of any other one. + * of instance.web.View must use the provided view instead of any other one. * * @param embedded_view A view. */ set_embedded_view: function(embedded_view) { this.embedded_view = embedded_view; - this.options.sidebar = false; }, do_show: function () { this.$element.show(); @@ -1147,15 +1302,12 @@ session.web.View = session.web.Widget.extend({ }, do_search: function(view) { }, - set_common_sidebar_sections: function(sidebar) { - sidebar.add_default_sections(); - }, on_sidebar_import: function() { - var import_view = new session.web.DataImport(this, this.dataset); + var import_view = new instance.web.DataImport(this, this.dataset); import_view.start(); }, on_sidebar_export: function() { - var export_view = new session.web.DataExport(this, this.dataset); + var export_view = new instance.web.DataExport(this, this.dataset); export_view.start(); }, on_sidebar_translate: function() { @@ -1180,7 +1332,7 @@ session.web.View = session.web.Widget.extend({ } }); -session.web.xml_to_json = function(node) { +instance.web.xml_to_json = function(node) { switch (node.nodeType) { case 3: case 4: @@ -1198,11 +1350,11 @@ session.web.xml_to_json = function(node) { return { tag: node.tagName.toLowerCase(), attrs: attrs, - children: _.map(node.childNodes, session.web.xml_to_json) + children: _.map(node.childNodes, instance.web.xml_to_json) } } } -session.web.json_node_to_xml = function(node, human_readable, indent) { +instance.web.json_node_to_xml = function(node, human_readable, indent) { // For debugging purpose, this function will convert a json node back to xml // Maybe useful for xml view editor indent = indent || 0; @@ -1231,7 +1383,7 @@ session.web.json_node_to_xml = function(node, human_readable, indent) { r += '>' + cr; var childs = []; for (var i = 0, ii = node.children.length; i < ii; i++) { - childs.push(session.web.json_node_to_xml(node.children[i], human_readable, indent + 1)); + childs.push(instance.web.json_node_to_xml(node.children[i], human_readable, indent + 1)); } r += childs.join(cr); r += cr + sindent + ''; @@ -1240,14 +1392,14 @@ session.web.json_node_to_xml = function(node, human_readable, indent) { return r + '/>'; } } -session.web.xml_to_str = function(node) { +instance.web.xml_to_str = function(node) { if (window.ActiveXObject) { return node.xml; } else { return (new XMLSerializer()).serializeToString(node); } } -session.web.str_to_xml = function(s) { +instance.web.str_to_xml = function(s) { if (window.DOMParser) { var dp = new DOMParser(); var r = dp.parseFromString(s, "text/xml"); @@ -1269,14 +1421,9 @@ session.web.str_to_xml = function(s) { } /** - * Registry for all the client actions key: tag value: widget - */ -session.web.client_actions = new session.web.Registry(); - -/** * Registry for all the main views */ -session.web.views = new session.web.Registry(); +instance.web.views = new instance.web.Registry(); };