diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index e463fec12e3..94357c0131b 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1012,18 +1012,7 @@ class Session(http.Controller): :return: A key identifying the saved action. :rtype: integer """ - saved_actions = request.httpsession.get('saved_actions') - if not saved_actions: - saved_actions = {"next":1, "actions":{}} - request.httpsession['saved_actions'] = saved_actions - # we don't allow more than 10 stored actions - if len(saved_actions["actions"]) >= 10: - del saved_actions["actions"][min(saved_actions["actions"])] - key = saved_actions["next"] - saved_actions["actions"][key] = the_action - saved_actions["next"] = key + 1 - request.httpsession['saved_actions'] = saved_actions - return key + return request.httpsession.save_action(the_action) @http.route('/web/session/get_session_action', type='json', auth="user") def get_session_action(self, key): @@ -1036,10 +1025,7 @@ class Session(http.Controller): :return: The saved action or None. :rtype: anything """ - saved_actions = request.httpsession.get('saved_actions') - if not saved_actions: - return None - return saved_actions["actions"].get(key) + return request.httpsession.get_action(key) @http.route('/web/session/check', type='json', auth="user") def check(self): diff --git a/addons/web/static/src/css/Makefile b/addons/web/static/src/css/Makefile index f4f1f6d1bb5..ba88946baac 100644 --- a/addons/web/static/src/css/Makefile +++ b/addons/web/static/src/css/Makefile @@ -1,2 +1,5 @@ -sass: - sass -t expanded --compass --unix-newlines --watch base.sass:base.css& \ No newline at end of file +all: *.css +%.css: %.sass + sass -t expanded --compass --unix-newlines $< $@ +watch: + sass -t expanded --compass --unix-newlines --watch .:. diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 6b568f8846e..e43a2fb654e 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -78,6 +78,20 @@ .openerp td { vertical-align: top; } +.openerp .oe_title { + width: 50%; + float: left; +} +.openerp .oe_title:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +.openerp .oe_form_group { + clear: both; +} .openerp .zebra tbody tr:nth-child(odd) td { background-color: #f0f0fa; background-color: #efeff8; @@ -1205,10 +1219,7 @@ .openerp .oe_about .oe_bottom a { color: #eeeeee; } -.openerp .oe_form_uri { - color: #7c7bad; -} -.openerp .oe_form_uri:hover { +.openerp a.oe_form_uri:hover { text-decoration: underline; } .openerp .oe_application { @@ -1594,7 +1605,6 @@ border-radius: 0 3px 3px 0; } .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value { - height: 18px; padding: 0 4px; } .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category { @@ -2021,7 +2031,6 @@ } .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button { margin: 3px 2px 1px; - float: left; } .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button:first-child { margin-left: 6px; @@ -2142,7 +2151,7 @@ } .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span { font-size: 80%; - color: darkGreen; + color: darkgreen; vertical-align: top; position: relative; top: -4px; @@ -3021,25 +3030,12 @@ font-size: 95%; line-height: 1.2em; } -.openerp .oe_debug_view_log label { - display: block; - width: 49%; - text-align: right; - float: left; - font-weight: bold; - color: #000099; -} -.openerp .oe_debug_view_log span { - display: block; - width: 49%; - float: right; - color: #333333; -} .openerp .navbar { min-height: 32px; margin-bottom: 0px; border: none; z-index: 1; + position: static; background-color: #414141; background-color: #454343; background-image: -webkit-gradient(linear, left top, left bottom, from(#646060), to(#262626)); @@ -3138,10 +3134,6 @@ border: none; padding: 10px 0 3px 0; } -.openerp .jqstooltip { - height: auto !important; - width: auto !important; -} .openerp h5 { font-weight: bold; font-size: smaller; @@ -3153,6 +3145,12 @@ margin: 3px 3px 0 !important; } +.jqstooltip { + height: auto !important; + width: auto !important; + padding: 0; +} + @-moz-document url-prefix() { .openerp .oe_searchview .oe_searchview_search { top: -1px; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 5bb2bb9b448..b19db9e4ebd 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -189,6 +189,17 @@ $sheet-padding: 16px vertical-align: middle td vertical-align: top + .oe_title + width: 50% + float: left + .oe_title:after + content: "." + display: block + height: 0 + clear: both + visibility: hidden + .oe_form_group + clear: both .zebra tbody tr:nth-child(odd) td background-color: #f0f0fa @include vertical-gradient(#f0f0fa, #eeeef6) @@ -1002,10 +1013,8 @@ $sheet-padding: 16px color: #eee // }}} // ActionManager {{{ - .oe_form_uri - color: $link-color - &:hover - text-decoration: underline + a.oe_form_uri:hover + text-decoration: underline .oe_application width: 100% height: 100% @@ -1302,7 +1311,6 @@ $sheet-padding: 16px background: $tag-bg-light @include radius(0 3px 3px 0) .oe_facet_category, .oe_facet_value - height: 18px padding: 0 4px .oe_facet_category color: white @@ -1639,7 +1647,6 @@ $sheet-padding: 16px float: right .oe_button margin: 3px 2px 1px - float: left &:first-child margin-left: 6px @@ -2419,18 +2426,6 @@ $sheet-padding: 16px .oe_debug_view_log font-size: 95% line-height: 1.2em - .oe_debug_view_log label - display: block - width: 49% - text-align: right - float: left - font-weight: bold - color: #009 - .oe_debug_view_log span - display: block - width: 49% - float: right - color: #333 // }}} // Bootstrap HACKS {{{ .navbar @@ -2438,6 +2433,7 @@ $sheet-padding: 16px margin-bottom: 0px border: none z-index: 1 + position: static background-color: #414141 @include vertical-gradient(#646060, #262626) .navbar-default @@ -2517,10 +2513,7 @@ $sheet-padding: 16px border: none padding: 10px 0 3px 0 - // Customize for kanban tooltip - .jqstooltip - height: auto !important - width: auto !important + // Customize for chatter h5 @@ -2531,7 +2524,12 @@ $sheet-padding: 16px .oe_msg_subtype_check margin: 3px 3px 0 !important // }}} - +// Customize for kanban tooltip +.jqstooltip + height: auto !important + width: auto !important + padding: 0 + @-moz-document url-prefix() .openerp .oe_searchview .oe_searchview_search diff --git a/addons/web/static/src/img/throbber-large.gif b/addons/web/static/src/img/throbber-large.gif new file mode 100644 index 00000000000..453b272979d Binary files /dev/null and b/addons/web/static/src/img/throbber-large.gif differ diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index afa761d7025..461bfefac1a 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -1336,10 +1336,15 @@ instance.web.WebClient = instance.web.Client.extend({ var state = $.bbq.getState(true); if (_.isEmpty(state) || state.action == "login") { self.menu.has_been_loaded.done(function() { - var first_menu_id = self.menu.$el.find("a:first").data("menu"); - if(first_menu_id) { - self.menu.menu_click(first_menu_id); - } + new instance.web.Model("res.users").call("read", [self.session.uid, ["action_id"]]).done(function(data) { + var first_menu_id = self.menu.$el.find("a:first").data("menu"); + if(first_menu_id) + self.menu.menu_click(first_menu_id); + + if(data.action_id) { + self.action_manager.do_action(data.action_id[0]); + } + }); }); } else { $(window).trigger('hashchange'); diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 78e3001d746..cc595c30688 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -452,6 +452,9 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, * @returns {$.Deferred} */ read_ids: function (ids, fields, options) { + if (_.isEmpty(ids)) + return $.Deferred().resolve([]); + options = options || {}; // TODO: reorder results to match ids list return this._model.call('read', @@ -872,7 +875,8 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({ }); var return_records = function() { var records = _.map(ids, function(id) { - return _.extend({}, _.detect(self.cache, function(c) {return c.id === id;}).values, {"id": id}); + var c = _.find(self.cache, function(c) {return c.id === id;}); + return _.isUndefined(c) ? c : _.extend({}, c.values, {"id": id}); }); if (self.debug_mode) { if (_.include(records, undefined)) { diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 2f6bbcebc4f..3c32dbe0426 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -205,7 +205,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) { case 'selection': case 'statusbar': // Each choice is [value, label] if(_.isArray(value)) { - value = value[0]; + return value[1]; } var result = _(descriptor.selection).detect(function (choice) { return choice[0] === value; diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index fa9bae9969d..b667d135bdd 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -414,7 +414,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea context: this.dataset.get_context(), }); - $.when(load_view).then(function (r) { + this.alive($.when(load_view)).then(function (r) { return self.search_view_loaded(r); }).fail(function () { self.ready.reject.apply(null, arguments); @@ -473,12 +473,9 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea * Sets up search view's view-wide auto-completion widget */ setup_global_completion: function () { - var self = this; - var autocomplete = this.$el.autocomplete({ source: this.proxy('complete_global_search'), select: this.proxy('select_completion'), - search: function () { self.$el.autocomplete('close'); }, focus: function (e) { e.preventDefault(); }, html: true, autoFocus: true, @@ -486,6 +483,10 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea delay: 250, }).data('autocomplete'); + this.$el.on('input', function () { + this.$el.autocomplete('close'); + }.bind(this)); + // MonkeyPatch autocomplete instance _.extend(autocomplete, { _renderItem: function (ul, item) { diff --git a/addons/web/static/src/js/testing.js b/addons/web/static/src/js/testing.js index f607b278437..c4f5aeebd60 100644 --- a/addons/web/static/src/js/testing.js +++ b/addons/web/static/src/js/testing.js @@ -15,6 +15,37 @@ openerp.testing = {}; list_editable: ['list', 'form', 'data'], }; + var initialized = []; + /** + * openerp.init is a broken-ass piece of shit, makes it impossible to + * progressively add modules, using it, retarded openerp_inited flag + * means the first tests being run get their dependencies loaded + * (basically just base and web), and for *every other module* the tests + * run without the dependencies being correctly loaded + */ + function init(modules) { + if (!initialized.length) { + openerp.init(modules); + initialized = openerp._modules.slice(); + return; + } + var to_initialize = _.difference(modules, initialized); + for (var i = 0; i < to_initialize.length; i++) { + var modname = to_initialize[i]; + var fct = openerp[modname]; + if (typeof fct === 'function') { + var module = openerp[modname] = {}; + for(var k in fct) { + if (!fct.hasOwnProperty(k)) { continue; } + module[k] = fct[k]; + } + fct(openerp, module) + } + initialized.push(modname); + openerp._modules.push(modname); + } + } + testing.dependencies = window['oe_all_dependencies'] || []; testing.current_module = null; testing.templates = { }; @@ -165,8 +196,6 @@ openerp.testing = {}; }); }; - var openerp_inited = false; - var db = window['oe_db_info']; testing.section = function (name, options, body) { if (_.isFunction(options)) { @@ -243,10 +272,7 @@ openerp.testing = {}; QUnit.test(name, function () { var instance = openerp; - if (!openerp_inited) { - openerp.init(module_deps); - openerp_inited = true; - } + init(module_deps); instance.session = new instance.web.Session(); instance.session.uid = 42; if (_.isNumber(opts.asserts)) { diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 4576e9d328d..f1fc377fa94 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -1030,8 +1030,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM open_defaults_dialog: function () { var self = this; var display = function (field, value) { + if (!value) { return value; } if (field instanceof instance.web.form.FieldSelection) { - return _(field.values).find(function (option) { + return _(field.get('values')).find(function (option) { return option[0] === value; })[1]; } else if (field instanceof instance.web.form.FieldMany2One) { @@ -3091,7 +3092,7 @@ instance.web.form.CompletionFieldMixin = { // quick create var raw_result = _(data.result).map(function(x) {return x[1];}); if (search_val.length > 0 && !_.include(raw_result, search_val) && - ! (self.options && self.options.no_quick_create)) { + ! (self.options && (self.options.no_create || self.options.no_quick_create))) { values.push({ label: _.str.sprintf(_t('Create "%s"'), $('').text(search_val).html()), @@ -3102,13 +3103,15 @@ instance.web.form.CompletionFieldMixin = { }); } // create... - values.push({ - label: _t("Create and Edit..."), - action: function() { - self._search_create_popup("form", undefined, self._create_context(search_val)); - }, - classname: 'oe_m2o_dropdown_option' - }); + if (!(self.options && self.options.no_create)){ + values.push({ + label: _t("Create and Edit..."), + action: function() { + self._search_create_popup("form", undefined, self._create_context(search_val)); + }, + classname: 'oe_m2o_dropdown_option' + }); + } return values; }); @@ -5129,7 +5132,7 @@ instance.web.form.FieldReference = instance.web.form.AbstractField.extend(instan .on('blurred', null, function () {self.trigger('blurred');}); this.m2o = new instance.web.form.FieldMany2One(fm, { attrs: { - name: 'm2o', + name: 'Referenced Document', modifiers: JSON.stringify({readonly: this.get('effective_readonly')}), }}); this.m2o.on("change:value", this, this.data_changed); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 8e3923dcaf2..e01ab29f914 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -1654,9 +1654,12 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we function synchronized(fn) { var fn_mutex = new $.Mutex(); return function () { + var obj = this; var args = _.toArray(arguments); - args.unshift(this); - return fn_mutex.exec(fn.bind.apply(fn, args)); + return fn_mutex.exec(function () { + if (obj.isDestroyed()) { return $.when(); } + return fn.apply(obj, args) + }); }; } var DataGroup = instance.web.Class.extend({ diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 79a75551c8d..c9229c3c70a 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -595,6 +595,7 @@ instance.web.ViewManager = instance.web.Widget.extend({ action_views_ids : views_ids }, self.flags, self.flags[view.view_type] || {}, view.options || {}) }); + views_ids[view.view_type] = view.view_id; }); if (this.flags.views_switcher === false) { @@ -602,7 +603,11 @@ instance.web.ViewManager = instance.web.Widget.extend({ } // If no default view defined, switch to the first one in sequence var default_view = this.flags.default_view || this.views_src[0].view_type; - return this.switch_mode(default_view); + + + return this.switch_mode(default_view, null, this.flags[default_view] && this.flags[default_view].options); + + }, switch_mode: function(view_type, no_store, view_options) { var self = this; @@ -810,6 +815,11 @@ instance.web.ViewManager = instance.web.Widget.extend({ contexts: [action_context].concat(contexts || []), group_by_seq: groupbys || [] }).done(function (results) { + if (results.error) { + throw new Error( + _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s", + JSON.stringify(results.error))); + } self.dataset._model = new instance.web.Model( self.dataset.model, results.context, results.domain); var groupby = results.group_by.length @@ -1254,7 +1264,7 @@ instance.web.Sidebar = instance.web.Widget.extend({ this.dataset = dataset; this.model_id = model_id; if (args && args[0].error) { - this.do_warn( instance.web.qweb.render('message_error_uploading'), args[0].error); + this.do_warn(_t('Uploading Error'), args[0].error); } if (!model_id) { this.on_attachments_loaded([]); @@ -1338,7 +1348,7 @@ instance.web.View = instance.web.Widget.extend({ "context": this.dataset.get_context(), }); } - return view_loaded_def.then(function(r) { + return this.alive(view_loaded_def).then(function(r) { self.fields_view = r; // add css classes that reflect the (absence of) access rights self.$el.addClass('oe_view') diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index fc9c2154d01..80b82c1f40b 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -536,23 +536,32 @@
- - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + +
ID:
XML ID:
Creation User:
Creation Date:
Latest Modification by:
Latest Modification Date:
diff --git a/addons/web/static/test/jsonrpc.js b/addons/web/static/test/jsonrpc.js index ef0c1fbc44c..96b10f0fee1 100644 --- a/addons/web/static/test/jsonrpc.js +++ b/addons/web/static/test/jsonrpc.js @@ -156,7 +156,6 @@ ropenerp.testing.section('jsonrpc-auth', { rpc: "rpc", }, function (test) { - return; test('basic-auth', {asserts: 3}, function () { var db = ropenerp.session.db; var session = new openerp.Session(null, null, {override_session: true}); @@ -182,7 +181,6 @@ function (test) { session2 = new openerp.Session(null, null, {session_id: session.session_id}); equal(session2.uid, undefined, "uid should be undefined"); equal(session2.override_session, true, "overwrite_session should be true"); - console.log("session_id", session.session_id); return session2.session_reload(); }).then(function() { equal(session2.uid, session.uid); diff --git a/addons/web/tests/qunitsuite/suite.py b/addons/web/tests/qunitsuite/suite.py index 0abd2f38562..1b6bc7ae0ac 100644 --- a/addons/web/tests/qunitsuite/suite.py +++ b/addons/web/tests/qunitsuite/suite.py @@ -108,6 +108,8 @@ class QUnitSuite(unittest.TestSuite): self._test.failed = True result.addFailure( self._test, self.failure_to_str(*args[2:])) + elif event_name == 'console': + print args[1] return False diff --git a/addons/web/tests/test_js.py b/addons/web/tests/test_js.py index 2228794af6f..0d4a9f35a85 100644 --- a/addons/web/tests/test_js.py +++ b/addons/web/tests/test_js.py @@ -10,14 +10,8 @@ class WebSuite(QUnitSuite): '/web/tests', 'mod=*&source={db}&supadmin={supadmin}&password={password}'.format( db=tools.config['db_name'], - # al: i dont understand why both are needed, db_password is the - # password for postgres and should not appear here of that i'm - # sure - # - # But runbot provides it with this wrong key so i let it here - # until it's fixed - supadmin=tools.config['db_password'] or 'admin', - password=tools.config['admin_passwd'] or 'admin'), + supadmin=tools.config['admin_passwd'], + password='admin'), '' ]) super(WebSuite, self).__init__(url, 50000) diff --git a/addons/web_calendar/static/src/js/web_calendar.js b/addons/web_calendar/static/src/js/web_calendar.js index b283f8b5cb1..77bf3fb7337 100644 --- a/addons/web_calendar/static/src/js/web_calendar.js +++ b/addons/web_calendar/static/src/js/web_calendar.js @@ -5,9 +5,9 @@ _.str.toBoolElse = function(str, elseValues, trueValues, falseValues) { var ret = _.str.toBool(str, trueValues, falseValues); if (_.isUndefined(ret)) { - return elseValues + return elseValues; } - return ret + return ret; }; openerp.web_calendar = function(instance) { @@ -37,7 +37,7 @@ openerp.web_calendar = function(instance) { } function isNullOrUndef(value) { - return _.isUndefined(value) || _.isNull(value) + return _.isUndefined(value) || _.isNull(value); } instance.web.views.add('calendar', 'instance.web_calendar.CalendarView'); @@ -60,7 +60,6 @@ openerp.web_calendar = function(instance) { this.range_start = null; this.range_stop = null; this.selected_filters = []; - }, set_default_options: function(options) { @@ -72,7 +71,9 @@ openerp.web_calendar = function(instance) { destroy: function() { this.$calendar.fullCalendar('destroy'); - this.$small_calendar.datepicker('destroy'); + if (this.$small_calendar){ + this.$small_calendar.datepicker('destroy'); + } this._super.apply(this, arguments); }, @@ -112,21 +113,21 @@ openerp.web_calendar = function(instance) { this.date_start = attrs.date_start; // Field name of starting date field this.date_delay = attrs.date_delay; // duration this.date_stop = attrs.date_stop; - this.all_day = attrs.all_day; - this.attendee_people = attrs.attendee; + this.all_day = attrs.all_day; this.how_display_event = ''; - + this.attendee_people = attrs.attendee; + if (!isNullOrUndef(attrs.quick_create_instance)) { - self.quick_create_instance = 'instance.' + attrs.quick_create_instance; + self.quick_create_instance = 'instance.' + attrs.quick_create_instance; } //if quick_add = False, we don't allow quick_add //if quick_add = not specified in view, we use the default quick_create_instance //if quick_add = is NOT False and IS specified in view, we this one for quick_create_instance' - this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) ); + this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) ); if (this.quick_add_pop && !isNullOrUndef(attrs.quick_add)) { - self.quick_create_instance = 'instance.' + attrs.quick_add; + self.quick_create_instance = 'instance.' + attrs.quick_add; } // The display format which will be used to display the event where fields are between "[" and "]" if (!isNullOrUndef(attrs.display)) { @@ -135,18 +136,29 @@ openerp.web_calendar = function(instance) { // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup,true)) { - this.open_popup_action = false; + this.open_popup_action = false; } else { this.open_popup_action = attrs.event_open_popup; } - // If this field is set to true, we will use de calendar_friends model as filter and not the color field. - this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)); + + // If this field is set to true, we will use the calendar_friends model as filter and not the color field. + this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)) && (!isNullOrUndef(self.options.$sidebar)); // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event // The color is the color of the attendee, so don't need to show again that it will be present - this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee,true))); + this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee, true))) && (!isNullOrUndef(self.options.$sidebar)); + + + + // if we have not sidebar, (eg: Dashboard), we don't use the filter "coworkers" + if (isNullOrUndef(self.options.$sidebar)) { + this.useContacts = false; + this.colorIsAttendee = false; + this.attendee_people = undefined; + } + /* Will be more logic to do it in futur, but see below to stay Retro-compatible @@ -164,14 +176,14 @@ openerp.web_calendar = function(instance) { } */ if (isNullOrUndef(attrs.avatar_model)) { - this.avatar_model = null; + this.avatar_model = null; } else { this.avatar_model = attrs.avatar_model; } if (isNullOrUndef(attrs.avatar_title)) { - this.avatar_title = this.avatar_model; + this.avatar_title = this.avatar_model; } else { this.avatar_title = attrs.avatar_title; @@ -195,7 +207,7 @@ openerp.web_calendar = function(instance) { .call("check_access_rights", ["create", false]) .then(function (create_right) { self.create_right = create_right; - self.init_calendar().then(function() { + self.init_calendar().then(function() { self.trigger('calendar_view_loaded', fv); self.ready.resolve(); }); @@ -231,15 +243,15 @@ openerp.web_calendar = function(instance) { self.proxy('update_record')(event._id, data); }, eventRender: function (event, element, view) { - element.find('.fc-event-title').html(event.title); + element.find('.fc-event-title').html(event.title); }, - eventAfterRender: function (event, element, view) { + eventAfterRender: function (event, element, view) { if ((view.name !== 'month') && (((event.end-event.start)/60000)<=30)) { //if duration is too small, we see the html code of img var current_title = $(element.find('.fc-event-time')).text(); - var new_title = current_title.substr(0,current_title.indexOf("0?current_title.indexOf("0?current_title.indexOf("'; + if (attendee_showed<= MAX_ATTENDEES) { + if (self.avatar_model !== null) { + the_title_avatar += ''; } else { if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) { tempColor = (self.all_filters[the_attendee_people] != undefined) ? self.all_filters[the_attendee_people].color : self.all_filters[-1].color; - - the_title_avatar += '' + the_title_avatar += ''; }//else don't add myself } } else { attendee_other += self.all_attendees[the_attendee_people] +", "; - } + } } ); if (attendee_other.length>2) { - the_title_avatar += '+'; + the_title_avatar += '+'; } the_title = the_title_avatar + the_title; - } + } } if (!date_stop && date_delay) { date_stop = date_start.clone().addHours(date_delay); } if (this.fields[this.date_start].type != "date" && all_day) { - date_stop.addDays(-1); + //date_stop.addDays(-1); } var r = { 'start': date_start.toString('yyyy-MM-dd HH:mm:ss'), @@ -597,20 +612,19 @@ openerp.web_calendar = function(instance) { }; - if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) { + if (!self.useContacts || self.all_filters[evt[this.color_field]] !== undefined) { if (this.color_field && evt[this.color_field]) { var color_key = evt[this.color_field]; if (typeof color_key === "object") { color_key = color_key[0]; } - r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key); + r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key); } } else { // if form all, get color -1 r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color; } - return r; }, @@ -627,7 +641,7 @@ openerp.web_calendar = function(instance) { var event_end = event.end; //Bug when we move an all_day event from week or day view, we don't have a dateend or duration... - if (event_end == null) { + if (event_end === null) { event_end = new Date(event.start).addHours(2); } @@ -637,14 +651,14 @@ openerp.web_calendar = function(instance) { event_end = new Date(event.start); } if (this.all_day) { - event_end = (new Date(event_end.getTime())).addDays(1); - date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) - date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) + event_end = (new Date(event_end.getTime())).addDays(1); + date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),12); + date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),12); } else { - date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7)) - date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19)) - } + date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7); + date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19); + } data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]); if (this.date_stop) { data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]); @@ -652,17 +666,15 @@ openerp.web_calendar = function(instance) { } else { - data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]); if (this.date_stop) { data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]); - } - + } } if (this.all_day) { - data[this.all_day] = event.allDay; + data[this.all_day] = event.allDay; } if (this.date_delay) { @@ -671,8 +683,14 @@ openerp.web_calendar = function(instance) { } return data; }, + do_search: function(domain, context, _group_by) { var self = this; + + if (self.sidebar) { + self.sidebar.filter.is_loaded = false; + } + if (! _.isUndefined(this.event_source)) { this.$calendar.fullCalendar('removeEventSource', this.event_source); } @@ -684,33 +702,32 @@ openerp.web_calendar = function(instance) { domain: self.get_range_domain(domain, start, end), context: context, }).done(function(events) { + if (self.event_source !== current_event_source) { console.log("Consecutive ``do_search`` called. Cancelling."); return; } - // We should make sure that *2many used in title of event have their extended form [ID, NAME]... - events = $.map(events, function (e) { - - if (self.attendee_people != undefined) { //If we filter on contacts... - if (_.intersection(self.selected_filters,e[self.attendee_people]).length || (self.selected_filters.indexOf(-1) > -1)) { - return e; - } - else { - return null; - } + if (self.attendee_people !== undefined) { + //Else we filter on 'Everybody's Calendar, we don't filter events + if (self.selected_filters.indexOf(-1) == -1) { + + //If we filter on contacts... we keep only events from coworkers + events = $.map(events, function (e) { + if (_.intersection(self.selected_filters,e[self.attendee_people]).length ) { + return e; + } + return null; + }); } - else { //We adds all events - return e; - } - return null; - }); + } - if (!self.useContacts) { // If we use all peoples as filter in sidebars + if (!self.useContacts) { // If we use all peoples displayed in the current month as filter in sidebars var now_filters = {}; var filter_value; var filter_item; + _.each(events, function (e) { filter_value = e[self.color_field][0]; filter_item = { @@ -724,31 +741,44 @@ openerp.web_calendar = function(instance) { } }); - self.allFilters = now_filters; - self.sidebar.filter.events_loaded(now_filters); + self.allFilters = now_filters; + + if (self.sidebar) { + if (!self.sidebar.filter.is_loaded) { + self.sidebar.filter.events_loaded(now_filters); + } + else { + events = $.map(events, function (e) { + if (_.contains(self.selected_filters,e[self.color_field][0]) ) { + return e; + } + return null; + }); + } + } return self.perform_necessary_name_gets(events).then(callback); } else { var all_attendees = []; _.each(events, function (e) { - all_attendees.push(e[self.attendee_people]); + all_attendees.push(e[self.attendee_people]); }); - self.all_attendees = {} + self.all_attendees = {}; all_attendees = _.chain(all_attendees).flatten().uniq().value(); - if (self.avatar_title != null) { + if (self.avatar_title !== null) { new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) { _.each(result, function(item) { self.all_attendees[item.id] = item.name; }); - }).done(function() { + }).done(function() { return self.perform_necessary_name_gets(events).then(callback); }); - } + } else { _.each(all_attendees,function(item){ self.all_attendees[item] = ''; @@ -756,10 +786,7 @@ openerp.web_calendar = function(instance) { return self.perform_necessary_name_gets(events).then(callback); } - } - - }); }, eventDataTransform: function (event) { @@ -780,7 +807,6 @@ openerp.web_calendar = function(instance) { [this.date_start, '<=', format(end.clone())]]); }, - /** * Updates record identified by ``id`` with values in object ``data`` */ @@ -803,26 +829,22 @@ openerp.web_calendar = function(instance) { } return false; }, - open_event: function(id,title) { + open_event: function(id, title) { var self = this; - if (! this.open_popup_action) { + if (! this.open_popup_action) { var index = this.dataset.get_id_index(id); this.dataset.index = index; this.do_switch_view('form', null, { mode: "edit" }); - } + } else { - - var self = this; - var pop = new instance.web.form.FormOpenPopup(this); - console.log(this.open_popup_action, +this.open_popup_action); pop.show_element(this.dataset.model, id, this.dataset.get_context(), { title: _.str.sprintf(_t("View: %s"),title), view_id: +this.open_popup_action, res_id: id, target: 'new', readonly:true - }); + }); var form_controller = pop.view_form; form_controller.on("load_record", self, function(){ @@ -830,33 +852,25 @@ openerp.web_calendar = function(instance) { button_edit = _.str.sprintf("",_t("Edit Event")); - pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete) - pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit) + pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete); + pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit); $('.delme').click( - function() { - $('.oe_form_button_cancel').trigger('click'); - self.remove_event(id); + function() { + $('.oe_form_button_cancel').trigger('click'); + self.remove_event(id); } ); $('.editme').click( - function() { - $('.oe_form_button_cancel').trigger('click'); - - var index = self.dataset.get_id_index(id); - self.dataset.index = index; + function() { + $('.oe_form_button_cancel').trigger('click'); + self.dataset.index = self.dataset.get_id_index(id); self.do_switch_view('form', null, { mode: "edit" }); - } ); - - }); - - } - - return false; - + } + return false; }, do_show: function() { @@ -900,6 +914,10 @@ openerp.web_calendar = function(instance) { slow_created: function () { // refresh all view, because maybe some recurrents item var self = this; + if (self.sidebar) { + // force filter refresh + self.sidebar.filter.is_loaded = false; + } self.$calendar.fullCalendar('refetchEvents'); }, @@ -933,7 +951,7 @@ openerp.web_calendar = function(instance) { template: 'CalendarView.quick_create', init: function(parent, dataset, buttons, options, data_template) { - this._super(parent); + this._super(parent); this.dataset = dataset; this._buttons = buttons || false; this.options = options; @@ -944,7 +962,7 @@ openerp.web_calendar = function(instance) { get_title: function () { var parent = this.getParent(); if (_.isUndefined(parent)) { - return _t("Create") + return _t("Create"); } var title = (_.isUndefined(parent.field_widget)) ? (parent.string || parent.name) : @@ -965,7 +983,7 @@ openerp.web_calendar = function(instance) { if(event.keyCode == 13){ self.$input.off('keyup', enterHandler); if (!self.quick_add()){ - self.$input.on('keyup', enterHandler); + self.$input.on('keyup', enterHandler); } } }); @@ -974,14 +992,13 @@ openerp.web_calendar = function(instance) { submit.click(function clickHandler() { submit.off('click', clickHandler); if (!self.quick_add()){ - submit.on('click', clickHandler); - } + submit.on('click', clickHandler); } self.focus(); }); this.$el.find(".oe_calendar_quick_create_edit").click(function () { self.slow_add(); self.focus(); - }); + }); this.$el.find(".oe_calendar_quick_create_close").click(function (ev) { ev.preventDefault(); self.trigger('close'); @@ -997,7 +1014,6 @@ openerp.web_calendar = function(instance) { }); self.$el.on('dialogclose', self, function() { - console.log("dialogclose"); self.trigger('close'); }); @@ -1011,10 +1027,10 @@ openerp.web_calendar = function(instance) { */ quick_add: function() { var val = this.$input.val(); - if (/^\s*$/.test(val)) { - return false; + if (/^\s*$/.test(val)) { + return false; } - return this.quick_create({'name': val}).always(function() { return true }); + return this.quick_create({'name': val}).always(function() { return true; }); }, slow_add: function() { @@ -1053,21 +1069,19 @@ openerp.web_calendar = function(instance) { return infos; }, slow_create: function(data) { + //if all day, we could reset time to display 00:00:00 + var self = this; var def = $.Deferred(); var defaults = {}; + _.each($.extend({}, this.data_template, data), function(val, field_name) { defaults['default_' + field_name] = val; }); - - if (defaults['default_allday'] && (defaults['default_date_deadline'] || defaults['default_duration'])) { - delete defaults['default_date_deadline']; - delete defaults['default_duration']; - } - + var pop_infos = self.get_form_popup_infos(); var pop = new instance.web.form.FormOpenPopup(this); - var context = new instance.web.CompoundContext(this.dataset.context, defaults) + var context = new instance.web.CompoundContext(this.dataset.context, defaults); pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), { title: this.get_title(), disable_multiple_selection: true, @@ -1316,7 +1330,6 @@ openerp.web_calendar = function(instance) { }, render_value: function() { - console.log("In render value"); var self = this; this.dataset.set_ids(this.get("value")); this.is_loaded = this.is_loaded.then(function() { @@ -1360,7 +1373,7 @@ openerp.web_calendar = function(instance) { }, alternative_form_view: this.field.views ? this.field.views.form : undefined, - parent_view: this.view, //XXXvlab: to check ! this.view is likely undefined + parent_view: this.view, child_name: this.name, readonly: this.get("effective_readonly") }); @@ -1377,19 +1390,26 @@ openerp.web_calendar = function(instance) { } }); instance.web_calendar.SidebarFilter = instance.web.Widget.extend({ + is_loaded:false, events: { 'change input:checkbox': 'filter_click' }, init: function(parent, view) { this._super(parent); - this.view = view; + this.view = view; }, + + + events_loaded: function(filters) { var self = this; + self.is_loaded=true; + self.selected_filters = []; self.view.all_filters = filters; this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters })); - this.filter_click(null); + this.filter_click(null); + }, filter_click: function(e) { var self = this, @@ -1398,25 +1418,21 @@ openerp.web_calendar = function(instance) { this.$('div.oe_calendar_responsible input:checked').each(function() { responsibles.push($(this).val()); - if (e==null && parseInt($(this).val())<0) { + if (e==null && parseInt($(this).val())<0){ $(this).prop('checked',false); return; - } + } + self.view.selected_filters.push(parseInt($(this).val())); }); - - if (e !== null) { //First intialize - self.view.$calendar.fullCalendar('refetchEvents'); - } - - + self.view.$calendar.fullCalendar('refetchEvents'); }, addUpdateButton: function() { var self=this; this.$('div.oe_calendar_all_responsibles').append(QWeb.render('CalendarView.sidebar.button_add_contact')); - this.$(".add_contacts_link_btn").on('click', function() { - self.rpc("/web/action/load", { - action_id: "calendar.action_calendar_contacts" + this.$(".add_contacts_link_btn").on('click', function() { + self.rpc("/web/action/load", { + action_id: "calendar.action_calendar_contacts" }).then( function(result) { return self.do_action(result); }); }); diff --git a/addons/web_graph/static/src/js/graph_view.js b/addons/web_graph/static/src/js/graph_view.js index e1a50d4ff6d..ace2f14ae20 100644 --- a/addons/web_graph/static/src/js/graph_view.js +++ b/addons/web_graph/static/src/js/graph_view.js @@ -50,7 +50,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ var field_name = field.attrs.name; if (_.has(field.attrs, 'interval')) { field_name = field.attrs.name + ':' + field.attrs.interval; - } + } if (_.has(field.attrs, 'type')) { switch (field.attrs.type) { case 'row': @@ -77,15 +77,20 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { + if (this.ignore_do_search) { + this.ignore_do_search = false; + return; + } + var self = this, - col_group_by = context.col_group_by || this.get_groupbys_from_searchview('ColGroupBy', 'col_group_by'); + col_group_by = self.get_groupbys_from_searchview('ColGroupBy', 'col_group_by'); if (!this.graph_widget) { if (group_by.length) { this.widget_config.row_groupby = group_by; } if (col_group_by.length) { - this.widget_config.col_groupby = group_by; + this.widget_config.col_groupby = col_group_by; } this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); this.graph_widget.appendTo(this.$el); @@ -101,16 +106,18 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.graph_widget.set(domain, group_by, col_group_by); }, + extract_groupby: function (cat_field, context) { + context = (_.isString(context)) ? py.eval(context) : context; + return context[cat_field]; + }, + get_groupbys_from_searchview: function (cat_name, cat_field) { - var facet = this.search_view.query.findWhere({category:cat_name}), + var self=this, + facet = this.search_view.query.findWhere({category:cat_name}), groupby_list = facet ? facet.values.models : []; return _.map(groupby_list, function (g) { var context = g.attributes.value.attrs.context; - if (_.isString(context)) { - return py.eval(context).group_by; - } else { - return context[cat_field]; - } + return self.extract_groupby(cat_field, context); }); }, @@ -129,6 +136,14 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (!_.has(this.search_view, '_s_groupby')) { return; } + if (row_groupby.length && col_groupby.length) { + // when two changes to the search view will be done, the method do_search + // will be called twice, once with the correct groupby and incorrect col_groupby, + // and once with correct informations. This flag is necessary to prevent the + // incorrect informations to propagate and trigger useless queries + this.ignore_do_search = true; + } + // add row groupbys var row_facet = this.make_row_groupby_facets(row_groupby), row_search_facet = query.findWhere({category:'GroupBy'}); diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index 51baabaff5e..9e4c81157d1 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -263,9 +263,6 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({ case 'swap_axis': this.swap_axis(); break; - case 'expand_all': - this.pivot.expand_all().then(this.proxy('display_data')); - break; case 'update_values': this.pivot.update_data().then(this.proxy('display_data')); break; @@ -295,25 +292,30 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({ if (header.expanded) { this.fold(header); - } else { - if (header.path.length < header.root.groupby.length) { - this.expand(id); - } else { - if (!this.important_fields.length) { - return; - } - - var fields = _.map(this.important_fields, function (field) { - return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type}; - }); - this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); - $(event.target).after(this.dropdown); - this.dropdown.css({position:'absolute', - left:event.pageX, - top:event.pageY}); - this.$('.field-selection').next('.dropdown-menu').toggle(); - } + return; + } + if (header.path.length < header.root.groupby.length) { + this.expand(id); + return; + } + if (!this.important_fields.length) { + return; } + + var fields = _.map(this.important_fields, function (field) { + return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type}; + }); + if (this.dropdown) { + this.dropdown.remove(); + } + this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); + $(event.target).after(this.dropdown); + this.dropdown.css({position:'absolute', + left:event.pageX, + top:event.pageY}); + this.$('.field-selection').next('.dropdown-menu').toggle(); + + }, field_selection: function (event) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 81804e5a9b1..4522fd2504f 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -35,9 +35,6 @@ - diff --git a/addons/web_tests_demo/static/test/demo.js b/addons/web_tests_demo/static/test/demo.js index 0ca10ba642c..2ead2902828 100644 --- a/addons/web_tests_demo/static/test/demo.js +++ b/addons/web_tests_demo/static/test/demo.js @@ -1,7 +1,5 @@ -// niv: I desactivate these until the testing framework has been adapted to better use -// the new way to declare JavaScript modules -/*openerp.testing.section('basic section', function (test) { +openerp.testing.section('basic section', function (test) { test('my first test', function () { ok(true, "this test has run"); }); @@ -88,18 +86,18 @@ }); }); -// test('actual RPC', {rpc: 'rpc', asserts: 4}, function (instance) { -// var Model = new instance.web.Model('web_tests_demo.model'); -// return Model.call('create', [{name: "Bob"}]) -// .then(function (id) { -// return Model.call('read', [[id]]); -// }).then(function (records) { -// strictEqual(records.length, 1); -// var record = records[0]; -// strictEqual(record.name, "Bob"); -// strictEqual(record.thing, false); -// // default value -// strictEqual(record.other, 'bob'); -// }); -// }); -});*/ + test('actual RPC', {rpc: 'rpc', asserts: 4}, function (instance) { + var Model = new instance.web.Model('web_tests_demo.model'); + return Model.call('create', [{name: "Bob"}]) + .then(function (id) { + return Model.call('read', [[id]]); + }).then(function (records) { + strictEqual(records.length, 1); + var record = records[0]; + strictEqual(record.name, "Bob"); + strictEqual(record.thing, false); + // default value + strictEqual(record.other, 'bob'); + }); + }); +}); diff --git a/addons/web_view_editor/static/src/js/view_editor.js b/addons/web_view_editor/static/src/js/view_editor.js index a7906689cce..69e9a3080b7 100644 --- a/addons/web_view_editor/static/src/js/view_editor.js +++ b/addons/web_view_editor/static/src/js/view_editor.js @@ -15,7 +15,7 @@ instance.web.ViewManagerAction.include({ } evt.currentTarget.selectedIndex = 0; }else{ - return this._super.apply(this,arguments); + return this._super.apply(this,arguments); } } }); @@ -73,12 +73,10 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ $.when(this.action_manager.do_action(action)).done(function() { var viewmanager = self.action_manager.inner_widget; var controller = viewmanager.views[viewmanager.active_view].controller; - controller.on('view_loaded', self, function(){ - $(controller.groups).bind({ - 'selected': function(e, ids, records) { + $(controller.groups).bind({ + 'selected': function (e, ids, records, deselected) { self.main_view_id = ids[0]; - } - }); + } }); }); }, @@ -232,10 +230,11 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ return main_object; }, parse_xml: function(arch, view_id) { + //First element of att_list must be element tagname. main_object = { 'level': 0, 'id': this.xml_element_id +=1, - 'att_list': [], + 'att_list': ["view"], 'name': _.str.sprintf("", view_id), 'child_id': [] }; @@ -535,15 +534,22 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ var field_dataset = new instance.web.DataSetSearch(this, this.model, null, null); parent_tr = self.get_object_by_id(parseInt($(parent_tr).attr('id').replace(/[^0-9]+/g, '')), this.one_object['main_object'], [])[0].att_list[0]; _.each([tr, parent_tr],function(element) { - var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false; + var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false; property_to_check.push(value); }); field_dataset.call( 'fields_get', []).done(function(result) { var fields = _.keys(result); fields.push(" "),fields.sort(); - self.on_add_node(property_to_check, fields); + self.on_add_node(property_to_check, fields, self.inject_position(parent_tr,tr)); }); }, + inject_position : function(parent_tag,current_tag){ + if(parent_tag == "view") + return ['Inside']; + if(current_tag == "field") + return ['After','Before']; + return ['After','Before','Inside']; + }, do_node_edit: function(side) { var self = this; var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []); @@ -637,12 +643,12 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) { return child.nodeType == 1; }); - arch.arch = _.detect(children, function(xml_child) { + var inherited_view = _.detect(children, function(xml_child) { var temp_obj = self.create_View_Node(xml_child), insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list)); if (insert.length == _.uniq(check_list).length ) {return xml_child;} }); - xml_arch = QWeb.load_xml(arch.arch); + xml_arch = QWeb.load_xml(instance.web.xml_to_str(inherited_view)); } return self.do_save_xml(xml_arch.documentElement, obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch); }, @@ -941,11 +947,11 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ }); return def.promise(); }, - on_add_node: function(properties, fields){ + on_add_node: function(properties, fields, position){ var self = this; var render_list = [{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), 'value': 'field', 'string': 'Node Type','type': 'selection'}, {'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'}, - {'name': 'position','selection': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}]; + {'name': 'position','selection': position, 'value': false, 'string': 'Position','type': 'selection'}]; this.add_widget = []; this.add_node_dialog = new instance.web.Dialog(this,{ title: _t("Properties"), @@ -1186,7 +1192,7 @@ var _CHILDREN = { //e.g.:xyz 'td' : ['field'] }; // Generic html_tag list and can be added html tag in future. It's support above _CHILDREN dict's *html_tag* by default. -// For specific child node one has to define tag above and specify children tag in list. Like above xyz example. +// For specific child node one has to define tag above and specify children tag in list. Like above xyz example. var html_tag = ['div','h1','h2','h3','h4','h5','h6','td','tr']; var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',