[MERGE] Merge with trunk
bzr revid: fme@openerp.com-20110727114430-kzyiq9avv2kur1zm
This commit is contained in:
@@ -775,6 +775,25 @@ class SearchView(View):
|
||||
filter["context"] = req.session.eval_context(self.parse_context(filter["context"], req.session))
|
||||
filter["domain"] = req.session.eval_domain(self.parse_domain(filter["domain"], req.session))
|
||||
return filters
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def save_filter(self, req, model, name, context_to_save, domain):
|
||||
Model = req.session.model("ir.filters")
|
||||
ctx = openerpweb.nonliterals.CompoundContext(context_to_save)
|
||||
ctx.session = req.session
|
||||
ctx = ctx.evaluate()
|
||||
domain = openerpweb.nonliterals.CompoundDomain(domain)
|
||||
domain.session = req.session
|
||||
domain = domain.evaluate()
|
||||
uid = req.session._uid
|
||||
context = req.session.eval_context(req.context)
|
||||
to_return = Model.create_or_replace({"context": ctx,
|
||||
"domain": domain,
|
||||
"model_id": model,
|
||||
"name": name,
|
||||
"user_id": uid
|
||||
}, context)
|
||||
return to_return
|
||||
|
||||
class Binary(openerpweb.Controller):
|
||||
_cp_path = "/base/binary"
|
||||
|
||||
@@ -1020,6 +1020,10 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
|
||||
.openerp .closed-sidebar .toggle-sidebar {
|
||||
border-left: none;
|
||||
}
|
||||
.openerp li.oe_sidebar_print {
|
||||
padding-left: 20px;
|
||||
background: 1px 3px url(../img/icons/gtk-print.png) no-repeat;
|
||||
}
|
||||
|
||||
.openerp.kitten-mode-activated .main_table {
|
||||
background: url(http://placekitten.com/g/1500/800) repeat;
|
||||
|
||||
@@ -246,7 +246,7 @@ openerp.base.Session = openerp.base.Controller.extend( /** @lends openerp.base.S
|
||||
* @param port
|
||||
*/
|
||||
init: function(parent, element_id, server, port) {
|
||||
this._super(element_id);
|
||||
this._super(parent, element_id);
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
@@ -425,7 +425,7 @@ openerp.base.Session = openerp.base.Controller.extend( /** @lends openerp.base.S
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return decodeURIComponent(cookie.substring(nameEQ.length));
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -441,7 +441,7 @@ openerp.base.Session = openerp.base.Controller.extend( /** @lends openerp.base.S
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(value),
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
@@ -532,6 +532,7 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
dialog_title: "",
|
||||
identifier_prefix: 'dialog',
|
||||
init: function (parent, options) {
|
||||
var self = this;
|
||||
this._super(parent);
|
||||
this.options = {
|
||||
modal: true,
|
||||
@@ -542,7 +543,10 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
min_height: 0,
|
||||
max_height: '100%',
|
||||
autoOpen: false,
|
||||
buttons: {}
|
||||
buttons: {},
|
||||
close: function () {
|
||||
self.stop();
|
||||
}
|
||||
};
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
@@ -605,11 +609,7 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
this.set_options(options);
|
||||
this.$dialog.dialog(this.options).dialog('open');
|
||||
},
|
||||
close: function(options) {
|
||||
this.$dialog.dialog('close');
|
||||
},
|
||||
stop: function () {
|
||||
this.close();
|
||||
this.$dialog.dialog('destroy');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -492,24 +492,33 @@ openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
||||
this.to_create.push(cached);
|
||||
this.cache.push(cached);
|
||||
var to_return = $.Deferred().then(callback);
|
||||
setTimeout(function() {to_return.resolve({result: cached.id});}, 0);
|
||||
to_return.resolve({result: cached.id});
|
||||
return to_return.promise();
|
||||
},
|
||||
write: function (id, data, 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 (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;});
|
||||
$.extend(cached.values, record.values);
|
||||
this.on_change();
|
||||
if (dirty)
|
||||
this.on_change();
|
||||
var to_return = $.Deferred().then(callback);
|
||||
setTimeout(function () {to_return.resolve({result: true});}, 0);
|
||||
to_return.resolve({result: true});
|
||||
return to_return.promise();
|
||||
},
|
||||
unlink: function(ids, callback, error_callback) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openerp.base.form = function (openerp) {
|
||||
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{
|
||||
openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{
|
||||
/**
|
||||
* Indicates that this view is not searchable, and thus that no search
|
||||
* view should be displayed (if there is one active).
|
||||
@@ -19,6 +19,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
@@ -30,8 +31,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.datarecord = {};
|
||||
this.ready = false;
|
||||
this.show_invalid = true;
|
||||
this.touched = false;
|
||||
this.flags = this.view_manager.flags || {};
|
||||
this.dirty = false;
|
||||
this.default_focus_field = null;
|
||||
this.default_focus_button = null;
|
||||
this.registry = openerp.base.form.widgets;
|
||||
@@ -53,10 +53,14 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
context.add(this.view_manager.action.context);
|
||||
}
|
||||
return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id,
|
||||
toolbar:!!this.flags.sidebar, context: context}, this.on_loaded);
|
||||
toolbar: this.options.sidebar, context: context}, this.on_loaded);
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.stop();
|
||||
this.sidebar.stop();
|
||||
}
|
||||
_.each(this.widgets, function(w) {
|
||||
w.stop();
|
||||
});
|
||||
@@ -85,12 +89,16 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
$('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
|
||||
});
|
||||
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id);
|
||||
this.sidebar.start();
|
||||
this.sidebar.attachments = new openerp.base.form.SidebarAttachments(this.sidebar, this.sidebar.add_section("Attachments"), this);
|
||||
this.sidebar.add_toolbar(data.fields_view.toolbar);
|
||||
this.sidebar.do_unfold();
|
||||
}
|
||||
this.has_been_loaded.resolve();
|
||||
},
|
||||
do_show: function () {
|
||||
var self = this;
|
||||
var promise;
|
||||
if (this.dataset.index === null) {
|
||||
// null index means we should start a new record
|
||||
@@ -98,13 +106,17 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
} else {
|
||||
promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
}
|
||||
self.$element.show();
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
this.$element.show();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.show();
|
||||
}
|
||||
return promise;
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
},
|
||||
on_record_loaded: function(record) {
|
||||
if (!record) {
|
||||
@@ -121,22 +133,22 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.$form_header.find('.oe_form_on_update').show();
|
||||
this.$form_header.find('button.oe_form_button_new').show();
|
||||
}
|
||||
this.touched = false;
|
||||
this.dirty = false;
|
||||
this.datarecord = record;
|
||||
for (var f in this.fields) {
|
||||
var field = this.fields[f];
|
||||
field.touched = false;
|
||||
field.dirty = false;
|
||||
field.set_value(this.datarecord[f] || false);
|
||||
field.validate();
|
||||
}
|
||||
if (!record.id) {
|
||||
// New record: Second pass in order to trigger the onchanges
|
||||
this.touched = true;
|
||||
this.dirty = true;
|
||||
this.show_invalid = false;
|
||||
for (var f in record) {
|
||||
var field = this.fields[f];
|
||||
if (field) {
|
||||
field.touched = true;
|
||||
field.dirty = true;
|
||||
this.do_onchange(field);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +156,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.on_form_changed();
|
||||
this.show_invalid = this.ready = true;
|
||||
this.do_update_pager(record.id == null);
|
||||
this.do_update_sidebar();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
}
|
||||
if (this.default_focus_field) {
|
||||
this.default_focus_field.focus();
|
||||
}
|
||||
@@ -253,7 +267,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
processed.push(field.name);
|
||||
if (field.get_value() != value) {
|
||||
field.set_value(value);
|
||||
field.touched = true;
|
||||
field.dirty = true;
|
||||
if (_.indexOf(processed, field.name) < 0) {
|
||||
this.do_onchange(field, processed);
|
||||
}
|
||||
@@ -301,37 +315,40 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
if (!this.ready) {
|
||||
return false;
|
||||
}
|
||||
var invalid = false,
|
||||
var form_dirty = false,
|
||||
form_invalid = false,
|
||||
values = {},
|
||||
first_invalid_field = null;
|
||||
for (var f in this.fields) {
|
||||
f = this.fields[f];
|
||||
if (f.invalid) {
|
||||
invalid = true;
|
||||
if (!f.is_valid()) {
|
||||
form_invalid = true;
|
||||
f.update_dom();
|
||||
if (!first_invalid_field) {
|
||||
first_invalid_field = f;
|
||||
}
|
||||
} else if (f.touched) {
|
||||
} else if (f.is_dirty()) {
|
||||
form_dirty = true;
|
||||
values[f.name] = f.get_value();
|
||||
}
|
||||
}
|
||||
if (invalid) {
|
||||
if (form_invalid) {
|
||||
first_invalid_field.focus();
|
||||
this.on_invalid();
|
||||
return false;
|
||||
} else {
|
||||
} else if (form_dirty) {
|
||||
this.log("About to save", values);
|
||||
if (!this.datarecord.id) {
|
||||
this.dataset.create(values, function(r) {
|
||||
return this.dataset.create(values, function(r) {
|
||||
self.on_created(r, success, prepend_on_create);
|
||||
});
|
||||
} else {
|
||||
this.dataset.write(this.datarecord.id, values, function(r) {
|
||||
return this.dataset.write(this.datarecord.id, values, function(r) {
|
||||
self.on_saved(r, success);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
do_save_edit: function() {
|
||||
@@ -345,7 +362,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
on_invalid: function() {
|
||||
var msg = "<ul>";
|
||||
_.each(this.fields, function(f) {
|
||||
if (f.invalid) {
|
||||
if (!f.is_valid()) {
|
||||
msg += "<li>" + f.string + "</li>";
|
||||
}
|
||||
});
|
||||
@@ -389,7 +406,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.dataset.index = 0;
|
||||
}
|
||||
this.do_update_pager();
|
||||
this.do_update_sidebar();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
}
|
||||
this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id);
|
||||
if (success) {
|
||||
success(_.extend(r, {created: true}));
|
||||
@@ -406,51 +425,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
do_cancel: function () {
|
||||
this.notification.notify("Cancelling form");
|
||||
},
|
||||
do_update_sidebar: function() {
|
||||
if (this.flags.sidebar === false || this.view_manager.sidebar === undefined) {
|
||||
return;
|
||||
}
|
||||
if (!this.datarecord.id) {
|
||||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.dataset.get_context(),
|
||||
[['res_model', '=', this.dataset.model],
|
||||
['res_id', '=', this.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
this.$sidebar = this.view_manager.sidebar.$element.find('.sidebar-attachments');
|
||||
this.attachments = attachments;
|
||||
this.$sidebar.html(QWeb.render('FormView.sidebar.attachments', this));
|
||||
this.$sidebar.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete);
|
||||
this.$sidebar.find('.oe-binary-file').change(this.on_attachment_changed);
|
||||
},
|
||||
on_attachment_changed: function(e) {
|
||||
window[this.element_id + '_iframe'] = this.do_update_sidebar;
|
||||
var $e = $(e.target);
|
||||
if ($e.val() != '') {
|
||||
this.$sidebar.find('form.oe-binary-form').submit();
|
||||
$e.parent().find('input[type=file]').attr('disabled', 'true');
|
||||
$e.parent().find('button').attr('disabled', 'true').find('img, span').toggle();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
var self = this, $e = $(e.currentTarget);
|
||||
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
|
||||
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
|
||||
this.rpc('/base/dataset/unlink', {
|
||||
model: 'ir.attachment',
|
||||
ids: [parseInt($e.attr('data-id'))]
|
||||
}, function(r) {
|
||||
$e.parent().remove();
|
||||
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
|
||||
});
|
||||
}
|
||||
},
|
||||
reload: function() {
|
||||
if (this.datarecord.id) {
|
||||
this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
@@ -471,6 +445,54 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
/** @namespace */
|
||||
openerp.base.form = {};
|
||||
|
||||
openerp.base.form.SidebarAttachments = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id, form_view) {
|
||||
this._super(parent, element_id);
|
||||
this.view = form_view;
|
||||
},
|
||||
do_update: function() {
|
||||
if (!this.view.datarecord.id) {
|
||||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
this.attachments = attachments;
|
||||
this.$element.html(QWeb.render('FormView.sidebar.attachments', this));
|
||||
this.$element.find('.oe-binary-file').change(this.on_attachment_changed);
|
||||
this.$element.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete);
|
||||
},
|
||||
on_attachment_changed: function(e) {
|
||||
window[this.element_id + '_iframe'] = this.do_update;
|
||||
var $e = $(e.target);
|
||||
if ($e.val() != '') {
|
||||
this.$element.find('form.oe-binary-form').submit();
|
||||
$e.parent().find('input[type=file]').attr('disabled', 'true');
|
||||
$e.parent().find('button').attr('disabled', 'true').find('img, span').toggle();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
var self = this, $e = $(e.currentTarget);
|
||||
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
|
||||
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
|
||||
this.rpc('/base/dataset/unlink', {
|
||||
model: 'ir.attachment',
|
||||
ids: [parseInt($e.attr('data-id'))]
|
||||
}, function(r) {
|
||||
$e.parent().remove();
|
||||
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.compute_domain = function(expr, fields) {
|
||||
var stack = [];
|
||||
for (var i = expr.length - 1; i >= 0; i--) {
|
||||
@@ -707,7 +729,7 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
||||
},
|
||||
on_click: function(saved) {
|
||||
var self = this;
|
||||
if (!this.node.attrs.special && this.view.touched && saved !== true) {
|
||||
if (!this.node.attrs.special && this.view.dirty && saved !== true) {
|
||||
this.view.do_save(function() {
|
||||
self.on_click(true);
|
||||
});
|
||||
@@ -787,7 +809,7 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
this.readonly = this.modifiers['readonly'] === true;
|
||||
this.required = this.modifiers['required'] === true;
|
||||
this.invalid = false;
|
||||
this.touched = false;
|
||||
this.dirty = false;
|
||||
},
|
||||
set_value: function(value) {
|
||||
this.value = value;
|
||||
@@ -800,6 +822,12 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
get_value: function() {
|
||||
return this.value;
|
||||
},
|
||||
is_valid: function() {
|
||||
return !this.invalid;
|
||||
},
|
||||
is_dirty: function() {
|
||||
return this.dirty;
|
||||
},
|
||||
get_on_change_value: function() {
|
||||
return this.get_value();
|
||||
},
|
||||
@@ -808,13 +836,13 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
this.$element.toggleClass('disabled', this.readonly);
|
||||
this.$element.toggleClass('required', this.required);
|
||||
if (this.view.show_invalid) {
|
||||
this.$element.toggleClass('invalid', this.invalid);
|
||||
this.$element.toggleClass('invalid', !this.is_valid());
|
||||
}
|
||||
},
|
||||
on_ui_change: function() {
|
||||
this.touched = this.view.touched = true;
|
||||
this.dirty = this.view.dirty = true;
|
||||
this.validate();
|
||||
if (!this.invalid) {
|
||||
if (this.is_valid()) {
|
||||
this.set_value_from_ui();
|
||||
this.view.do_onchange(this);
|
||||
this.view.on_form_changed();
|
||||
@@ -912,7 +940,7 @@ openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({
|
||||
this.$element.find('button').click(this.on_button_clicked);
|
||||
},
|
||||
on_button_clicked: function() {
|
||||
if (!this.value || this.invalid) {
|
||||
if (!this.value || !this.is_valid()) {
|
||||
this.notification.warn("E-mail error", "Can't send email to invalid e-mail address");
|
||||
} else {
|
||||
location.href = 'mailto:' + this.value;
|
||||
@@ -953,7 +981,7 @@ openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({
|
||||
if (value === false || value === undefined) {
|
||||
// As in GTK client, floats default to 0
|
||||
value = 0;
|
||||
this.touched = true;
|
||||
this.dirty = true;
|
||||
}
|
||||
var show_value = value.toFixed(2);
|
||||
this.$element.find('input').val(show_value);
|
||||
@@ -973,7 +1001,7 @@ openerp.base.form.FieldInteger = openerp.base.form.FieldFloat.extend({
|
||||
if (value === false || value === undefined) {
|
||||
// TODO fme: check if GTK client default integers to 0 (like it does with floats)
|
||||
value = 0;
|
||||
this.touched = true;
|
||||
this.dirty = true;
|
||||
}
|
||||
var show_value = parseInt(value, 10);
|
||||
this.$element.find('input').val(show_value);
|
||||
@@ -1060,7 +1088,7 @@ openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({
|
||||
if (value === false || value === undefined) {
|
||||
// As in GTK client, floats default to 0
|
||||
value = 0;
|
||||
this.touched = true;
|
||||
this.dirty = true;
|
||||
}
|
||||
var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60));
|
||||
this.$element.find('input').val(show_value);
|
||||
@@ -1267,7 +1295,6 @@ openerp.base.form.dialog = function(content, options) {
|
||||
options.autoOpen = true;
|
||||
var dialog = new openerp.base.Dialog(null, options);
|
||||
dialog.$dialog = $(content).dialog(dialog.options);
|
||||
console.log(dialog.options)
|
||||
return dialog.$dialog;
|
||||
}
|
||||
|
||||
@@ -1612,6 +1639,9 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
controller.on_record_loaded.add_last(function() {
|
||||
once.resolve();
|
||||
});
|
||||
controller.on_form_changed.add_last(function() {
|
||||
self.save_form_view();
|
||||
});
|
||||
}
|
||||
self.is_started.resolve();
|
||||
});
|
||||
@@ -1692,6 +1722,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
var self = this;
|
||||
if (!this.dataset)
|
||||
return [];
|
||||
this.save_form_view();
|
||||
var val = this.dataset.delete_all ? [commands.delete_all()] : [];
|
||||
val = val.concat(_.map(this.dataset.ids, function(id) {
|
||||
var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;});
|
||||
@@ -1708,9 +1739,38 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
this.dataset.to_delete, function(x) {
|
||||
return commands['delete'](x.id);}));
|
||||
},
|
||||
save_form_view: function() {
|
||||
if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view &&
|
||||
this.viewmanager.views[this.viewmanager.active_view] &&
|
||||
this.viewmanager.views[this.viewmanager.active_view].controller) {
|
||||
var view = this.viewmanager.views[this.viewmanager.active_view].controller;
|
||||
if (this.viewmanager.active_view === "form") {
|
||||
var res = view.do_save();
|
||||
if (res === false) {
|
||||
// ignore
|
||||
} else if (res.isRejected()) {
|
||||
throw "Save or create on one2many dataset is not supposed to fail.";
|
||||
} else if (!res.isResolved()) {
|
||||
throw "Asynchronous get_value() is not supported in form view.";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
// TODO niv
|
||||
var self = this;
|
||||
var view = self.viewmanager.views[self.viewmanager.active_view].controller;
|
||||
if(self.viewmanager.active_view === "list") {
|
||||
return;
|
||||
} else if (self.viewmanager.active_view === "form") {
|
||||
for (var f in view.fields) {
|
||||
f = view.fields[f];
|
||||
if (!f.is_valid()) {
|
||||
this.invalid = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -24,24 +24,37 @@ openerp.base.list = {
|
||||
].join('')
|
||||
}
|
||||
|
||||
var record = row_data[column.id];
|
||||
if (record.value === false) {
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
var value = row_data[column.id].value;
|
||||
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (column.widget || column.type) {
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return record.value[1];
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = column.digits ? column.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(record.value),
|
||||
Math.round((record.value % 1) * 60));
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
record.value, record.value);
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return record.value;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -89,6 +102,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
@@ -97,7 +111,6 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
this.columns = [];
|
||||
|
||||
this.options = _.extend({}, this.defaults, options || {});
|
||||
this.flags = this.view_manager.flags || {};
|
||||
|
||||
this.set_groups(new openerp.base.ListView.Groups(this));
|
||||
|
||||
@@ -254,9 +267,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
})
|
||||
.val(self._limit || 'NaN');
|
||||
});
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id);
|
||||
this.sidebar.start();
|
||||
this.sidebar.add_toolbar(data.fields_view.toolbar);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Configures the ListView pager based on the provided dataset's information
|
||||
@@ -348,16 +363,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
}
|
||||
var aggregation_func = column['group_operator'] || 'sum';
|
||||
|
||||
if (!column[aggregation_func]) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
field: column.id,
|
||||
type: column.type,
|
||||
return _.extend({}, column, {
|
||||
'function': aggregation_func,
|
||||
label: column[aggregation_func]
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -386,16 +395,20 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.show();
|
||||
}
|
||||
if (this.hidden) {
|
||||
this.$element.find('.oe-listview-content').append(
|
||||
this.groups.apoptosis().render());
|
||||
this.hidden = false;
|
||||
}
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
this.hidden = true;
|
||||
},
|
||||
/**
|
||||
@@ -415,7 +428,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
context: this.dataset.get_context(),
|
||||
toolbar: !!this.flags.sidebar
|
||||
toolbar: this.options.sidebar
|
||||
}, callback);
|
||||
}
|
||||
},
|
||||
@@ -477,6 +490,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
var self = this;
|
||||
return $.when(this.dataset.unlink(ids)).then(function () {
|
||||
self.groups.drop_records(ids);
|
||||
self.compute_aggregates();
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -505,11 +519,17 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
do_action: function (name, id, callback) {
|
||||
var action = _.detect(this.columns, function (field) {
|
||||
var self = this,
|
||||
action = _.detect(this.columns, function (field) {
|
||||
return field.name === name;
|
||||
});
|
||||
if (!action) { return; }
|
||||
this.execute_action(action, this.dataset, this.session.action_manager, id, callback);
|
||||
this.execute_action(
|
||||
action, this.dataset, this.session.action_manager, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Handles the activation of a record (clicking on it)
|
||||
@@ -556,7 +576,6 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
compute_aggregates: function (records) {
|
||||
var columns = _(this.aggregate_columns).filter(function (column) {
|
||||
return column['function']; });
|
||||
|
||||
if (_.isEmpty(columns)) { return; }
|
||||
|
||||
if (_.isEmpty(records)) {
|
||||
@@ -564,17 +583,39 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
}
|
||||
|
||||
var count = 0, sums = {};
|
||||
_(columns).each(function (column) { sums[column.field] = 0; });
|
||||
_(columns).each(function (column) {
|
||||
switch (column['function']) {
|
||||
case 'max':
|
||||
sums[column.id] = -Infinity;
|
||||
break;
|
||||
case 'min':
|
||||
sums[column.id] = Infinity;
|
||||
break;
|
||||
default:
|
||||
sums[column.id] = 0;
|
||||
}
|
||||
});
|
||||
_(records).each(function (record) {
|
||||
count += record.count || 1;
|
||||
_(columns).each(function (column) {
|
||||
var field = column.field;
|
||||
var field = column.id,
|
||||
value = record.values[field];
|
||||
switch (column['function']) {
|
||||
case 'sum':
|
||||
sums[field] += record.values[field];
|
||||
sums[field] += value;
|
||||
break;
|
||||
case 'avg':
|
||||
sums[field] += record.count * record.values[field];
|
||||
sums[field] += record.count * value;
|
||||
break;
|
||||
case 'min':
|
||||
if (sums[field] > value) {
|
||||
sums[field] = value;
|
||||
}
|
||||
break;
|
||||
case 'max':
|
||||
if (sums[field] < value) {
|
||||
sums[field] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -582,14 +623,13 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
|
||||
var aggregates = {};
|
||||
_(columns).each(function (column) {
|
||||
var field = column.field;
|
||||
var field = column.id;
|
||||
switch (column['function']) {
|
||||
case 'sum':
|
||||
aggregates[field] = sums[field];
|
||||
break;
|
||||
case 'avg':
|
||||
aggregates[field] = sums[field] / count;
|
||||
aggregates[field] = {value: sums[field] / count};
|
||||
break;
|
||||
default:
|
||||
aggregates[field] = {value: sums[field]};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -601,9 +641,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
if (!column['function']) {
|
||||
return;
|
||||
}
|
||||
var pattern = (column.type == 'integer') ? '%d' : '%.2f';
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.field))
|
||||
.text(_.sprintf(pattern, aggregation[column.field]));
|
||||
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
|
||||
.html(openerp.base.list.render_cell(aggregation, column));
|
||||
});
|
||||
}
|
||||
// TODO: implement reorder (drag and drop rows)
|
||||
@@ -668,7 +708,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
index = self.row_position($row);
|
||||
|
||||
$(self).trigger('action', [field, record_id, function () {
|
||||
self.reload_record(index, true);
|
||||
return self.reload_record(index, true);
|
||||
}]);
|
||||
})
|
||||
.delegate('tr', 'click', function (e) {
|
||||
@@ -806,7 +846,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
|
||||
return $.when(read_p).then(function () {
|
||||
self.$current.children().eq(record_index)
|
||||
.replaceWith(self.render_record(record_index)); })
|
||||
.replaceWith(self.render_record(record_index)); });
|
||||
},
|
||||
/**
|
||||
* Renders a list record to HTML
|
||||
@@ -981,8 +1021,8 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
row_data[group.grouped_on] = group;
|
||||
var group_column = _(self.columns).detect(function (column) {
|
||||
return column.id === group.grouped_on; });
|
||||
$group_column.text(openerp.base.list.render_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
$group_column.html(openerp.base.list.render_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
));
|
||||
if (group.openable) {
|
||||
// Make openable if not terminal group & group_by_no_leaf
|
||||
|
||||
@@ -110,9 +110,10 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
}
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
var lines = this.make_widgets(
|
||||
data.fields_view['arch'].children,
|
||||
data.fields_view.fields);
|
||||
var self = this,
|
||||
lines = this.make_widgets(
|
||||
data.fields_view['arch'].children,
|
||||
data.fields_view.fields);
|
||||
|
||||
// for extended search view
|
||||
var ext = new openerp.base.search.ExtendedSearch(this, this.model);
|
||||
@@ -144,7 +145,9 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
self.ready.resolve();
|
||||
});
|
||||
|
||||
// filters management
|
||||
this.reload_managed_filters();
|
||||
},
|
||||
reload_managed_filters: function() {
|
||||
var self = this;
|
||||
return this.rpc('/base/searchview/get_filters', {
|
||||
model: this.dataset.model
|
||||
@@ -159,6 +162,7 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
* Handle event when the user make a selection in the filters management select box.
|
||||
*/
|
||||
on_filters_management: function(e) {
|
||||
var self = this;
|
||||
var select = this.$element.find(".oe_search-view-filters-management");
|
||||
var val = select.val();
|
||||
|
||||
@@ -173,10 +177,50 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
this.on_search([filter.domain], [filter.context], []);
|
||||
} else if (val == "save_filter") {
|
||||
select.val("_filters");
|
||||
//TODO niv
|
||||
var data = this.build_search_data();
|
||||
var context = new openerp.base.CompoundContext();
|
||||
_.each(data.contexts, function(x) {
|
||||
context.add(x);
|
||||
});
|
||||
var domain = new openerp.base.CompoundDomain();
|
||||
_.each(data.domains, function(x) {
|
||||
domain.add(x);
|
||||
});
|
||||
var dial_html = QWeb.render("SearchView.managed-filters.add");
|
||||
var $dial = $(dial_html);
|
||||
$dial.dialog({
|
||||
modal: true,
|
||||
title: "Filter Entry",
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("close");
|
||||
},
|
||||
OK: function() {
|
||||
$(this).dialog("close");
|
||||
var name = $(this).find("input").val();
|
||||
self.rpc('/base/searchview/save_filter', {
|
||||
model: self.dataset.model,
|
||||
context_to_save: context,
|
||||
domain: domain,
|
||||
name: name
|
||||
}).then(function(result) {
|
||||
self.reload_managed_filters();
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
} else { // manage_filters
|
||||
select.val("_filters");
|
||||
//TODO niv
|
||||
this.do_action({
|
||||
res_model: 'ir.filters',
|
||||
views: [[false, 'list'], [false, 'form']],
|
||||
type: 'ir.actions.act_window',
|
||||
context: {"search_default_user_id": this.session.uid,
|
||||
"search_default_model_id": this.dataset.model},
|
||||
target: "current",
|
||||
limit : 80,
|
||||
auto_search : true
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -197,6 +241,16 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
|
||||
if (e && e.preventDefault) { e.preventDefault(); }
|
||||
|
||||
var data = this.build_search_data();
|
||||
|
||||
if (data.errors.length) {
|
||||
this.on_invalid(data.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
this.on_search(data.domains, data.contexts, data.groupbys);
|
||||
},
|
||||
build_search_data: function() {
|
||||
var domains = [],
|
||||
contexts = [],
|
||||
errors = [];
|
||||
@@ -221,19 +275,13 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
this.on_invalid(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: do we need to handle *fields* with group_by in their context?
|
||||
var groupbys = _(this.enabled_filters)
|
||||
.chain()
|
||||
.map(function (filter) { return filter.get_context();})
|
||||
.compact()
|
||||
.value();
|
||||
|
||||
this.on_search(domains, contexts, groupbys);
|
||||
return {domains: domains, contexts: contexts, errors: errors, groupbys: groupbys};
|
||||
},
|
||||
/**
|
||||
* Triggered after the SearchView has collected all relevant domains and
|
||||
|
||||
@@ -61,6 +61,9 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
var url = window.location.protocol + "//" + window.location.host +
|
||||
window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url);
|
||||
if (on_closed) {
|
||||
on_closed();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (this.viewmanager) {
|
||||
@@ -117,7 +120,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
this.views = {};
|
||||
this.flags = this.flags || {};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
this.registry = openerp.base.views;
|
||||
},
|
||||
/**
|
||||
@@ -131,7 +133,12 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
_.each(this.views_src, function(view) {
|
||||
self.views[view.view_type] = $.extend({}, view, {controller: null});
|
||||
self.views[view.view_type] = $.extend({}, view, {
|
||||
controller : null,
|
||||
options : _.extend({
|
||||
sidebar_id : self.element_id + '_sidebar_' + view.view_type
|
||||
}, self.flags)
|
||||
});
|
||||
});
|
||||
if (this.flags.views_switcher === false) {
|
||||
this.$element.find('.oe_vm_switch').hide();
|
||||
@@ -155,7 +162,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
if (!view.controller) {
|
||||
// Lazy loading of views
|
||||
var controllerclass = this.registry.get_object(view_type);
|
||||
var controller = new controllerclass( this, this.element_id + "_view_" + view_type,
|
||||
var controller = new controllerclass(this, this.element_id + '_view_' + view_type,
|
||||
this.dataset, view.view_id, view.options);
|
||||
if (view.embedded_view) {
|
||||
controller.set_embedded_view(view.embedded_view);
|
||||
@@ -285,7 +292,6 @@ openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.b
|
||||
if(parent)
|
||||
this.session = parent.session;
|
||||
this.action = {flags: {}};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -310,19 +316,10 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
// Not elegant but allows to avoid flickering of SearchView#do_hide
|
||||
this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false;
|
||||
}
|
||||
if (this.flags.sidebar) {
|
||||
this.sidebar = new openerp.base.Sidebar(null, this);
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
var inital_view_loaded = this._super();
|
||||
|
||||
// init sidebar
|
||||
if (this.flags.sidebar) {
|
||||
this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render());
|
||||
this.sidebar.start();
|
||||
}
|
||||
|
||||
var search_defaults = {};
|
||||
_.each(this.action.context, function (value, key) {
|
||||
var match = /^search_default_(.*)$/.exec(key);
|
||||
@@ -347,7 +344,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
},
|
||||
stop: function() {
|
||||
// should be replaced by automatic destruction implemented in BaseWidget
|
||||
this.sidebar.stop();
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
@@ -374,83 +370,97 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
||||
template: "ViewManager.sidebar",
|
||||
init: function(parent, view_manager) {
|
||||
this._super(parent, view_manager.session);
|
||||
this.view_manager = view_manager;
|
||||
this.sections = [];
|
||||
},
|
||||
set_toolbar: function(toolbar) {
|
||||
this.sections = [];
|
||||
var self = this;
|
||||
_.each([["print", "Reports"], ["action", "Actions"], ["relate", "Links"]], function(type) {
|
||||
if (toolbar[type[0]].length == 0)
|
||||
return;
|
||||
var section = {elements:toolbar[type[0]], label:type[1]};
|
||||
self.sections.push(section);
|
||||
});
|
||||
this.do_refresh(true);
|
||||
},
|
||||
do_refresh: function(new_view) {
|
||||
var view = this.view_manager.active_view;
|
||||
var the_condition = this.sections.length > 0 && _.detect(this.sections,
|
||||
function(x) {return x.elements.length > 0;}) != undefined
|
||||
&& (!new_view || view != 'list');
|
||||
|
||||
this.$element.toggleClass('open-sidebar', the_condition)
|
||||
.toggleClass('closed-sidebar', !the_condition);
|
||||
|
||||
this.$element.html(QWeb.render("ViewManager.sidebar.internal", { sidebar: this, view: view }));
|
||||
|
||||
var self = this;
|
||||
this.$element.find(".toggle-sidebar").click(function(e) {
|
||||
self.$element.toggleClass('open-sidebar closed-sidebar');
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
this.$element.find("a.oe_sidebar_action_a").click(function(e) {
|
||||
var $this = jQuery(this);
|
||||
var index = $this.attr("data-index").split('-');
|
||||
var action = self.sections[index[0]].elements[index[1]];
|
||||
action.flags = {
|
||||
new_window : true
|
||||
};
|
||||
self.session.action_manager.do_action(action);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
openerp.base.Sidebar = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.items = {};
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.do_refresh(false);
|
||||
var self = this;
|
||||
this._super(this, arguments);
|
||||
this.$element.html(QWeb.render('Sidebar'));
|
||||
this.$element.find(".toggle-sidebar").click(function(e) {
|
||||
self.do_toggle();
|
||||
});
|
||||
},
|
||||
add_toolbar: function(toolbar) {
|
||||
var self = this;
|
||||
_.each([['print', "Reports"], ['action', "Actions"], ['relate', "Links"]], function(type) {
|
||||
var items = toolbar[type[0]];
|
||||
if (items.length) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i] = {
|
||||
label: items[i]['name'],
|
||||
action: items[i],
|
||||
classname: 'oe_sidebar_' + type[0]
|
||||
}
|
||||
}
|
||||
self.add_section(type[1], items);
|
||||
}
|
||||
});
|
||||
},
|
||||
add_section: function(name, items) {
|
||||
// For each section, we pass a name/label and optionally an array of items.
|
||||
// If no items are passed, then the section will be created as a custom section
|
||||
// returning back an element_id to be used by a custom controller.
|
||||
// Else, the section is a standard section with items displayed as links.
|
||||
// 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: optionnal dom class name for the line,
|
||||
// }
|
||||
// Note: The item should have one action or/and a callback
|
||||
var self = this,
|
||||
section_id = _.uniqueId(this.element_id + '_section_');
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i].element_id = _.uniqueId(section_id + '_item_');
|
||||
this.items[items[i].element_id] = items[i];
|
||||
}
|
||||
}
|
||||
var $section = $(QWeb.render("Sidebar.section", {
|
||||
section_id: section_id,
|
||||
name: name,
|
||||
items: items
|
||||
}));
|
||||
if (items) {
|
||||
$section.find('a.oe_sidebar_action_a').click(function() {
|
||||
var item = self.items[$(this).attr('id')];
|
||||
if (item.callback) {
|
||||
item.callback();
|
||||
}
|
||||
if (item.action) {
|
||||
item.action.flags = item.action.flags || {};
|
||||
item.action.flags.new_window = true;
|
||||
self.do_action(item.action);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
$section.appendTo(this.$element.find('div.sidebar-actions'));
|
||||
return section_id;
|
||||
},
|
||||
do_fold: function() {
|
||||
this.$element.addClass('closed-sidebar').removeClass('open-sidebar');
|
||||
},
|
||||
do_unfold: function() {
|
||||
this.$element.addClass('open-sidebar').removeClass('closed-sidebar');
|
||||
},
|
||||
do_toggle: function() {
|
||||
this.$element.toggleClass('open-sidebar closed-sidebar');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar);
|
||||
|
||||
/*
|
||||
openerp.base.Export = openerp.base.Dialog.extend({
|
||||
dialog_title: "Export",
|
||||
template: 'ExportDialog',
|
||||
identifier_prefix: 'export_dialog',
|
||||
init: function (session, model, domain) {
|
||||
this._super();
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.html(this.render());
|
||||
},
|
||||
on_button_Export: function() {
|
||||
console.log("Export")
|
||||
},
|
||||
on_button_Cancel: function() {
|
||||
this.$element.dialog("close");
|
||||
}
|
||||
});
|
||||
*/
|
||||
openerp.base.View = openerp.base.Controller.extend({
|
||||
set_default_options: function(options) {
|
||||
this.options = options || {};
|
||||
_.defaults(this.options, {
|
||||
// All possible views options should be defaulted here
|
||||
sidebar_id: null,
|
||||
sidebar: true
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Fetches and executes the action identified by ``action_data``.
|
||||
*
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<td><label for="db">Database:</label></td>
|
||||
<td>
|
||||
<t t-if="!db_list">
|
||||
<input type="text" name="db" value="" autofocus="true"/>
|
||||
<input type="text" name="db" t-att-value="selected_db || ''" autofocus="true"/>
|
||||
</t>
|
||||
<t t-if="db_list">
|
||||
<select name="db">
|
||||
@@ -232,18 +232,40 @@
|
||||
</t>
|
||||
</td>
|
||||
<td class="view-manager-main-sidebar" height="100%">
|
||||
<t t-foreach="views" t-as="view">
|
||||
<div t-attf-id="#{prefix}_sidebar_#{view.view_type}" class="sidebar-main-div closed-sidebar" style="display: none"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="Sidebar">
|
||||
<a class="toggle-sidebar"></a>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-actions">
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Sidebar.section">
|
||||
<h2><t t-esc="name"/></h2>
|
||||
<div t-att-id="section_id">
|
||||
<ul t-if="items">
|
||||
<li t-foreach="items" t-as="item" t-att-class="item.classname">
|
||||
<a class="oe_sidebar_action_a" t-att-id="item.element_id" href="#">
|
||||
<t t-esc="item.label"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
<table t-name="ListView" class="oe-listview-content">
|
||||
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
|
||||
<thead class="ui-widget-header">
|
||||
<tr t-if="flags.action_buttons !== false or flags.pager !== false">
|
||||
<tr t-if="options.action_buttons !== false or options.pager !== false">
|
||||
<th t-att-colspan="columns_count">
|
||||
<table>
|
||||
<tr>
|
||||
<td t-if="flags.action_buttons !== false" class="oe-actions">
|
||||
<td t-if="options.action_buttons !== false" class="oe-actions">
|
||||
<button type="button" class="oe-list-add"
|
||||
t-if="options.addable">
|
||||
<t t-esc="options.addable"/>
|
||||
@@ -253,7 +275,7 @@
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
<th t-if="flags.pager !== false" class="oe-list-pager">
|
||||
<th t-if="options.pager !== false" class="oe-list-pager">
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="first">First</button>
|
||||
<button type="button" disabled="disabled"
|
||||
@@ -293,7 +315,7 @@
|
||||
<tr>
|
||||
<td t-if="options.selectable"/>
|
||||
<td t-foreach="aggregate_columns" t-as="column" class="oe-list-footer oe-number"
|
||||
t-att-data-field="column.field" t-att-title="column.label">
|
||||
t-att-data-field="column.id" t-att-title="column.label">
|
||||
</td>
|
||||
<td t-if="options.deletable"/>
|
||||
</tr>
|
||||
@@ -335,7 +357,7 @@
|
||||
<t t-name="FormView">
|
||||
<div class="oe_form_header" t-att-id="view.element_id + '_header'">
|
||||
<h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/> <button class="oe_get_xml_view">xml</button></h2>
|
||||
<div class="oe_form_buttons" t-if="view.flags.action_buttons !== false">
|
||||
<div class="oe_form_buttons" t-if="view.options.action_buttons !== false">
|
||||
<!--<button type="button" class="oe_form_button_save">
|
||||
<span class="oe_form_on_update">Save</span>
|
||||
<span class="oe_form_on_create">Create</span>
|
||||
@@ -347,7 +369,7 @@
|
||||
<!--<button type="button" class="oe_form_button_cancel">Cancel</button>-->
|
||||
<button type="button" class="oe_form_button_new">New</button>
|
||||
</div>
|
||||
<div class="oe_form_pager" t-if="view.flags.pager !== false">
|
||||
<div class="oe_form_pager" t-if="view.options.pager !== false">
|
||||
<button type="button" data-pager-action="first">First</button>
|
||||
<button type="button" data-pager-action="previous"><<</button>
|
||||
|
||||
@@ -360,21 +382,20 @@
|
||||
<t t-raw="frame.render()"/>
|
||||
</t>
|
||||
<t t-name="FormView.sidebar.attachments">
|
||||
<h2>Attachments</h2>
|
||||
<div class="oe-sidebar-attachments-toolbar">
|
||||
<div class="oe-binary-file-set" style="float: right">
|
||||
<form class="oe-binary-form" t-attf-target="#{element_id}_iframe"
|
||||
method="post" enctype="multipart/form-data" action="/base/binary/upload_attachment">
|
||||
<input type="hidden" name="session_id" t-att-value="session.session_id"/>
|
||||
<input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/>
|
||||
<input type="hidden" name="model" t-att-value="dataset.model"/>
|
||||
<input type="hidden" name="id" t-att-value="datarecord.id"/>
|
||||
<input type="hidden" name="model" t-att-value="view.dataset.model"/>
|
||||
<input type="hidden" name="id" t-att-value="view.datarecord.id"/>
|
||||
<button class="button" type="button">
|
||||
<img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/>
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<input type="file" class="oe-binary-file" name="ufile" title="Add attachment"
|
||||
t-att-onclick="datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/>
|
||||
t-att-onclick="view.datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/>
|
||||
</form>
|
||||
<iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe>
|
||||
</div>
|
||||
@@ -384,7 +405,7 @@
|
||||
<li t-foreach="attachments" t-as="attachment">
|
||||
<t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/base/binary/saveas?session_id='
|
||||
+ session.session_id + '&model=ir.attachment&id=' + attachment.id
|
||||
+ '&field=datas' + '&fieldname=name' + '&t=' + (new Date().getTime())"/>
|
||||
+ '&field=datas&fieldname=name&t=' + (new Date().getTime())"/>
|
||||
<a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank">
|
||||
<t t-esc="attachment.name"/>
|
||||
</a>
|
||||
@@ -679,6 +700,13 @@
|
||||
<option value="save_filter">Save Filter</option>
|
||||
<option value="manage_filters">Manage Filters</option>
|
||||
</t>
|
||||
<t t-name="SearchView.managed-filters.add">
|
||||
<div>
|
||||
<p>Filter Name:</p>
|
||||
<input type="text"/>
|
||||
<p>(Any existing filter with the same name will be replaced)</p>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.render_lines">
|
||||
<table class="oe-searchview-render-line" border="0" cellspacing="0" cellpadding="0"
|
||||
t-foreach="lines" t-as="line">
|
||||
@@ -842,29 +870,6 @@
|
||||
</t>
|
||||
</select>
|
||||
</t>
|
||||
<t t-name="ViewManager.sidebar">
|
||||
<div t-att-id="element_id" class="sidebar-main-div closed-sidebar">
|
||||
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="ViewManager.sidebar.internal">
|
||||
<a class="toggle-sidebar"></a>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-attachments" t-if="view == 'form'"> </div>
|
||||
<div class="sidebar-actions">
|
||||
<t t-foreach="sidebar.sections" t-as="section" t-if="section.elements.length">
|
||||
<h2><t t-esc="section.label"/></h2>
|
||||
<ul>
|
||||
<li t-foreach="section.elements" t-as="element">
|
||||
<a class="oe_sidebar_action_a" t-attf-data-index="#{section_index}-#{element_index}" href="#">
|
||||
<t t-esc="element.name"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="DialogWarning">
|
||||
<table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning">
|
||||
<tr>
|
||||
|
||||
@@ -18,15 +18,6 @@ $(document).ready(function () {
|
||||
}
|
||||
}};
|
||||
|
||||
var fuck_that_shit = {
|
||||
action: {
|
||||
flags: {}
|
||||
},
|
||||
sidebar: {
|
||||
set_toolbar: function () {}
|
||||
}
|
||||
};
|
||||
|
||||
var openerp;
|
||||
module("ListView", {
|
||||
setup: function () {
|
||||
@@ -42,8 +33,7 @@ $(document).ready(function () {
|
||||
|
||||
test('render selection checkboxes', 2, function () {
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null,
|
||||
'qunit-fixture', {model: null, ids: [null, null, null], index: 0});
|
||||
null, 'qunit-fixture', {model: null, ids: [null, null, null], index: 0});
|
||||
|
||||
listview.on_loaded(fvg);
|
||||
|
||||
@@ -60,8 +50,7 @@ $(document).ready(function () {
|
||||
});
|
||||
test('render no checkbox if selectable=false', 1, function () {
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null,
|
||||
'qunit-fixture', {model: null, ids: [null, null, null], index: 0}, false,
|
||||
null, 'qunit-fixture', {model: null, ids: [null, null, null], index: 0}, false,
|
||||
{selectable: false});
|
||||
|
||||
listview.on_loaded(fvg);
|
||||
@@ -75,8 +64,7 @@ $(document).ready(function () {
|
||||
});
|
||||
test('select a bunch of records', 2, function () {
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null, 'qunit-fixture',
|
||||
{model: null, ids: [1, 2, 3], index: 0});
|
||||
null, 'qunit-fixture', {model: null, ids: [1, 2, 3], index: 0});
|
||||
listview.on_loaded(fvg);
|
||||
|
||||
listview.do_fill_table({records: [
|
||||
@@ -94,8 +82,7 @@ $(document).ready(function () {
|
||||
});
|
||||
test('render deletion button if list is deletable', 1, function () {
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null, 'qunit-fixture',
|
||||
{model: null, ids: [null, null, null], index: 0});
|
||||
null, 'qunit-fixture', {model: null, ids: [null, null, null], index: 0});
|
||||
|
||||
listview.on_loaded(fvg);
|
||||
|
||||
@@ -112,7 +99,7 @@ $(document).ready(function () {
|
||||
2, function () {
|
||||
var deleted;
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null, 'qunit-fixture',
|
||||
null, 'qunit-fixture',
|
||||
{model: null, unlink: function (ids) {
|
||||
deleted = ids;
|
||||
}, ids: [1, 2, 3], index: 0});
|
||||
@@ -132,7 +119,7 @@ $(document).ready(function () {
|
||||
test('multiple records deletion', 1, function () {
|
||||
var deleted;
|
||||
var listview = new openerp.base.ListView(
|
||||
fuck_that_shit, null, 'qunit-fixture',
|
||||
null, 'qunit-fixture',
|
||||
{model: null, unlink: function (ids) {
|
||||
deleted = ids;
|
||||
}, ids: [1, 2, 3], index: 0});
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
openerp.base_calendar = function(openerp) {
|
||||
QWeb.add_template('/base_calendar/static/src/xml/base_calendar.xml');
|
||||
openerp.base.views.add('calendar', 'openerp.base_calendar.CalendarView');
|
||||
openerp.base_calendar.CalendarView = openerp.base.Controller.extend({
|
||||
openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
// Dhtmlx scheduler ?
|
||||
init: function(view_manager, session, element_id, dataset, view_id){
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager;
|
||||
init: function(parent, element_id, dataset, view_id) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.dataset_index = 0;
|
||||
this.model = dataset.model;
|
||||
@@ -194,7 +194,9 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({
|
||||
// self.color_field
|
||||
console.log('Reload Scheduler>>>')
|
||||
},
|
||||
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
this.notification.notify("Searching caldendar");
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user