summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorniv-openerp <nicolas.vanhoren@openerp.com>2012-02-17 11:17:31 +0100
committerniv-openerp <nicolas.vanhoren@openerp.com>2012-02-17 11:17:31 +0100
commit1e9380b8faf05aa5ccb7fdfaf7309c362b1963bb (patch)
treee49a42e01b00a5e95522a93c720762d487b17fd8 /addons/web/static/src/js
parentaffc2d4d04539d452ee207eef2c01238df72d1ef (diff)
parent9f65e1565e785fd1c11fef65e7b49e78fba290ed (diff)
[merge]
bzr revid: nicolas.vanhoren@openerp.com-20120217101731-3g9hrhs65qb32pkv
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/chrome.js52
-rw-r--r--addons/web/static/src/js/core.js67
-rw-r--r--addons/web/static/src/js/data.js29
-rw-r--r--addons/web/static/src/js/data_import.js13
-rw-r--r--addons/web/static/src/js/formats.js50
-rw-r--r--addons/web/static/src/js/search.js51
-rw-r--r--addons/web/static/src/js/view_editor.js112
-rw-r--r--addons/web/static/src/js/view_form.js146
-rw-r--r--addons/web/static/src/js/view_list.js8
-rw-r--r--addons/web/static/src/js/view_list_editable.js4
-rw-r--r--addons/web/static/src/js/view_page.js17
-rw-r--r--addons/web/static/src/js/views.js71
12 files changed, 470 insertions, 150 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 9fda4752a36..ba31ec81846 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -20,17 +20,27 @@ openerp.web.Notification = openerp.web.OldWidget.extend(/** @lends openerp.web.
expires: 2500
});
},
- notify: function(title, text) {
+ notify: function(title, text, sticky) {
+ sticky = !!sticky;
+ var opts = {};
+ if (sticky) {
+ opts.expires = false;
+ }
this.$element.notify('create', {
title: title,
text: text
- });
+ }, opts);
},
- warn: function(title, text) {
+ warn: function(title, text, sticky) {
+ sticky = !!sticky;
+ var opts = {};
+ if (sticky) {
+ opts.expires = false;
+ }
this.$element.notify('create', 'oe_notification_alert', {
title: title,
text: text
- });
+ }, opts);
}
});
@@ -606,6 +616,10 @@ openerp.web.Login = openerp.web.OldWidget.extend(/** @lends openerp.web.Login#
}
var $e = this.$element;
var db = $e.find("form [name=db]").val();
+ if (!db) {
+ this.do_warn("Login", "No database selected !");
+ return false;
+ }
var login = $e.find("form input[name=login]").val();
var password = $e.find("form input[name=password]").val();
@@ -945,7 +959,8 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
do_menu_click: function($clicked_menu, manual) {
var $sub_menu, $main_menu,
active = $clicked_menu.is('.active'),
- sub_menu_visible = false;
+ sub_menu_visible = false,
+ has_submenu_items = false;
if (this.$secondary_menu.has($clicked_menu).length) {
$sub_menu = $clicked_menu.parents('.oe_secondary_menu');
@@ -956,15 +971,18 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
}
sub_menu_visible = $sub_menu.is(':visible');
+ has_submenu_items = !!$sub_menu.children().length;
this.$secondary_menu.find('.oe_secondary_menu').hide();
$('.active', this.$element.add(this.$secondary_menu)).removeClass('active');
$main_menu.add($clicked_menu).add($sub_menu).addClass('active');
- if (!(this.folded && manual)) {
- this.do_show_secondary($sub_menu, $main_menu);
- } else {
- this.do_show_secondary();
+ if (has_submenu_items) {
+ if (!(this.folded && manual)) {
+ this.do_show_secondary($sub_menu, $main_menu);
+ } else {
+ this.do_show_secondary();
+ }
}
if ($main_menu != $clicked_menu) {
@@ -980,7 +998,7 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
return true;
}
} else if (this.folded) {
- if (active && sub_menu_visible) {
+ if ((active && sub_menu_visible) || !has_submenu_items) {
$sub_menu.hide();
return true;
}
@@ -1147,12 +1165,14 @@ openerp.web.WebClient = openerp.web.OldWidget.extend(/** @lends openerp.web.WebC
n.warn.apply(n, arguments);
},
on_logout: function() {
- this.session.session_logout();
- $(window).unbind('hashchange', this.on_hashchange);
- this.do_push_state({});
- //would be cool to be able to do this, but I think it will make addons do strange things
- //this.show_login();
- window.location.reload();
+ var self = this;
+ this.session.session_logout().then(function () {
+ $(window).unbind('hashchange', self.on_hashchange);
+ self.do_push_state({});
+ //would be cool to be able to do this, but I think it will make addons do strange things
+ //this.show_login();
+ window.location.reload();
+ });
},
bind_hashchange: function() {
$(window).bind('hashchange', this.on_hashchange);
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index 8ab6c897fb0..086f7f3b56a 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -254,6 +254,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
* @param {Object} mapping a mapping of keys to object-paths
*/
init: function (mapping) {
+ this.parent = null;
this.map = mapping || {};
},
/**
@@ -269,6 +270,9 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
get_object: function (key, silent_error) {
var path_string = this.map[key];
if (path_string === undefined) {
+ if (this.parent) {
+ return this.parent.get_object(key, silent_error);
+ }
if (silent_error) { return void 'nooo'; }
throw new openerp.web.KeyNotFound(key);
}
@@ -287,6 +291,21 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
return object_match;
},
/**
+ * Checks if the registry contains an object mapping for this key.
+ *
+ * @param {String} key key to look for
+ */
+ contains: function (key) {
+ if (key === undefined) { return false; }
+ if (key in this.map) {
+ return true
+ }
+ if (this.parent) {
+ return this.parent.contains(key);
+ }
+ return false;
+ },
+ /**
* Tries a number of keys, and returns the first object matching one of
* the keys.
*
@@ -299,7 +318,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
get_any: function (keys) {
for (var i=0; i<keys.length; ++i) {
var key = keys[i];
- if (key === undefined || !(key in this.map)) {
+ if (!this.contains(key)) {
continue;
}
@@ -324,11 +343,22 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
* Creates and returns a copy of the current mapping, with the provided
* mapping argument added in (replacing existing keys if needed)
*
+ * Parent and child remain linked, a new key in the parent (which is not
+ * overwritten by the child) will appear in the child.
+ *
* @param {Object} [mapping={}] a mapping of keys to object-paths
*/
+ extend: function (mapping) {
+ var child = new openerp.web.Registry(mapping);
+ child.parent = this;
+ return child;
+ },
+ /**
+ * @deprecated use Registry#extend
+ */
clone: function (mapping) {
- return new openerp.web.Registry(
- _.extend({}, this.map, mapping || {}));
+ console.warn('Registry#clone is deprecated, use Registry#extend');
+ return this.extend(mapping);
}
});
@@ -644,6 +674,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
},
session_logout: function() {
this.set_cookie('session_id', '');
+ return this.rpc("/web/session/destroy", {});
},
on_session_valid: function() {
},
@@ -702,17 +733,21 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
var params = { mods: all_modules, lang: lang};
var to_load = _.difference(result, self.module_list).join(',');
self.module_list = all_modules;
- return $.when(
- self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css),
- self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb),
- self.rpc('/web/webclient/translations', params).pipe(function(trans) {
- openerp.web._t.database.set_bundle(trans);
- var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
- return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) {
- return self.do_load_js(file_list.concat(files));
- });
- })
- ).then(function() {
+
+ var loaded = $.Deferred().resolve().promise();
+ if (to_load.length) {
+ loaded = $.when(
+ self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css),
+ self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb),
+ self.rpc('/web/webclient/translations', params).pipe(function(trans) {
+ openerp.web._t.database.set_bundle(trans);
+ var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
+ return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) {
+ return self.do_load_js(file_list.concat(files));
+ });
+ }))
+ }
+ return loaded.then(function() {
self.on_modules_loaded();
if (!no_session_valid_signal) {
self.on_session_valid();
@@ -1184,9 +1219,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we
add_module_translation: function(mod) {
var self = this;
_.each(mod.messages, function(message) {
- if (self.db[message.id] === undefined) {
- self.db[message.id] = message.string;
- }
+ self.db[message.id] = message.string;
});
},
build_translation_function: function() {
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index 01962f829e6..8e200951eaa 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -469,13 +469,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data
* @param {String} name name to perform a search for/on
* @param {Array} [domain=[]] filters for the objects returned, OpenERP domain
* @param {String} [operator='ilike'] matching operator to use with the provided name value
- * @param {Number} [limit=100] maximum number of matches to return
+ * @param {Number} [limit=0] maximum number of matches to return
* @param {Function} callback function to call with name_search result
* @returns {$.Deferred}
*/
name_search: function (name, domain, operator, limit, callback) {
return this.call_and_eval('name_search',
- [name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100],
+ [name || '', domain || false, operator || 'ilike', this.get_context(), limit || 0],
1, 3, callback);
},
/**
@@ -522,7 +522,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data
this._sort.unshift((reverse ? '-' : '') + field);
return undefined;
- }
+ },
+ size: function () {
+ return this.ids.length;
+ },
+ alter_ids: function(n_ids) {
+ this.ids = n_ids;
+ },
});
openerp.web.DataSetStatic = openerp.web.DataSet.extend({
init: function(parent, model, context, ids) {
@@ -568,6 +574,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
this._super(parent, model, context);
this.domain = domain || [];
this.offset = 0;
+ this._length;
// subset records[offset:offset+limit]
// is it necessary ?
this.ids = [];
@@ -599,6 +606,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
}).pipe(function (result) {
self.ids = result.ids;
self.offset = offset;
+ self._length = result.length;
return result.records;
});
},
@@ -619,6 +627,12 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
if (callback)
callback(result);
}, error_callback);
+ },
+ size: function () {
+ if (this._length !== undefined) {
+ return this._length;
+ }
+ return this._super();
}
});
openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
@@ -640,7 +654,6 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
defaults: this.last_default_get};
this.to_create.push(_.extend(_.clone(cached), {values: _.clone(cached.values)}));
this.cache.push(cached);
- this.on_change();
var prom = $.Deferred().then(callback);
prom.resolve({result: cached.id});
return prom.promise();
@@ -751,7 +764,7 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
self.cache.push({id: id, values: record});
} else {
// I assume cache value is prioritary
- _.defaults(cached.values, record);
+ cached.values = _.defaults(_.clone(cached.values), record);
}
});
return_records();
@@ -774,7 +787,11 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
}
}
return this._super(method, args, callback, error_callback);
- }
+ },
+ alter_ids: function(n_ids) {
+ this._super(n_ids);
+ this.on_change();
+ },
});
openerp.web.BufferedDataSet.virtual_id_regex = /^one2many_v_id_.*$/;
diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js
index 18870ca2157..83eea2cccbb 100644
--- a/addons/web/static/src/js/data_import.js
+++ b/addons/web/static/src/js/data_import.js
@@ -109,9 +109,20 @@ openerp.web.DataImport = openerp.web.Dialog.extend({
_(fields).each(function (field, field_name) {
// Ignore spec for id field
// Don't import function fields (function and related)
- if (field_name === 'id' || 'function' in field) {
+ if (field_name === 'id') {
return;
}
+ // Skip if there's no state which could disable @readonly,
+ // if a field is ever always readonly we can't import it
+ if (field.readonly) {
+ // no states at all
+ if (_.isEmpty(field.states)) { return; }
+ // no state altering @readonly
+ if (!_.any(field.states, function (modifiers) {
+ return _(modifiers).chain().pluck(0).contains('readonly').value();
+ })) { return; }
+ }
+
var f = {
id: field_name,
name: field_name,
diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js
index eb7d6c335ac..4fb576e4a90 100644
--- a/addons/web/static/src/js/formats.js
+++ b/addons/web/static/src/js/formats.js
@@ -61,6 +61,28 @@ openerp.web.insert_thousand_seps = function (num) {
return (negative ? '-' : '') + openerp.web.intersperse(
num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep);
};
+
+/**
+ * removes literal (non-format) text from a date or time pattern, as datejs can
+ * not deal with literal text in format strings (whatever the format), whereas
+ * strftime allows for literal characters
+ *
+ * @param {String} value original format
+ */
+openerp.web.strip_raw_chars = function (value) {
+ var isletter = /[a-zA-Z]/, output = [];
+ for(var index=0; index < value.length; ++index) {
+ var character = value[index];
+ if(isletter.test(character) && (index === 0 || value[index-1] !== '%')) {
+ continue;
+ }
+ output.push(character);
+ }
+ return output.join('');
+};
+var normalize_format = function (format) {
+ return Date.normalizeFormat(openerp.web.strip_raw_chars(format));
+};
/**
* Formats a single atomic value based on a field descriptor
*
@@ -101,7 +123,12 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
formatted[0] = openerp.web.insert_thousand_seps(formatted[0]);
return formatted.join(l10n.decimal_point);
case 'float_time':
- return _.str.sprintf("%02d:%02d",
+ var pattern = '%02d:%02d';
+ if (value < 0) {
+ value = Math.abs(value);
+ pattern = '-' + pattern;
+ }
+ return _.str.sprintf(pattern,
Math.floor(value),
Math.round((value % 1) * 60));
case 'many2one':
@@ -111,16 +138,16 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
- return value.format(l10n.date_format
- + ' ' + l10n.time_format);
+ return value.toString(normalize_format(l10n.date_format)
+ + ' ' + normalize_format(l10n.time_format));
case 'date':
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
- return value.format(l10n.date_format);
+ return value.toString(normalize_format(l10n.date_format));
case 'time':
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
- return value.format(l10n.time_format);
+ return value.toString(normalize_format(l10n.time_format));
case 'selection':
// Each choice is [value, label]
if(_.isArray(value)) {
@@ -137,8 +164,8 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
};
openerp.web.parse_value = function (value, descriptor, value_if_empty) {
- var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format),
- time_pattern = Date.normalizeFormat(_t.database.parameters.time_format);
+ var date_pattern = normalize_format(_t.database.parameters.date_format),
+ time_pattern = normalize_format(_t.database.parameters.time_format);
switch (value) {
case false:
case "":
@@ -171,12 +198,17 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) {
throw new Error(value + " is not a correct float");
return parsed;
case 'float_time':
+ var factor = 1;
+ if (value[0] === '-') {
+ value = value.slice(1);
+ factor = -1;
+ }
var float_time_pair = value.split(":");
if (float_time_pair.length != 2)
- return openerp.web.parse_value(value, {type: "float"});
+ return factor * openerp.web.parse_value(value, {type: "float"});
var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"});
var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"});
- return hours + (minutes / 60);
+ return factor * (hours + (minutes / 60));
case 'progressbar':
return openerp.web.parse_value(value, {type: "float"});
case 'datetime':
diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js
index 6cd05100de5..74ae65785f9 100644
--- a/addons/web/static/src/js/search.js
+++ b/addons/web/static/src/js/search.js
@@ -154,7 +154,6 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
// for extended search view
var ext = new openerp.web.search.ExtendedSearch(this, this.model);
lines.push([ext]);
- this.inputs.push(ext);
this.extended_search = ext;
var render = QWeb.render("SearchView", {
@@ -187,7 +186,10 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
}).then(function(result) {
self.managed_filters = result;
var filters = self.$element.find(".oe_search-view-filters-management");
- filters.html(QWeb.render("SearchView.managed-filters", {filters: result}));
+ filters.html(QWeb.render("SearchView.managed-filters", {
+ filters: result,
+ disabled_filter_message: _t('Filter disabled due to invalid syntax')
+ }));
filters.change(self.on_filters_management);
});
},
@@ -425,13 +427,9 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
this.$element.find('table:last').hide();
$('.searchview_extended_groups_list').empty();
- _.each(this.inputs, function (input) {
- if(input.datewidget && input.datewidget.value) {
- input.datewidget.set_value(false);
- }
- });
- return $.async_when().pipe(
- reload_view !== false ? this.on_clear : null);
+ return $.async_when.apply(
+ null, _(this.inputs).invoke('clear')).pipe(
+ reload_view !== false ? this.on_clear : null);
},
/**
* Triggered when the search view gets cleared
@@ -618,7 +616,11 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp.
}
}
this.attrs = attrs;
- }
+ },
+ /**
+ * Specific clearing operations, if any
+ */
+ clear: function () {}
});
openerp.web.search.FilterGroup = openerp.web.search.Input.extend(/** @lends openerp.web.search.FilterGroup# */{
template: 'SearchView.filters',
@@ -900,6 +902,22 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o
defaults[this.attrs.name] = false;
}
return this._super(defaults);
+ },
+ clear: function () {
+ var self = this, d = $.Deferred(), selection = this.attrs.selection;
+ for(var index=0; index<selection.length; ++index) {
+ var item = selection[index];
+ if (!item[1]) {
+ setTimeout(function () {
+ // won't override mutable, because we immediately bail out
+ //noinspection JSReferencingMutableVariableFromClosure
+ self.$element.val(index);
+ d.resolve();
+ }, 0);
+ return d.promise();
+ }
+ }
+ return d.resolve().promise();
}
});
openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @lends openerp.web.search.BooleanField# */{
@@ -947,15 +965,20 @@ openerp.web.search.DateField = openerp.web.search.Field.extend(/** @lends opener
template: "SearchView.date",
start: function () {
this._super();
+ // FIXME: this insanity puts a div inside a span
this.datewidget = new openerp.web.DateWidget(this);
this.datewidget.prependTo(this.$element);
- this.datewidget.$element.find("input").attr("size", 15);
- this.datewidget.$element.find("input").attr("autofocus",
- this.attrs.default_focus === '1' ? 'autofocus' : undefined);
+ this.datewidget.$element.find("input")
+ .attr("size", 15)
+ .attr("autofocus", this.attrs.default_focus === '1' ? 'autofocus' : null)
+ .removeAttr('style');
this.datewidget.set_value(this.defaults[this.attrs.name] || false);
},
get_value: function () {
return this.datewidget.get_value() || null;
+ },
+ clear: function () {
+ this.datewidget.set_value(false);
}
});
/**
@@ -1051,7 +1074,7 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
}
});
-openerp.web.search.ExtendedSearch = openerp.web.search.Widget.extend({
+openerp.web.search.ExtendedSearch = openerp.web.search.Input.extend({
template: 'SearchView.extended_search',
init: function (parent, model) {
this._super(parent);
diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js
index 26376f24da2..0258509f172 100644
--- a/addons/web/static/src/js/view_editor.js
+++ b/addons/web/static/src/js/view_editor.js
@@ -27,6 +27,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
type: 'ir.actions.act_window',
target: "current",
limit: this.dataset.limit || 80,
+ auto_search : true,
flags: {
sidebar: false,
deletable: false,
@@ -45,9 +46,10 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
{text: _t("Create"), click: function() { self.on_create_view(); }},
{text: _t("Edit"), click: function() { self.xml_element_id = 0; self.get_arch(); }},
{text: _t("Remove"), click: function() { self.do_delete_view(); }},
- {text: _t("Close"), click: function() { self.view_edit_dialog.close(); }}
+ {text: _t("Close"), click: function() { self.view_edit_dialog.close(); window.location.reload(); }}
]
}).open();
+ this.view_edit_dialog.on_close.add_last(function(){window.location.reload();});
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new openerp.web.ActionManager(this);
this.action_manager.appendTo(this.view_edit_dialog);
@@ -162,11 +164,12 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
}
},
do_delete_view: function() {
+ var self = this;
if (confirm(_t("Do you really want to remove this view?"))) {
var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller;
this.dataset.unlink([this.main_view_id]).then(function() {
controller.reload_content();
- this.main_view_id = self.parent.fields_view.view_id;
+ self.main_view_id = self.parent.fields_view.view_id;
});
}
},
@@ -227,14 +230,14 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
get_arch: function() {
var self = this;
var view_arch_list = [];
- this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type']).then(function(arch) {
+ this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type','priority']).then(function(arch) {
if (arch.length) {
var arch_object = self.parse_xml(arch[0].arch, self.main_view_id);
self.main_view_type = arch[0].type == 'tree'? 'list': arch[0].type;
- view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch});
+ view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch,"priority":arch[0].priority});
self.dataset.read_slice([], {domain: [['inherit_id','=', parseInt(self.main_view_id)]]}).then(function(result) {
_.each(result, function(res) {
- view_arch_list.push({"view_id": res.id, "arch": res.arch});
+ view_arch_list.push({"view_id": res.id, "arch": res.arch,"priority":res.priority});
self.inherit_view(arch_object, res);
});
return self.edit_view({"main_object": arch_object,
@@ -303,7 +306,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
case 3:
//for field[@name='type']
obj = _.detect(arch_object, function(element){
- if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == check.length) {
+ if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == _.uniq(check).length) {
return element;
}
});
@@ -361,6 +364,20 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
title: _.str.sprintf(_t("View Editor %d - %s"), self.main_view_id, self.model),
height: '90%',
buttons: [
+ {text: _t("Inherited View"), click: function(){
+ var selected_row = self.edit_xml_dialog.$element.find('.ui-selected');
+ if (selected_row.length) {
+ if(selected_row.find('a').text().search("field") != -1){
+ if (confirm(_t("Do you really wants to create an inherited view here?"))) {
+ self.inherited_view(selected_row);
+ }
+ }else{
+ alert("Can't Update View");
+ }
+ }else{
+ alert("Select an element");
+ }
+ }},
{text: _t("Preview"), click: function() {
var action = {
context: self.session.user_context,
@@ -368,6 +385,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
views: [[self.main_view_id, self.main_view_type]],
type: 'ir.actions.act_window',
target: "new",
+ auto_search: true,
flags: {
sidebar: false,
views_switcher: false,
@@ -378,6 +396,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
action_manager.do_action(action);
}},
{text: _t("Close"), click: function(){
+ self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller.reload_content();
self.edit_xml_dialog.close();
}}
]
@@ -397,6 +416,53 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
self.on_select_img(this);
});
},
+ inherited_view: function(selected_row){
+ var self = this;
+ var row_id = parseInt((selected_row.attr('id')).split('-')[1]);
+ var obj = self.get_object_by_id(row_id,self.one_object['main_object'], [])[0];
+ var view_name = this.model + '.inherit_' + Math.round(Math.random() * 1000);
+ var view_find = selected_row;
+ var view_id;
+ var min_level = parseInt(selected_row.attr('level'));
+ while (1) {
+ view_find = view_find.prev();
+ if (view_find.length == 0 ||
+ self.edit_xml_dialog.$element.find(view_find).find('a').text().search("view_id") != -1 &&
+ parseInt(view_find.attr('level')) < min_level ) {
+ view_id = parseInt($(view_find).find('a').text().replace(/[^0-9]+/g, ''));
+ break;
+ }
+ if (view_find.attr('level') < min_level) {
+ min_level = parseInt(view_find.attr('level'));
+ }
+ }
+ var val = _.detect(obj.att_list, function(val) {return val[0] == "name";});
+ var priority = _.detect(self.one_object['arch'], function(val) {return val.view_id == view_id;});
+ var arch = _.str.sprintf("<?xml version='1.0'?>\n\t <field name='%s' position='after'> </field>", val[1]);
+ var vals = {'model': self.model, 'name': view_name, 'priority': priority.priority + 1, 'type': "form", 'arch': arch,'inherit_id':self.main_view_id};
+ this.dataset.create(vals, function(suc) {
+ var arch_to_obj = self.parse_xml(arch,suc.result);
+ obj.child_id.push(arch_to_obj[0]);
+ self.one_object['parent_child_id'] = self.parent_child_list(self.one_object['main_object'],[]);
+ self.one_object['arch'].push({'view_id':suc.result,"arch":arch,'priority': priority.priority + 1});
+ self.increase_level(arch_to_obj[0],obj.level+1);
+ self.render_inherited_view(selected_row,arch_to_obj[0]);
+ });
+ },
+ render_inherited_view: function(selected_row,obj){
+ var self = this,row_id = parseInt((selected_row.attr('id')).split('-')[1]);
+ var clone = this.create_clone(selected_row.clone(),obj);
+ if (selected_row.find("img[id^='parentimg-']").length == 0) {
+ ($(selected_row.find('a').parent()).siblings('td'))
+ .append($('<img width="16" height="16"></img>').attr('src', '/web/static/src/img/collapse.gif').
+ attr('id','parentimg-'+ row_id).click(function(){
+ self.do_parent_img_hide_show(this);
+ }));
+ }
+ self.edit_xml_dialog.$element.
+ find("tr[id='viewedit-"+row_id+"']").after(clone.removeClass('ui-selected'));
+ _.each(obj.child_id,function(obj){self.render_inherited_view(clone,obj);});
+ },
on_select_img: function(element_img) {
var self = this;
var side = $(element_img).closest("tr[id^='viewedit-']");
@@ -449,7 +515,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
},
do_node_add: function(side){
var self = this;
- var tr = $(side).find('a').text();
+ var tr = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], [])[0].att_list[0];
var parent_tr = ($(side).prevAll("tr[level=" + String(this.one_object.clicked_tr_level - 1) + "]"))[0];
var field_dataset = new openerp.web.DataSetSearch(this, this.model, null, null);
parent_tr = $(parent_tr).find('a').text();
@@ -562,13 +628,13 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
arch.arch = _.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 == check_list.length ) {return xml_child;}
+ if (insert.length == _.uniq(check_list).length ) {return xml_child;}
});
}
arch_to_pass = _.filter($(arch.arch), function (child) {
return child.nodeType == 1;
});
- return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],[], move_direct, update_values,arch);
+ return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
},
get_object_by_id: function(id, one_object, result) {
var self = this;
@@ -583,7 +649,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
}
return result;
},
- create_clone: function(clone, new_node_obj, position){
+ create_clone: function(clone, new_node_obj){
var self = this;
clone.find('a').text(new_node_obj.name);
($(clone.find('a').parent()).siblings('td')).css( "padding-left", 20 * new_node_obj.level);
@@ -599,7 +665,8 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
return clone;
},
do_save_xml: function(arch1, obj, child_list, move_direct, update_values, arch){
- var self = this, children_list = $(arch1).children(), list_obj_xml = _.zip(children_list, obj.child_id);
+ var self = this, children_list = $(arch1).children(),list_obj_xml;
+ try{list_obj_xml = _.zip(children_list, obj.child_id);}catch(err){return;}
if (this.one_object.clicked_tr_id) {
if (obj.id == this.one_object.clicked_tr_id) {
var parent = false, index = _.indexOf(child_list, obj);
@@ -823,6 +890,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
var value = _.detect(arch_val[0]['att_list'],function(res) {
return res instanceof Array? _.include(res, widget.name): false;
});
+
value = value instanceof Array ? value[1] : value;
self.edit_node_dialog.$element.find('table[id=rec_table]').append('<tr><td align="right">' + widget.string + ':</td>' + type_widget.render() + '</tr>');
type_widget.start();
@@ -845,7 +913,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
res_groups.read_slice([], {}).done(function (res_grp) {
_.each(res_grp, function (res) {
var key = res.id;
- group_names[key] = res.name;
+ group_names[key]=res.full_name;
group_ids.push(res.id);
});
model_data.read_slice([], {domain: [
@@ -933,16 +1001,16 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
var action_manager = new openerp.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
var controller = action_manager.dialog_viewmanager.views['form'].controller;
- // TODO NIV: use page view
- controller.do_set_readonly.add_last(function(){
+ controller.on_button_cancel.add_last(function(){
+ action_manager.stop()
+ });
+ controller.do_save.add_last(function(){
action_manager.stop();
- new_fields_name = new openerp.web.DataSetSearch(self,'ir.model.fields', null, null);
- new_fields_name.read_ids([controller.datarecord.id], ['name']).then(function(result) {
- self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value", result[0].name).text(result[0].name));
+ var value =controller.fields.name.value;
+ self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value",value).text(value));
_.detect(self.add_widget,function(widget){
- widget.name == "field_value"? widget.selection.push(result[0].name): false;
+ widget.name == "field_value"? widget.selection.push(value): false;
});
- });
});
});
}
@@ -1039,7 +1107,7 @@ openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({
var index = 0;
value = value === null? false: value;
for (var i = 0, ii = this.selection.length; i < ii; i++) {
- if ((this.selection[i] instanceof Array && this.selection[i][1] === value) || this.selection[i] === value) index = i;
+ if ((this.selection[i] instanceof Array && this.selection[i][0] === value) || this.selection[i] === value) index = i;
}
this.$element.find("select[id=" + this.name + "]")[0].selectedIndex = index;
},
@@ -1092,10 +1160,10 @@ var _CHILDREN = {
'calendar': ['field'],
'notebook': ['page'],
'page': ['notebook', 'group', 'field', 'label', 'button', 'newline', 'separator'],
- 'group': ['field', 'label', 'button', 'separator', 'newline'],
+ 'group': ['field', 'label', 'button', 'separator', 'newline','group'],
'board': ['column'],
'action': [],
- 'field': ['form', 'tree', 'graph'],
+ 'field': ['form', 'tree', 'graph','field'],
'label': [],
'button' : [],
'newline': [],
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index ca1c2c29e6e..3f576089e5b 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -121,6 +121,15 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
this.sidebar.attachments = new openerp.web.form.SidebarAttachments(this.sidebar, this);
this.sidebar.add_toolbar(this.fields_view.toolbar);
this.set_common_sidebar_sections(this.sidebar);
+
+ this.sidebar.add_section(_t('Customize'), 'customize');
+ this.sidebar.add_items('customize', [{
+ label: _t('Set Default'),
+ form: this,
+ callback: function (item) {
+ item.form.open_defaults_dialog();
+ }
+ }]);
}
this.has_been_loaded.resolve();
},
@@ -140,6 +149,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
do_show: function () {
var self = this;
this.$element.show().css('visibility', 'hidden');
+ this.$element.removeClass('oe_form_dirty');
return this.has_been_loaded.pipe(function() {
var result;
if (self.dataset.index === null) {
@@ -168,7 +178,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
on_record_loaded: function(record) {
var self = this, set_values = [];
if (!record) {
- throw new Error("Form: No record received");
+ this.do_warn("Form", "The record could not be found in the database.", true);
+ return $.Deferred().reject();
}
this.datarecord = record;
@@ -204,6 +215,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (record.id) {
self.do_push_state({id:record.id});
}
+ self.$element.removeClass('oe_form_dirty');
});
},
on_form_changed: function() {
@@ -216,6 +228,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
w.update_dom();
}
},
+ do_notify_change: function() {
+ this.$element.addClass('oe_form_dirty');
+ },
on_pager_action: function(action) {
if (this.can_be_discarded()) {
switch (action) {
@@ -437,7 +452,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
});
},
on_button_cancel: function() {
- return this.do_prev_view({'default': 'page'});
+ if (this.can_be_discarded()) {
+ return this.do_prev_view({'default': 'page'});
+ }
},
on_button_new: function() {
var self = this;
@@ -459,8 +476,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
return def.promise();
},
can_be_discarded: function() {
- return true; // FIXME: Disabled until the page view and button refactoring is done
- return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
+ return !this.$element.is('.oe_form_dirty') || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
},
/**
* Triggers saving the form's record. Chooses between creating a new
@@ -559,10 +575,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
} else {
this.datarecord.id = r.result;
if (!prepend_on_create) {
- this.dataset.ids.push(this.datarecord.id);
+ this.dataset.alter_ids(this.dataset.ids.concat([this.datarecord.id]));
this.dataset.index = this.dataset.ids.length - 1;
} else {
- this.dataset.ids.unshift(this.datarecord.id);
+ this.dataset.alter_ids([this.datarecord.id].concat(this.dataset.ids));
this.dataset.index = 0;
}
this.do_update_pager();
@@ -631,6 +647,82 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
},
sidebar_context: function () {
return this.do_save().pipe(_.bind(function() {return this.get_fields_values();}, this));
+ },
+ open_defaults_dialog: function () {
+ var self = this;
+ var fields = _.chain(this.fields)
+ .map(function (field, name) {
+ var value = field.get_value();
+ // ignore fields which are empty, invisible, readonly, o2m
+ // or m2m
+ if (!value
+ || field.invisible
+ || field.readonly
+ || field.field.type === 'one2many'
+ || field.field.type === 'many2many') {
+ return false;
+ }
+ var displayed;
+ switch(field.field.type) {
+ case 'selection':
+ displayed = _(field.values).find(function (option) {
+ return option[0] === value;
+ })[1];
+ break;
+ case 'many2one':
+ displayed = field.value[1] || value;
+ break;
+ default:
+ displayed = value;
+ }
+
+ return {
+ name: name,
+ string: field.string,
+ value: value,
+ displayed: displayed,
+ // convert undefined to false
+ change_default: !!field.field.change_default
+ }
+ })
+ .compact()
+ .sortBy(function (field) { return field.string; })
+ .value();
+ var conditions = _.chain(fields)
+ .filter(function (field) { return field.change_default; })
+ .value();
+
+ var d = new openerp.web.Dialog(this, {
+ title: _t("Set Default"),
+ args: {
+ fields: fields,
+ conditions: conditions
+ },
+ buttons: [
+ {text: _t("Close"), click: function () { d.close(); }},
+ {text: _t("Save default"), click: function () {
+ var $defaults = d.$element.find('#formview_default_fields');
+ var field_to_set = $defaults.val();
+ if (!field_to_set) {
+ $defaults.parent().addClass('invalid');
+ return;
+ }
+ var condition = d.$element.find('#formview_default_conditions').val(),
+ all_users = d.$element.find('#formview_default_all').is(':checked');
+ new openerp.web.DataSet(self, 'ir.values').call(
+ 'set_default', [
+ self.dataset.model,
+ field_to_set,
+ self.fields[field_to_set].get_value(),
+ all_users,
+ false,
+ condition || false
+ ]).then(function () { d.close(); });
+ }}
+ ]
+ });
+ d.template = 'FormView.set_default';
+ d.open();
}
});
openerp.web.FormDialog = openerp.web.Dialog.extend({
@@ -831,7 +923,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo
},
stop: function() {
this._super.apply(this, arguments);
- $('div.tipsy').stop().remove();
+ $.fn.tipsy.clear();
},
process_modifiers: function() {
var compute_domain = openerp.web.form.compute_domain;
@@ -861,7 +953,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo
debug: openerp.connection.debug,
widget: widget
})},
- gravity: $.fn.tipsy.autoBounds(50, 'n'),
+ gravity: $.fn.tipsy.autoBounds(50, 'nw'),
html: true,
opacity: 0.85,
trigger: 'hover'
@@ -1219,6 +1311,11 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({
this._super(view, node);
+ if (this.node.tag == 'label' && !this.string && this.node.children.length) {
+ this.string = this.node.children[0];
+ this.align = 'left';
+ }
+
if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) {
this.form_template = "WidgetParagraph";
this.colspan = parseInt(this.node.attrs.colspan || 1, 10);
@@ -1227,6 +1324,8 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({
if (isNaN(parseFloat(this.node.attrs.align))) {
this.align = 'left';
}
+
+ this.multilines = this.string && _.str.lines(this.string).length > 1;
} else {
this.colspan = 1;
this.width = '1%';
@@ -1293,6 +1392,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this._super.apply(this, arguments);
if (this.field.translate) {
this.view.translatable_fields.push(this);
+ this.$element.addClass('oe_form_field_translatable');
this.$element.find('.oe_field_translate').click(this.on_translate);
}
if (this.nolabel && openerp.connection.debug) {
@@ -1344,7 +1444,8 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
if (this.is_valid()) {
this.set_value_from_ui();
this.view.do_onchange(this);
- this.view.on_form_changed();
+ this.view.on_form_changed(true);
+ this.view.do_notify_change();
} else {
this.update_dom(true);
}
@@ -1389,7 +1490,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
- this.$element.find('input').prop('disabled', this.readonly);
+ this.$element.find('input').prop('readonly', this.readonly);
},
set_value_from_ui: function() {
this.value = openerp.web.parse_value(this.$element.find('input').val(), this);
@@ -1412,7 +1513,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({
openerp.web.form.FieldID = openerp.web.form.FieldChar.extend({
update_dom: function() {
this._super.apply(this, arguments);
- this.$element.find('input').prop('disabled', true);
+ this.$element.find('input').prop('readonly', true);
}
});
@@ -1490,7 +1591,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({
showButtonPanel: true
});
this.$element.find('img.oe_datepicker_trigger').click(function() {
- if (!self.readonly) {
+ if (!self.readonly && !self.picker('widget').is(':visible')) {
self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
self.$input_picker.show();
self.picker('show');
@@ -1520,7 +1621,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({
},
set_readonly: function(readonly) {
this.readonly = readonly;
- this.$input.prop('disabled', this.readonly);
+ this.$input.prop('readonly', this.readonly);
this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
},
is_valid: function(required) {
@@ -1609,7 +1710,7 @@ openerp.web.form.FieldText = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
- this.$element.find('textarea').prop('disabled', this.readonly);
+ this.$element.find('textarea').prop('readonly', this.readonly);
},
set_value_from_ui: function() {
this.value = openerp.web.parse_value(this.$element.find('textarea').val(), this);
@@ -2126,7 +2227,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
- this.$input.prop('disabled', this.readonly);
+ this.$input.prop('readonly', this.readonly);
}
});
@@ -2248,7 +2349,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, {});
this.viewmanager.template = 'One2Many.viewmanager';
- this.viewmanager.registry = openerp.web.views.clone({
+ this.viewmanager.registry = openerp.web.views.extend({
list: 'openerp.web.form.One2ManyListView',
form: 'openerp.web.form.One2ManyFormView',
page: 'openerp.web.PageView'
@@ -2326,13 +2427,13 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix);
obj.defaults = {};
self.dataset.to_create.push(obj);
- self.dataset.cache.push(_.clone(obj));
+ self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
ids.push(obj.id);
return;
case commands.UPDATE:
obj['id'] = command[1];
self.dataset.to_write.push(obj);
- self.dataset.cache.push(_.clone(obj));
+ self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
ids.push(obj.id);
return;
case commands.DELETE:
@@ -2539,6 +2640,13 @@ openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({
this.$form_header.find('button.oe_form_button_create').click(function() {
self.do_save().then(self.on_button_new);
});
+ },
+ do_notify_change: function() {
+ if (this.dataset.parent_view) {
+ this.dataset.parent_view.do_notify_change();
+ } else {
+ this._super.apply(this, arguments);
+ }
}
});
@@ -3151,7 +3259,7 @@ openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({
update_dom: function() {
this._super.apply(this, arguments);
this.$element.find('.oe-binary-file-set, .oe-binary-file-clear').toggle(!this.readonly);
- this.$element.find('input[type=text]').prop('disabled', this.readonly);
+ this.$element.find('input[type=text]').prop('readonly', this.readonly);
},
set_value: function(value) {
this._super.apply(this, arguments);
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index 7fd4d20fba5..eb13bbd927b 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -246,7 +246,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
self.page = 0; break;
case 'last':
self.page = Math.floor(
- self.dataset.ids.length / self.limit());
+ self.dataset.size() / self.limit());
break;
case 'next':
self.page += 1; break;
@@ -293,7 +293,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
this.dataset.ids = dataset.ids;
var limit = this.limit(),
- total = dataset.ids.length,
+ total = dataset.size(),
first = (this.page * limit),
last;
if (!limit || (total - first) < limit) {
@@ -1317,11 +1317,11 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
if (!self.datagroup.openable) {
view.configure_pager(dataset);
} else {
- if (dataset.ids.length == records.length) {
+ if (dataset.size() == records.length) {
// only one page
self.$row.find('td.oe-group-pagination').empty();
} else {
- var pages = Math.ceil(dataset.ids.length / limit);
+ var pages = Math.ceil(dataset.size() / limit);
self.$row
.find('.oe-pager-state')
.text(_.str.sprintf(_t("%(page)d/%(page_count)d"), {
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index 4f6a1531c7a..c7222455889 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -386,7 +386,7 @@ openerp.web.list_editable = function (openerp) {
template: 'ListView.row.frame'
});
var form_widgets = openerp.web.form.widgets;
- openerp.web.list.form.widgets = form_widgets.clone({
+ openerp.web.list.form.widgets = form_widgets.extend({
'frame': 'openerp.web.list.form.WidgetFrame'
});
// All form widgets inherit a problematic behavior from
@@ -395,7 +395,7 @@ openerp.web.list_editable = function (openerp) {
// former should completely remove the cell. We need to override update_dom
// on all widgets since we can't just hit on widget itself (I think)
var list_form_widgets = openerp.web.list.form.widgets;
- _(list_form_widgets.map).each(function (widget_path, key) {
+ _(form_widgets.map).each(function (widget_path, key) {
if (key === 'frame') { return; }
var new_path = 'openerp.web.list.form.' + key;
diff --git a/addons/web/static/src/js/view_page.js b/addons/web/static/src/js/view_page.js
index be3863e9918..95259a01927 100644
--- a/addons/web/static/src/js/view_page.js
+++ b/addons/web/static/src/js/view_page.js
@@ -92,11 +92,13 @@ openerp.web.page = function (openerp) {
openerp.web.page.FieldURIReadonly = openerp.web.page.FieldCharReadonly.extend({
form_template: 'FieldURI.readonly',
scheme: null,
+ format_value: function (value) {
+ return value;
+ },
set_value: function (value) {
- var displayed = this._super.apply(this, arguments);
this.$element.find('a')
- .attr('href', this.scheme + ':' + displayed)
- .text(displayed);
+ .attr('href', this.scheme + ':' + value)
+ .text(this.format_value(value));
}
});
openerp.web.page.FieldEmailReadonly = openerp.web.page.FieldURIReadonly.extend({
@@ -105,9 +107,10 @@ openerp.web.page = function (openerp) {
openerp.web.page.FieldUrlReadonly = openerp.web.page.FieldURIReadonly.extend({
set_value: function (value) {
var s = /(\w+):(.+)/.exec(value);
- if (!s || !(s[1] === 'http' || s[1] === 'https')) { return; }
- this.scheme = s[1];
- this._super(s[2]);
+ if (!s) {
+ value = "http://" + value;
+ }
+ this.$element.find('a').attr('href', value).text(value);
}
});
openerp.web.page.FieldBooleanReadonly = openerp.web.form.FieldBoolean.extend({
@@ -242,7 +245,7 @@ openerp.web.page = function (openerp) {
}
}
});
- openerp.web.page.readonly = openerp.web.form.widgets.clone({
+ openerp.web.page.readonly = openerp.web.form.widgets.extend({
'frame': 'openerp.web.page.WidgetFrameReadonly',
'char': 'openerp.web.page.FieldCharReadonly',
'id': 'openerp.web.page.FieldCharReadonly',
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 7c1f7385927..56997190bc1 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -602,16 +602,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
width: '95%'}, $root).open();
});
break;
- case 'customize_object':
- this.rpc('/web/dataset/search_read', {
- model: 'ir.model',
- fields: ['id'],
- domain: [['model', '=', this.dataset.model]]
- }, function (result) {
- self.do_edit_resource('ir.model', result.ids[0], {
- name : _t("Customize Object") });
- });
- 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);
@@ -765,16 +755,21 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
var $logs_list = $logs.find('ul').empty();
$logs.toggleClass('oe-has-more', log_records.length > cutoff);
_(log_records.reverse()).each(function (record) {
+ var context = {};
+ if (record.context) {
+ try { context = py.eval(record.context).toJSON(); }
+ catch (e) { /* TODO: what do I do now? */ }
+ }
$(_.str.sprintf('<li><a href="#">%s</a></li>', record.name))
.appendTo($logs_list)
- .delegate('a', 'click', function (e) {
+ .delegate('a', 'click', function () {
self.do_action({
type: 'ir.actions.act_window',
res_model: record.res_model,
res_id: record.res_id,
// TODO: need to have an evaluated context here somehow
- //context: record.context,
- views: [[false, 'form']]
+ context: context,
+ views: [[context.view_id || false, 'form']]
});
return false;
});
@@ -821,10 +816,6 @@ session.web.Sidebar = session.web.OldWidget.extend({
}, {
label: _t("Export"),
callback: view.on_sidebar_export
- }, {
- label: _t("View Log"),
- callback: view.on_sidebar_view_log,
- classname: 'oe_hide oe_sidebar_view_log'
}
]);
},
@@ -863,18 +854,32 @@ session.web.Sidebar = session.web.OldWidget.extend({
}
return $section;
},
-
+ /**
+ * For each item added to the section:
+ *
+ * ``label``
+ * will be used as the item's name in the sidebar
+ *
+ * ``action``
+ * descriptor for the action which will be executed, ``action`` and
+ * ``callback`` should be exclusive
+ *
+ * ``callback``
+ * function to call when the item is clicked in the sidebar, called
+ * with the item descriptor as its first argument (so information
+ * can be stored as additional keys on the object passed to
+ * ``add_items``)
+ *
+ * ``classname`` (optional)
+ * ``@class`` set on the sidebar serialization of the item
+ *
+ * ``title`` (optional)
+ * will be set as the item's ``@title`` (tooltip)
+ *
+ * @param {String} section_code
+ * @param {Array<{label, action | callback[, classname][, title]}>} items
+ */
add_items: function(section_code, items) {
- // An item is a dictonary : {
- // label: label to be displayed for the link,
- // action: action to be launch when the link is clicked,
- // callback: a function to be executed when the link is clicked,
- // classname: optional dom class name for the line,
- // title: optional title for the link
- // }
- // Note: The item should have one action or/and a callback
- //
-
var self = this,
$section = this.add_section(_.str.titleize(section_code.replace('_', ' ')), section_code),
section_id = $section.attr('id');
@@ -1038,7 +1043,8 @@ session.web.TranslateDialog = session.web.Dialog.extend({
},
on_button_Save: function() {
var trads = {},
- self = this;
+ self = this,
+ trads_mutex = new $.Mutex();
self.$fields_form.find('.oe_trad_field.touched').each(function() {
var field = $(this).attr('name').split('-');
if (!trads[field[0]]) {
@@ -1051,9 +1057,10 @@ session.web.TranslateDialog = session.web.Dialog.extend({
_.each(data, function(value, field) {
self.view.fields[field].set_value(value);
});
- } else {
- self.view.dataset.write(self.view.datarecord.id, data, { 'lang': code });
}
+ trads_mutex.exec(function() {
+ return self.view.dataset.write(self.view.datarecord.id, data, { context : { 'lang': code } });
+ });
});
this.close();
},
@@ -1222,8 +1229,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
view_mode : "list"
});
},
- on_sidebar_view_log: function() {
- },
sidebar_context: function () {
return $.when();
},