[MERGE] Merge with trunk upto revison no 1256.

bzr revid: ysa@tinyerp.com-20111014045839-rc5gvd0crl20pjqv
This commit is contained in:
Yogesh (OpenERP)
2011-10-14 10:28:39 +05:30
10 changed files with 223 additions and 119 deletions
+3 -2
View File
@@ -227,7 +227,7 @@ class HttpRequest(WebRequest):
_logger.debug("%s --> %s.%s %r", self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
r = method(controller, self, **self.params)
if self.debug or 1:
if isinstance(r, werkzeug.wrappers.BaseResponse):
if isinstance(r, (werkzeug.wrappers.BaseResponse, werkzeug.exceptions.HTTPException)):
_logger.debug('<-- %s', r)
else:
_logger.debug("<-- size: %s", len(r))
@@ -395,7 +395,8 @@ class Root(object):
else:
response = result
response.set_cookie(self.session_cookie, session.sid)
if hasattr(response, 'set_cookie'):
response.set_cookie(self.session_cookie, session.sid)
return response(environ, start_response)
+36 -19
View File
@@ -5,15 +5,16 @@ openerp.web.chrome = function(openerp) {
var QWeb = openerp.web.qweb;
openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{
/**
* @constructs openerp.web.Notification
* @extends openerp.web.Widget
*
* @param parent
* @param element_id
*/
init: function(parent, element_id) {
this._super(parent, element_id);
template: 'Notification',
identifier_prefix: 'notification-',
init: function() {
this._super.apply(this, arguments);
openerp.notification = this;
},
start: function() {
this._super.apply(this, arguments);
this.$element.notify({
speed: 500,
expires: 1500
@@ -28,9 +29,12 @@ openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Not
warn: function(title, text) {
this.$element.notify('create', 'oe_notification_alert', {
title: title,
text: text
text: text,
}, {
expires: false,
});
}
},
});
openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog# */{
@@ -369,7 +373,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
}
$db_list.find(':selected').remove();
self.db_list.splice(_.indexOf(self.db_list, db, true), 1);
self.notification.notify("Dropping database", "The database '" + db + "' has been dropped");
self.do_notify("Dropping database", "The database '" + db + "' has been dropped");
});
}
});
@@ -454,7 +458,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
self.display_error(result);
return;
}
self.notification.notify("Changed Password", "Password has been changed successfully");
self.do_notify("Changed Password", "Password has been changed successfully");
});
}
});
@@ -788,9 +792,8 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
},
start: function() {
this.$secondary_menu.addClass(this.folded ? 'oe_folded' : 'oe_unfolded');
this.reload();
},
reload: function() {
do_reload: function() {
this.rpc("/web/menu/load", {}, this.on_loaded);
},
on_loaded: function(data) {
@@ -939,14 +942,12 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
}
this.$element.html(QWeb.render("Interface", params));
this.notification = new openerp.web.Notification();
this.session = new openerp.web.Session();
this.loading = new openerp.web.Loading(this,"oe_loading");
this.crashmanager = new openerp.web.CrashManager(this);
this.crashmanager.start();
// Do you autorize this ? will be replaced by notify() in controller
openerp.web.Widget.prototype.notification = new openerp.web.Notification(this, "oe_notification");
this.header = new openerp.web.Header(this);
this.login = new openerp.web.Login(this);
this.header.on_logout.add(this.login.on_logout);
@@ -966,12 +967,27 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
start: function() {
this._super.apply(this, arguments);
this.notification.prependTo(this.$element);
this.header.appendTo($("#oe_header"));
this.session.start();
this.login.appendTo($('#oe_login'));
this.menu.start();
},
do_reload: function() {
this.session.session_restore();
this.menu.do_reload();
},
do_notify: function() {
var n = this.notification;
n.notify.apply(n, arguments);
},
do_warn: function() {
var n = this.notification;
n.warn.apply(n, arguments);
},
on_logged: function() {
this.menu.do_reload();
if(this.action_manager)
this.action_manager.stop();
this.action_manager = new openerp.web.ActionManager(this);
@@ -1058,7 +1074,8 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
this.action_manager.do_action(action);
},
do_about: function() {
}
},
});
};
+107 -31
View File
@@ -610,44 +610,120 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
on_default_get: function(res) {
this.last_default_get = res;
},
/**
* Makes sure this dataset has the fields_get for its model stored locally,
* so create/write methods are able to determine if written fields are m2os
* and can name_get those fields if that's the case (in order to cache a
* correct m2o value for them)
*
* @returns {$.Deferred} whether the fields_get is done executing, provides the fields_get value to its callbacks
*/
ensure_has_fields: function () {
var self = this;
if (this.fields_get) {
var d = $.Deferred();
setTimeout(function () { d.resolve(self.fields_get, true); }, 0);
return d.promise();
} else {
return self.call('fields_get', [], function (fields_get) {
self.fields_get = fields_get;
});
}
},
/**
* Relational fields may not be written in the same format they are read.
*
* Since the BufferedDataSet is a bit dumb, it returns what it's got stored
* in its cache, which for modified value is what it was given. This breaks
* some basic contracts of openerp such as m2o read being in the
* ``name_get`` format.
*
* Because create & write are supposed to be asynchronous, though, it
* should be easy to just name_get all incorrect values.
*
* @param {Object} data form-data to write to the cache
* @returns {$.Deferred} resolved with a fixed data dictionary
*/
fix_relational: function (data) {
var self = this;
var results = $.Deferred();
this.ensure_has_fields().then(function (fields) {
var fields_to_fix = _(fields).chain()
.map(function (d, k) { return {key: k, descriptor: d}; })
.filter(function (field) {
// keep m2o fields which are in the data dict
return field.descriptor.type === 'many2one' &&
data[field.key];
}).pluck('key')
.value();
var name_gets = _(fields_to_fix).map(function (field) {
return new openerp.web.DataSet(self, self.fields_get[field].relation)
.name_get([data[field]], null);
});
// null-concat forces stupid bastard `when` to always return an
// array containing the Array-ified results of all the name_gets.
// otherwise, if there's a single field to fix it returns the
// results of the unique name_get directly.
$.when.apply(null, name_gets.concat([null])).then(function () {
var record = _.extend({}, data);
for(var i=0; i<fields_to_fix.length; ++i) {
// Each argument is [[name_get], success, jqXhr] and we
// want just the name_get pair
record[fields_to_fix[i]] = arguments[i][0][0];
}
results.resolve(record);
});
});
return results;
},
create: function(data, callback, error_callback) {
var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data,
defaults: this.last_default_get};
this.to_create.push(_.extend(_.clone(cached), {values: _.clone(cached.values)}));
this.cache.push(cached);
this.on_change();
var self = this;
var prom = $.Deferred().then(callback);
prom.resolve({result: cached.id});
this.fix_relational(data).then(function (fixed_m2o_data) {
var cached = {
id:_.uniqueId(self.virtual_id_prefix),
values: fixed_m2o_data,
defaults: self.last_default_get
};
self.to_create.push(_.extend(_.clone(cached), {
values: _.clone(data)}));
self.cache.push(cached);
self.on_change();
prom.resolve({result: cached.id});
});
return prom.promise();
},
write: function (id, data, options, callback) {
var self = this;
var record = _.detect(this.to_create, function(x) {return x.id === id;});
record = record || _.detect(this.to_write, function(x) {return x.id === id;});
var dirty = false;
if (record) {
for (var k in data) {
if (record.values[k] === undefined || record.values[k] !== data[k]) {
dirty = true;
break;
}
}
$.extend(record.values, data);
} else {
dirty = true;
record = {id: id, values: data};
self.to_write.push(record);
}
var cached = _.detect(this.cache, function(x) {return x.id === id;});
if (!cached) {
cached = {id: id, values: {}};
this.cache.push(cached);
}
$.extend(cached.values, record.values);
if (dirty)
this.on_change();
var to_return = $.Deferred().then(callback);
to_return.resolve({result: true});
this.fix_relational(data).then(function (fixed_m2o_data) {
var record = _.detect(self.to_create, function(x) {return x.id === id;});
record = record || _.detect(self.to_write, function(x) {return x.id === id;});
var dirty = false;
if (record) {
for (var k in data) {
if (record.values[k] === undefined || record.values[k] !== data[k]) {
dirty = true;
break;
}
}
_.extend(record.values, data);
} else {
dirty = true;
record = {id: id, values: data};
self.to_write.push(record);
}
var cached = _.detect(self.cache, function(x) {return x.id === id;});
if (!cached) {
cached = {id: id, values: {}};
this.cache.push(cached);
}
_.extend(cached.values, fixed_m2o_data);
if (dirty)
self.on_change();
to_return.resolve({result: true});
});
return to_return.promise();
},
unlink: function(ids, callback, error_callback) {
+1 -1
View File
@@ -336,7 +336,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
* @param {Array} errors a never-empty array of error objects
*/
on_invalid: function (errors) {
this.notification.notify("Invalid Search", "triggered from search view");
this.do_notify("Invalid Search", "triggered from search view");
},
do_clear: function () {
this.$element.find('.filter_label, .filter_icon').removeClass('enabled');
+64 -56
View File
@@ -443,7 +443,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
}
});
msg += "</ul>";
this.notification.warn("The following fields are invalid :", msg);
this.do_warn("The following fields are invalid :", msg);
},
on_saved: function(r, success) {
if (!r.result) {
@@ -451,7 +451,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
return $.Deferred().reject();
} else {
this.reload();
return $.when().then(success);
return $.when(r).then(success);
}
},
/**
@@ -485,7 +485,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
this.sidebar.attachments.do_update();
}
console.debug("The record has been created with id #" + this.datarecord.id);
this.reload()
this.reload();
return $.when(_.extend(r, {created: true})).then(success);
}
},
@@ -616,7 +616,7 @@ openerp.web.form.SidebarAttachments = openerp.web.Widget.extend({
ids: [parseInt($e.attr('data-id'))]
}, function(r) {
$e.parent().remove();
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
self.do_notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
});
}
}
@@ -735,6 +735,51 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.
render: function() {
var template = this.template;
return QWeb.render(template, { "widget": this });
},
_build_view_fields_values: function() {
var a_dataset = this.view.dataset;
var fields_values = this.view.get_fields_values();
var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {};
fields_values.parent = parent_values;
return fields_values;
},
_build_eval_context: function() {
var a_dataset = this.view.dataset;
return new openerp.web.CompoundContext(a_dataset.get_context(), this._build_view_fields_values());
},
/**
* Builds a new context usable for operations related to fields by merging
* the fields'context with the action's context.
*/
build_context: function() {
var f_context = (this.field || {}).context || {};
if (!!f_context.__ref) {
var fields_values = this._build_eval_context();
f_context = new openerp.web.CompoundDomain(f_context).set_eval_context(fields_values);
}
// maybe the default_get should only be used when we do a default_get?
var v_contexts = _.compact([this.node.attrs.default_get || null,
this.node.attrs.context || null]);
var v_context = new openerp.web.CompoundContext();
_.each(v_contexts, function(x) {v_context.add(x);});
if (_.detect(v_contexts, function(x) {return !!x.__ref;})) {
var fields_values = this._build_eval_context();
v_context.set_eval_context(fields_values);
}
// if there is a context on the node, overrides the model's context
var ctx = v_contexts.length > 0 ? v_context : f_context;
return ctx;
},
build_domain: function() {
var f_domain = this.field.domain || [];
var n_domain = this.node.attrs.domain || null;
// if there is a domain on the node, overrides the model's domain
var final_domain = n_domain !== null ? n_domain : f_domain;
if (!(final_domain instanceof Array)) {
var fields_values = this._build_eval_context();
final_domain = new openerp.web.CompoundDomain(final_domain).set_eval_context(fields_values);
}
return final_domain;
}
});
@@ -956,9 +1001,16 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
},
on_confirmed: function() {
var self = this;
var context = this.node.attrs.context;
if (context && context.__ref) {
context = new openerp.web.CompoundContext(context);
context.set_eval_context(this._build_eval_context());
}
return this.view.do_execute_action(
this.node.attrs, this.view.dataset, this.view.datarecord.id, function () {
_.extend({}, this.node.attrs, {context: context}),
this.view.dataset, this.view.datarecord.id, function () {
self.view.reload();
});
},
@@ -1105,51 +1157,6 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this.invalid = false;
},
focus: function() {
},
_build_view_fields_values: function() {
var a_dataset = this.view.dataset;
var fields_values = this.view.get_fields_values();
var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {};
fields_values.parent = parent_values;
return fields_values;
},
_build_eval_context: function() {
var a_dataset = this.view.dataset;
return new openerp.web.CompoundContext(a_dataset.get_context(), this._build_view_fields_values());
},
/**
* Builds a new context usable for operations related to fields by merging
* the fields'context with the action's context.
*/
build_context: function() {
var f_context = this.field.context || {};
if (!!f_context.__ref) {
var fields_values = this._build_eval_context();
f_context = new openerp.web.CompoundDomain(f_context).set_eval_context(fields_values);
}
// maybe the default_get should only be used when we do a default_get?
var v_contexts = _.compact([this.node.attrs.default_get || null,
this.node.attrs.context || null]);
var v_context = new openerp.web.CompoundContext();
_.each(v_contexts, function(x) {v_context.add(x);});
if (_.detect(v_contexts, function(x) {return !!x.__ref;})) {
var fields_values = this._build_eval_context();
v_context.set_eval_context(fields_values);
}
// if there is a context on the node, overrides the model's context
var ctx = v_contexts.length > 0 ? v_context : f_context;
return ctx;
},
build_domain: function() {
var f_domain = this.field.domain || [];
var n_domain = this.node.attrs.domain || null;
// if there is a domain on the node, overrides the model's domain
var final_domain = n_domain !== null ? n_domain : f_domain;
if (!(final_domain instanceof Array)) {
var fields_values = this._build_eval_context();
final_domain = new openerp.web.CompoundDomain(final_domain).set_eval_context(fields_values);
}
return final_domain;
}
});
@@ -1195,7 +1202,7 @@ openerp.web.form.FieldEmail = openerp.web.form.FieldChar.extend({
},
on_button_clicked: function() {
if (!this.value || !this.is_valid()) {
this.notification.warn("E-mail error", "Can't send email to invalid e-mail address");
this.do_warn("E-mail error", "Can't send email to invalid e-mail address");
} else {
location.href = 'mailto:' + this.value;
}
@@ -1210,7 +1217,7 @@ openerp.web.form.FieldUrl = openerp.web.form.FieldChar.extend({
},
on_button_clicked: function() {
if (!this.value) {
this.notification.warn("Resource error", "This resource is empty");
this.do_warn("Resource error", "This resource is empty");
} else {
window.open(this.value);
}
@@ -2476,7 +2483,6 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp
this.setup_form_view();
},
on_write: function(id, data) {
this.stop();
if (!this.options.auto_write)
return;
var self = this;
@@ -2499,7 +2505,9 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp
$buttons.html(QWeb.render("FormOpenPopup.form.buttons"));
var $nbutton = $buttons.find(".oe_formopenpopup-form-save");
$nbutton.click(function() {
self.view_form.do_save();
self.view_form.do_save().then(function() {
self.stop();
});
});
var $cbutton = $buttons.find(".oe_formopenpopup-form-close");
$cbutton.click(function() {
@@ -2626,7 +2634,7 @@ openerp.web.form.FieldBinary = openerp.web.form.Field.extend({
on_file_uploaded: function(size, name, content_type, file_base64) {
delete(window[this.iframe]);
if (size === false) {
this.notification.warn("File Upload", "There was a problem while uploading your file");
this.do_warn("File Upload", "There was a problem while uploading your file");
// TODO: use openerp web crashmanager
console.warn("Error while uploading file : ", name);
} else {
@@ -2640,7 +2648,7 @@ openerp.web.form.FieldBinary = openerp.web.form.Field.extend({
},
on_save_as: function() {
if (!this.view.datarecord.id) {
this.notification.warn("Can't save file", "The record has not yet been saved");
this.do_warn("Can't save file", "The record has not yet been saved");
} else {
var url = '/web/binary/saveas?session_id=' + this.session.session_id + '&model=' +
this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name +
@@ -194,7 +194,7 @@ openerp.web.list_editable = function (openerp) {
}
self.edition = true;
self.edition_id = record_id;
self.edition_form = _.extend(new openerp.web.ListEditableFormView(self, self.dataset, false), {
self.edition_form = _.extend(new openerp.web.ListEditableFormView(self.view, self.dataset, false), {
form_template: 'ListView.row.form',
registry: openerp.web.list.form.widgets,
$element: $new_row
+3 -3
View File
@@ -123,8 +123,8 @@ db.web.ActionManager = db.web.Widget.extend({
}
if (this.dialog && action.context) {
var model = action.context.active_model;
if (model === 'base.module.upgrade' || model === 'base.setup.installer') {
db.webclient.menu.reload();
if (model === 'base.module.upgrade' || model === 'base.setup.installer' || model === 'base.module.upgrade') {
db.webclient.do_reload();
}
}
this.dialog_stop();
@@ -903,7 +903,7 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
var view_editor = new db.web.ViewEditor(this, this.$element, this.dataset, this.fields_view.arch);
view_editor.start();
} else {
this.notification.warn("Manage Views", "Could not find current view declaration");
this.do_warn("Manage Views", "Could not find current view declaration");
}
},
on_sidebar_edit_workflow: function() {
+5 -3
View File
@@ -2,9 +2,8 @@
<!-- vim:fdl=1:
-->
<templates id="template" xml:space="preserve">
<t t-name="Interface">
<div id="oe_loading" class="loading"></div>
<div id="oe_notification" class="oe_notification">
<t t-name="Notification">
<div class="oe_notification">
<div id="oe_notification_default">
<a class="ui-notify-cross ui-notify-close" href="#">x</a>
<h1>#{title}</h1>
@@ -17,6 +16,9 @@
<p>#{text}</p>
</div>
</div>
</t>
<t t-name="Interface">
<div id="oe_loading" class="loading"></div>
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" class="main_table">
<tr>
<td colspan="2" valign="top">
@@ -3,6 +3,7 @@
*---------------------------------------------------------*/
openerp.web_calendar = function(openerp) {
var _t = openerp.web._t;
var QWeb = openerp.web.qweb;
QWeb.add_template('/web_calendar/static/src/xml/web_calendar.xml');
openerp.web.views.add('calendar', 'openerp.web_calendar.CalendarView');
@@ -485,9 +485,8 @@ openerp.web_dashboard.ApplicationTiles = openerp.web.View.extend({
var self = this;
new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) {
$.unblockUI();
self.do_action(action, function () {
// TODO: less brutal reloading
window.location.reload(true);
self.widget_parent.widget_parent.do_action(action, function () {
openerp.webclient.do_reload();
});
});
}