[MERGE]
bzr revid: nicolas.vanhoren@openerp.com-20110404142640-bgdhe7jcwdug4qq2
This commit is contained in:
commit
00188c2980
|
@ -88,6 +88,7 @@ class Session(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def login(self, req, db, login, password):
|
||||
req.session.login(db, login, password)
|
||||
|
||||
return {
|
||||
"session_id": req.session_id,
|
||||
"uid": req.session._uid,
|
||||
|
@ -187,8 +188,38 @@ def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
|||
action['domain'],
|
||||
req.session.evaluation_context(
|
||||
action['context'])) or []
|
||||
fix_view_modes(action)
|
||||
return actions
|
||||
|
||||
def fix_view_modes(action):
|
||||
""" For historical reasons, OpenERP has weird dealings in relation to
|
||||
view_mode and the view_type attribute (on window actions):
|
||||
|
||||
* one of the view modes is ``tree``, which stands for both list views
|
||||
and tree views
|
||||
* the choice is made by checking ``view_type``, which is either
|
||||
``form`` for a list view or ``tree`` for an actual tree view
|
||||
|
||||
This methods simply folds the view_type into view_mode by adding a
|
||||
new view mode ``list`` which is the result of the ``tree`` view_mode
|
||||
in conjunction with the ``form`` view_type.
|
||||
|
||||
TODO: this should go into the doc, some kind of "peculiarities" section
|
||||
|
||||
:param dict action: an action descriptor
|
||||
:returns: nothing, the action is modified in place
|
||||
"""
|
||||
if action.pop('view_type') != 'form':
|
||||
return
|
||||
|
||||
action['view_mode'] = ','.join(
|
||||
mode if mode != 'tree' else 'list'
|
||||
for mode in action['view_mode'].split(','))
|
||||
action['views'] = [
|
||||
[id, mode if mode != 'tree' else 'list']
|
||||
for id, mode in action['views']
|
||||
]
|
||||
|
||||
class Menu(openerpweb.Controller):
|
||||
_cp_path = "/base/menu"
|
||||
|
||||
|
@ -237,7 +268,6 @@ class Menu(openerpweb.Controller):
|
|||
|
||||
return {"action": actions}
|
||||
|
||||
|
||||
class DataSet(openerpweb.Controller):
|
||||
_cp_path = "/base/dataset"
|
||||
|
||||
|
@ -383,7 +413,7 @@ class View(openerpweb.Controller):
|
|||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
domain = elem.get(attr_name)
|
||||
domain = elem.get(attr_name, '').strip()
|
||||
if domain:
|
||||
try:
|
||||
elem.set(
|
||||
|
@ -408,7 +438,7 @@ class View(openerpweb.Controller):
|
|||
"""
|
||||
self.parse_domain(elem, 'domain', session)
|
||||
self.parse_domain(elem, 'filter_domain', session)
|
||||
context_string = elem.get('context')
|
||||
context_string = elem.get('context', '').strip()
|
||||
if context_string:
|
||||
try:
|
||||
elem.set('context',
|
||||
|
|
|
@ -395,6 +395,11 @@ body.openerp {
|
|||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* View Manager */
|
||||
.openerp .views-switchers {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Form */
|
||||
.openerp .required.error {
|
||||
border: 1px solid #900;
|
||||
|
@ -413,6 +418,13 @@ body.openerp {
|
|||
border-radius: 3px;
|
||||
background: white;
|
||||
}
|
||||
.openerp input.field_date {
|
||||
background: url('../img/ui/field_calendar.png') no-repeat right center;
|
||||
background-origin: content-box;
|
||||
-moz-background-origin: content;
|
||||
-moz-background-origin: content-box;
|
||||
-webkit-background-origin: content-box;
|
||||
}
|
||||
|
||||
/* Widgets */
|
||||
.openerp .separator {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 454 B |
|
@ -184,8 +184,19 @@ openerp.base.BasicController = Class.extend(
|
|||
* Controller start
|
||||
* event binding, rpc and callback calling required to initialize the
|
||||
* object can happen here
|
||||
*
|
||||
* Returns a promise object letting callers (subclasses and direct callers)
|
||||
* know when this component is done starting
|
||||
*
|
||||
* @returns {jQuery.Deferred}
|
||||
*/
|
||||
start: function() {
|
||||
// returns an already fulfilled promise. Maybe we could return nothing?
|
||||
// $.when can take non-deferred and in that case it simply considers
|
||||
// them all as fulfilled promises.
|
||||
// But in thise case we *have* to ensure callers use $.when and don't
|
||||
// try to call deferred methods on this return value.
|
||||
return $.Deferred().done().promise();
|
||||
},
|
||||
stop: function() {
|
||||
},
|
||||
|
@ -250,6 +261,19 @@ openerp.base.Session = openerp.base.BasicController.extend(
|
|||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
*
|
||||
* Registers a default error callback if none is provided, and handles
|
||||
* setting the correct session id and session context in the parameter
|
||||
* objects
|
||||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @param {Object} params call parameters
|
||||
* @param {Function} success_callback function to execute on RPC call success
|
||||
* @param {Function} error_callback function to execute on RPC call failure
|
||||
* @returns {jQuery.Deferred} jquery-provided ajax deferred
|
||||
*/
|
||||
rpc: function(url, params, success_callback, error_callback) {
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
|
@ -259,17 +283,22 @@ openerp.base.Session = openerp.base.BasicController.extend(
|
|||
error_callback = typeof(error_callback) != "undefined" ? error_callback : this.on_rpc_error;
|
||||
|
||||
// Call using the rpc_mode
|
||||
this.rpc_ajax(url, {
|
||||
return this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}, success_callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload, success_callback, error_callback) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
$.ajax({
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
|
@ -446,9 +475,18 @@ openerp.base.Controller = openerp.base.BasicController.extend(
|
|||
if(this.session)
|
||||
this.session.log.apply(this.session,arguments);
|
||||
},
|
||||
/**
|
||||
* Performs a JSON-RPC call
|
||||
*
|
||||
* @param {String} url endpoint url
|
||||
* @param {Object} data RPC parameters
|
||||
* @param {Function} success RPC call success callback
|
||||
* @param {Function} error RPC call error callback
|
||||
* @returns {jQuery.Deferred} deferred object for the RPC call
|
||||
*/
|
||||
rpc: function(url, data, success, error) {
|
||||
// TODO: support additional arguments ?
|
||||
this.session.rpc(url, data, success, error);
|
||||
return this.session.rpc(url, data, success, error);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
this._super(session);
|
||||
this.model = model;
|
||||
|
||||
this._fields = null;
|
||||
|
||||
this._ids = [];
|
||||
this._active_ids = null;
|
||||
this._active_id_index = 0;
|
||||
|
@ -43,12 +41,6 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
this._context = {};
|
||||
},
|
||||
start: function() {
|
||||
// TODO: fields_view_get fields selection?
|
||||
this.rpc("/base/dataset/fields", {"model":this.model}, this.on_fields);
|
||||
},
|
||||
on_fields: function(result) {
|
||||
this._fields = result.fields;
|
||||
this.on_ready();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -63,12 +55,11 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
* @param {Number} [limit=null] The maximum number of records to return
|
||||
* @returns itself
|
||||
*/
|
||||
fetch: function (offset, limit) {
|
||||
fetch: function (fields, offset, limit) {
|
||||
offset = offset || 0;
|
||||
limit = limit || null;
|
||||
this.rpc('/base/dataset/find', {
|
||||
model: this.model,
|
||||
fields: this._fields,
|
||||
fields: fields,
|
||||
domain: this._domain,
|
||||
context: this._context,
|
||||
sort: this._sort,
|
||||
|
@ -77,9 +68,7 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
}, _.bind(function (records) {
|
||||
var data_records = _.map(
|
||||
records, function (record) {
|
||||
return new openerp.base.DataRecord(
|
||||
this.session, this.model,
|
||||
this._fields, record);
|
||||
return new openerp.base.DataRecord(this.session, this.model, fields, record);
|
||||
}, this);
|
||||
|
||||
this.on_fetch(data_records, {
|
||||
|
@ -116,16 +105,14 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
*
|
||||
* @returns itself
|
||||
*/
|
||||
active_ids: function () {
|
||||
active_ids: function (fields) {
|
||||
this.rpc('/base/dataset/get', {
|
||||
ids: this.get_active_ids(),
|
||||
model: this.model
|
||||
}, _.bind(function (records) {
|
||||
this.on_active_ids(_.map(
|
||||
records, function (record) {
|
||||
return new openerp.base.DataRecord(
|
||||
this.session, this.model,
|
||||
this._fields, record);
|
||||
return new openerp.base.DataRecord(this.session, this.model, fields, record);
|
||||
}, this));
|
||||
}, this));
|
||||
return this;
|
||||
|
@ -149,7 +136,7 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
*
|
||||
* @returns itself
|
||||
*/
|
||||
active_id: function () {
|
||||
active_id: function (fields) {
|
||||
this.rpc('/base/dataset/get', {
|
||||
ids: [this.get_active_id()],
|
||||
model: this.model
|
||||
|
@ -158,7 +145,7 @@ openerp.base.DataSet = openerp.base.Controller.extend(
|
|||
this.on_active_id(
|
||||
record && new openerp.base.DataRecord(
|
||||
this.session, this.model,
|
||||
this._fields, record));
|
||||
fields, record));
|
||||
}, this));
|
||||
return this;
|
||||
},
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
|
||||
openerp.base.form = function (openerp) {
|
||||
|
||||
openerp.base.FormView = openerp.base.Controller.extend({
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
openerp.base.FormView = openerp.base.Controller.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).
|
||||
*/
|
||||
searchable: false,
|
||||
/**
|
||||
* @constructs
|
||||
* @param {openerp.base.Session} session the current openerp session
|
||||
* @param {String} element_id this view's root element id
|
||||
* @param {openerp.base.DataSet} dataset the dataset this view will work with
|
||||
* @param {String} view_id the identifier of the OpenERP view object
|
||||
*/
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this._super(session, element_id);
|
||||
this.view_manager;
|
||||
this.view_manager = view_manager;
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
@ -17,7 +31,7 @@ openerp.base.FormView = openerp.base.Controller.extend({
|
|||
},
|
||||
start: function() {
|
||||
//this.log('Starting FormView '+this.model+this.view_id)
|
||||
this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
|
||||
return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
var self = this;
|
||||
|
@ -92,6 +106,8 @@ openerp.base.FormView = openerp.base.Controller.extend({
|
|||
},
|
||||
on_saved: function() {
|
||||
// Check response for exceptions, display error
|
||||
},
|
||||
on_action: function (action) {
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -463,6 +479,10 @@ openerp.base.form.FieldDate = openerp.base.form.FieldChar.extend({
|
|||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldDate";
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('input').datepicker();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
openerp.base.list = function (openerp) {
|
||||
|
||||
openerp.base.views.add('list', 'openerp.base.ListView');
|
||||
openerp.base.ListView = openerp.base.Controller.extend({
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this._super(session, element_id);
|
||||
|
@ -9,6 +10,9 @@ openerp.base.ListView = openerp.base.Controller.extend({
|
|||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
this.name = "";
|
||||
// TODO: default to action.limit
|
||||
// TODO: decide if limit is a property of DataSet and thus global to all views (calendar ?)
|
||||
this.limit = 80;
|
||||
|
||||
this.cols = [];
|
||||
|
||||
|
@ -20,7 +24,7 @@ openerp.base.ListView = openerp.base.Controller.extend({
|
|||
},
|
||||
start: function() {
|
||||
//this.log('Starting ListView '+this.model+this.view_id)
|
||||
this.rpc("/base/listview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
return this.rpc("/base/listview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
this.fields_view = data.fields_view;
|
||||
|
@ -81,6 +85,20 @@ openerp.base.ListView = openerp.base.Controller.extend({
|
|||
return record.values;
|
||||
}));
|
||||
|
||||
},
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
var self = this;
|
||||
this.rpc('/base/session/eval_domain_and_context', {
|
||||
domains: domains,
|
||||
contexts: contexts,
|
||||
group_by_seq: groupbys
|
||||
}, function (results) {
|
||||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.set({
|
||||
context: results.context,
|
||||
domain: results.domain
|
||||
}).fetch(self.fields_view.fields, 0, self.limit);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -15,7 +15,13 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
|||
},
|
||||
start: function() {
|
||||
//this.log('Starting SearchView '+this.model+this.view_id)
|
||||
this.rpc("/base/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
return this.rpc("/base/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
},
|
||||
show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
hide: function () {
|
||||
this.$element.hide();
|
||||
},
|
||||
/**
|
||||
* Builds a list of widget rows (each row is an array of widgets)
|
||||
|
@ -442,122 +448,6 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.BaseWidget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.search.custom_filters = new openerp.base.Registry({
|
||||
'char': 'openerp.base.search.ExtendedSearchProposition.Char',
|
||||
'datetime': 'openerp.base.search.ExtendedSearchProposition.DateTime'
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearchProposition = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition',
|
||||
identifier_prefix: 'extended-search-proposition',
|
||||
init: function (parent, fields) {
|
||||
this._super(parent);
|
||||
this.fields = _(fields).chain()
|
||||
.map(function(val, key) { return _.extend({}, val, {'name': key}); })
|
||||
.sortBy(function(field) {return field.string;})
|
||||
.value();
|
||||
this.attrs = {_: _, fields: this.fields, selected: null};
|
||||
this.value = null;
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
this.select_field(this.fields.length > 0 ? this.fields[0] : null);
|
||||
var _this = this;
|
||||
this.$element.find(".searchview_extended_prop_field").change(function() {
|
||||
_this.changed();
|
||||
});
|
||||
var delete_btn = this.$element.find('.searchview_extended_delete_prop');
|
||||
delete_btn.click(function (e) {
|
||||
_this.stop();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
},
|
||||
changed: function() {
|
||||
var nval = this.$element.find(".searchview_extended_prop_field").val();
|
||||
if(this.attrs.selected == null || nval != this.attrs.selected.name) {
|
||||
this.select_field(_.detect(this.fields, function(x) {return x.name == nval;}));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Selects the provided field object
|
||||
*
|
||||
* @param field a field descriptor object (as returned by fields_get, augmented by the field name)
|
||||
*/
|
||||
select_field: function(field) {
|
||||
var _this = this;
|
||||
if(this.attrs.selected != null) {
|
||||
this.value.stop();
|
||||
this.value = null;
|
||||
this.$element.find('.searchview_extended_prop_op').html('');
|
||||
}
|
||||
this.attrs.selected = field;
|
||||
if(field == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.value = new (openerp.base.search.custom_filters.get_object(field.type))
|
||||
(this);
|
||||
_.each(this.value.operators, function(operator) {
|
||||
var option = jQuery('<option>', {value: operator.value})
|
||||
.text(operator.text)
|
||||
.appendTo(_this.$element.find('.searchview_extended_prop_op'));
|
||||
});
|
||||
this.$element.find('.searchview_extended_prop_value').html(
|
||||
this.value.render({}));
|
||||
this.value.start();
|
||||
} catch (e) {
|
||||
if (! e instanceof openerp.base.KeyNotFound) {
|
||||
throw e;
|
||||
}
|
||||
this.attrs.selected = null;
|
||||
this.log('Unknow field type ' + e.key);
|
||||
}
|
||||
},
|
||||
get_proposition: function() {
|
||||
if ( this.attrs.selected == null)
|
||||
return null;
|
||||
var field = this.attrs.selected.name;
|
||||
var op = this.$element.find('.searchview_extended_prop_op').val();
|
||||
var value = this.value.get_value();
|
||||
return [field, op, value];
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearchProposition.Char = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition.char',
|
||||
identifier_prefix: 'extended-search-proposition-char',
|
||||
operators: [
|
||||
{value: "ilike", text: "contains"},
|
||||
{value: "not ilike", text: "doesn't contain"},
|
||||
{value: "=", text: "is equal to"},
|
||||
{value: "!=", text: "is not equal to"},
|
||||
{value: ">", text: "greater than"},
|
||||
{value: "<", text: "less than"},
|
||||
{value: ">=", text: "greater or equal than"},
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.ExtendedSearchProposition.DateTime = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition.char',
|
||||
identifier_prefix: 'extended-search-proposition-datetime',
|
||||
operators: [
|
||||
{value: "=", text: "is equal to"},
|
||||
{value: "!=", text: "is not equal to"},
|
||||
{value: ">", text: "greater than"},
|
||||
{value: "<", text: "less than"},
|
||||
{value: ">=", text: "greater or equal than"},
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.search.Input = openerp.base.search.Widget.extend(
|
||||
/** @lends openerp.base.search.Input# */{
|
||||
/**
|
||||
|
@ -779,15 +669,81 @@ openerp.base.search.SelectionField = openerp.base.search.Field.extend({
|
|||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.DateTimeField = openerp.base.search.Field.extend({
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.Field
|
||||
*/
|
||||
openerp.base.search.DateField = openerp.base.search.Field.extend(
|
||||
/** @lends openerp.base.search.DateField# */{
|
||||
template: 'SearchView.fields.date',
|
||||
/**
|
||||
* enables date picker on the HTML widgets
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.find('input').datepicker({
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
},
|
||||
stop: function () {
|
||||
this.$element.find('input').datepicker('destroy');
|
||||
},
|
||||
/**
|
||||
* Returns an object with two optional keys ``from`` and ``to`` providing
|
||||
* the values for resp. the from and to sections of the date widget.
|
||||
*
|
||||
* If a key is absent, then the corresponding field was not filled.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
get_values: function () {
|
||||
var values_array = this.$element.find('input').serializeArray();
|
||||
|
||||
var from = values_array[0].value;
|
||||
var to = values_array[1].value;
|
||||
|
||||
var field_values = {};
|
||||
if (from) {
|
||||
field_values.from = from;
|
||||
}
|
||||
if (to) {
|
||||
field_values.to = to;
|
||||
}
|
||||
return field_values;
|
||||
},
|
||||
get_context: function () {
|
||||
var values = this.get_values();
|
||||
if (!this.attrs.context || _.isEmpty(values)) {
|
||||
return null;
|
||||
}
|
||||
return _.extend(
|
||||
{}, this.attrs.context,
|
||||
{own_values: {self: values}});
|
||||
},
|
||||
get_domain: function () {
|
||||
var values = this.get_values();
|
||||
if (_.isEmpty(values)) {
|
||||
return null;
|
||||
}
|
||||
var domain = this.attrs['filter_domain'];
|
||||
if (!domain) {
|
||||
domain = [];
|
||||
if (values.from) {
|
||||
domain.push([this.attrs.name, '>=', values.from]);
|
||||
}
|
||||
if (values.to) {
|
||||
domain.push([this.attrs.name, '<=', values.to]);
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
return _.extend(
|
||||
{}, domain,
|
||||
{own_values: {self: values}});
|
||||
}
|
||||
});
|
||||
openerp.base.search.DateField = openerp.base.search.Field.extend({
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
}
|
||||
openerp.base.search.DateTimeField = openerp.base.search.DateField.extend({
|
||||
// TODO: time?
|
||||
});
|
||||
openerp.base.search.OneToManyField = openerp.base.search.IntegerField.extend({
|
||||
// TODO: .relation, .context, .domain
|
||||
|
@ -800,6 +756,122 @@ openerp.base.search.ManyToManyField = openerp.base.search.IntegerField.extend({
|
|||
// TODO: .related_columns (Array), .context, .domain
|
||||
});
|
||||
|
||||
openerp.base.search.custom_filters = new openerp.base.Registry({
|
||||
'char': 'openerp.base.search.ExtendedSearchProposition.Char',
|
||||
'datetime': 'openerp.base.search.ExtendedSearchProposition.DateTime'
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearchProposition = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition',
|
||||
identifier_prefix: 'extended-search-proposition',
|
||||
init: function (parent, fields) {
|
||||
this._super(parent);
|
||||
this.fields = _(fields).chain()
|
||||
.map(function(val, key) { return _.extend({}, val, {'name': key}); })
|
||||
.sortBy(function(field) {return field.string;})
|
||||
.value();
|
||||
this.attrs = {_: _, fields: this.fields, selected: null};
|
||||
this.value = null;
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
this.select_field(this.fields.length > 0 ? this.fields[0] : null);
|
||||
var _this = this;
|
||||
this.$element.find(".searchview_extended_prop_field").change(function() {
|
||||
_this.changed();
|
||||
});
|
||||
var delete_btn = this.$element.find('.searchview_extended_delete_prop');
|
||||
delete_btn.click(function (e) {
|
||||
_this.stop();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
},
|
||||
changed: function() {
|
||||
var nval = this.$element.find(".searchview_extended_prop_field").val();
|
||||
if(this.attrs.selected == null || nval != this.attrs.selected.name) {
|
||||
this.select_field(_.detect(this.fields, function(x) {return x.name == nval;}));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Selects the provided field object
|
||||
*
|
||||
* @param field a field descriptor object (as returned by fields_get, augmented by the field name)
|
||||
*/
|
||||
select_field: function(field) {
|
||||
var _this = this;
|
||||
if(this.attrs.selected != null) {
|
||||
this.value.stop();
|
||||
this.value = null;
|
||||
this.$element.find('.searchview_extended_prop_op').html('');
|
||||
}
|
||||
this.attrs.selected = field;
|
||||
if(field == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.value = new (openerp.base.search.custom_filters.get_object(field.type))
|
||||
(this);
|
||||
_.each(this.value.operators, function(operator) {
|
||||
var option = jQuery('<option>', {value: operator.value})
|
||||
.text(operator.text)
|
||||
.appendTo(_this.$element.find('.searchview_extended_prop_op'));
|
||||
});
|
||||
this.$element.find('.searchview_extended_prop_value').html(
|
||||
this.value.render({}));
|
||||
this.value.start();
|
||||
} catch (e) {
|
||||
if (! e instanceof openerp.base.KeyNotFound) {
|
||||
throw e;
|
||||
}
|
||||
this.attrs.selected = null;
|
||||
this.log('Unknow field type ' + e.key);
|
||||
}
|
||||
},
|
||||
get_proposition: function() {
|
||||
if ( this.attrs.selected == null)
|
||||
return null;
|
||||
var field = this.attrs.selected.name;
|
||||
var op = this.$element.find('.searchview_extended_prop_op').val();
|
||||
var value = this.value.get_value();
|
||||
return [field, op, value];
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearchProposition.Char = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition.char',
|
||||
identifier_prefix: 'extended-search-proposition-char',
|
||||
operators: [
|
||||
{value: "ilike", text: "contains"},
|
||||
{value: "not ilike", text: "doesn't contain"},
|
||||
{value: "=", text: "is equal to"},
|
||||
{value: "!=", text: "is not equal to"},
|
||||
{value: ">", text: "greater than"},
|
||||
{value: "<", text: "less than"},
|
||||
{value: ">=", text: "greater or equal than"},
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.ExtendedSearchProposition.DateTime = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search.proposition.char',
|
||||
identifier_prefix: 'extended-search-proposition-datetime',
|
||||
operators: [
|
||||
{value: "=", text: "is equal to"},
|
||||
{value: "!=", text: "is not equal to"},
|
||||
{value: ">", text: "greater than"},
|
||||
{value: "<", text: "less than"},
|
||||
{value: ">=", text: "greater or equal than"},
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -8,7 +8,6 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
// process all kind of actions
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
this.action = null;
|
||||
this.viewmanager = null;
|
||||
},
|
||||
/**
|
||||
|
@ -17,8 +16,10 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
*/
|
||||
do_action: function(action) {
|
||||
// instantiate the right controllers by understanding the action
|
||||
this.action = action;
|
||||
if(action.type == "ir.actions.act_window") {
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
this.viewmanager = new openerp.base.ViewManager(this.session,this.element_id);
|
||||
this.viewmanager.do_action_window(action);
|
||||
this.viewmanager.start();
|
||||
|
@ -26,15 +27,18 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Registry for all the main views
|
||||
*/
|
||||
openerp.base.views = new openerp.base.Registry();
|
||||
openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
// This will be ViewManager Abstract/Common
|
||||
// This will be ViewManager Abstract/Common
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
this.action = null;
|
||||
this.dataset = null;
|
||||
this.searchview_id = false;
|
||||
this.searchview = null;
|
||||
this.search_visible = true;
|
||||
this.active_view = null;
|
||||
// this.views = { "list": { "view_id":1234, "controller": instance} }
|
||||
this.views = {};
|
||||
this.sidebar = new openerp.base.Sidebar(null);
|
||||
|
@ -48,10 +52,41 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
|||
this.sidebar.stop();
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* Asks the view manager to switch visualization mode.
|
||||
*
|
||||
* @param {String} view_type type of view to display
|
||||
* @returns {jQuery.Deferred} new view loading promise
|
||||
*/
|
||||
on_mode_switch: function(view_type) {
|
||||
for (var i in this.views) {
|
||||
this.views[i].controller.$element.toggle(i === view_type);
|
||||
var view_promise;
|
||||
this.active_view = view_type;
|
||||
var view = this.views[view_type];
|
||||
if (!view.controller) {
|
||||
// Lazy loading of views
|
||||
var controller = new (openerp.base.views.get_object(view_type))(
|
||||
this, this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id);
|
||||
view_promise = controller.start();
|
||||
this.views[view_type].controller = controller;
|
||||
}
|
||||
|
||||
if (view.controller.searchable === false) {
|
||||
this.searchview.hide();
|
||||
} else {
|
||||
this.searchview.show();
|
||||
}
|
||||
|
||||
this.$element
|
||||
.find('.views-switchers button').removeAttr('disabled')
|
||||
.filter('[data-view-type="' + view_type + '"]')
|
||||
.attr('disabled', true);
|
||||
|
||||
for (var i in this.views) {
|
||||
if (this.views[i].controller) {
|
||||
this.views[i].controller.$element.toggle(i === view_type);
|
||||
}
|
||||
}
|
||||
return view_promise;
|
||||
},
|
||||
/**
|
||||
* Extract search view defaults from the current action's context.
|
||||
|
@ -70,51 +105,51 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
|||
});
|
||||
return defaults;
|
||||
},
|
||||
/**
|
||||
* Sets up the current viewmanager's search view.
|
||||
*
|
||||
* @param action the action being executed
|
||||
* @returns {jQuery.Deferred} search view startup deferred
|
||||
*/
|
||||
setup_search_view:function (action) {
|
||||
var self = this;
|
||||
if (this.searchview) {
|
||||
this.searchview.stop();
|
||||
}
|
||||
|
||||
var searchview = this.searchview = new openerp.base.SearchView(
|
||||
this, this.session, this.element_id + "_search",
|
||||
this.dataset, action.search_view_id[0] || false,
|
||||
this.search_defaults());
|
||||
searchview.on_search.add(function() {
|
||||
self.views[self.active_view].controller.do_search.apply(self, arguments);
|
||||
});
|
||||
return searchview.start();
|
||||
},
|
||||
do_action_window: function(action) {
|
||||
var self = this;
|
||||
var prefix_id = "#" + this.element_id;
|
||||
this.action = action;
|
||||
this.dataset = new openerp.base.DataSet(this.session, action.res_model);
|
||||
this.dataset.start();
|
||||
|
||||
this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: action.views}));
|
||||
|
||||
this.searchview_id = false;
|
||||
if(this.search_visible && action.search_view_id) {
|
||||
this.searchview_id = action.search_view_id[0];
|
||||
var searchview = this.searchview = new openerp.base.SearchView(
|
||||
this, this.session, this.element_id + "_search",
|
||||
this.dataset, this.searchview_id,
|
||||
this.search_defaults());
|
||||
searchview.on_search.add(this.do_search);
|
||||
searchview.start();
|
||||
var searchview_loaded = this.setup_search_view(action);
|
||||
|
||||
this.$element.find('.views-switchers button').click(function() {
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
_.each(action.views, function(view) {
|
||||
self.views[view[1]] = { view_id: view[0], controller: null };
|
||||
});
|
||||
|
||||
if (action['auto_search']) {
|
||||
searchview.on_loaded.add_last(
|
||||
searchview.do_search);
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < action.views.length; i++) {
|
||||
var view_id, controller;
|
||||
view_id = action.views[i][0];
|
||||
if(action.views[i][1] == "tree") {
|
||||
controller = new openerp.base.ListView(this, this.session, this.element_id + "_view_tree", this.dataset, view_id);
|
||||
controller.start();
|
||||
this.views.tree = { view_id: view_id, controller: controller };
|
||||
this.$element.find(prefix_id + "_button_tree").bind('click',function(){
|
||||
self.on_mode_switch("tree");
|
||||
});
|
||||
} else if(action.views[i][1] == "form") {
|
||||
controller = new openerp.base.FormView(this, this.session, this.element_id + "_view_form", this.dataset, view_id);
|
||||
controller.start();
|
||||
this.views.form = { view_id: view_id, controller: controller };
|
||||
this.$element.find(prefix_id + "_button_form").bind('click',function(){
|
||||
self.on_mode_switch("form");
|
||||
});
|
||||
}
|
||||
}
|
||||
// switch to the first one in sequence
|
||||
this.on_mode_switch("tree");
|
||||
var inital_view_loaded = this.on_mode_switch(action.views[0][1]);
|
||||
|
||||
if (action['auto_search']) {
|
||||
$.when(searchview_loaded, inital_view_loaded)
|
||||
.then(this.searchview.do_search);
|
||||
}
|
||||
},
|
||||
// create when root, also add to parent when o2m
|
||||
on_create: function() {
|
||||
|
@ -123,19 +158,10 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
|||
},
|
||||
on_edit: function() {
|
||||
},
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
var self = this;
|
||||
this.rpc('/base/session/eval_domain_and_context', {
|
||||
domains: domains,
|
||||
contexts: contexts,
|
||||
group_by_seq: groupbys
|
||||
}, function (results) {
|
||||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.set({
|
||||
context: results.context,
|
||||
domain: results.domain
|
||||
}).fetch(0, self.action.limit);
|
||||
});
|
||||
/**
|
||||
* Called when one of the view want to execute an action
|
||||
*/
|
||||
on_action: function(action) {
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -262,19 +288,43 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('calendar', 'openerp.base.CalendarView');
|
||||
|
||||
openerp.base.CalendarView = openerp.base.Controller.extend({
|
||||
// Dhtmlx scheduler ?
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Calendar view');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('gantt', 'openerp.base.GanttView');
|
||||
openerp.base.GanttView = openerp.base.Controller.extend({
|
||||
// Dhtmlx gantt ?
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Gantt view');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
/**
|
||||
* Genuine tree view (the one displayed as a tree, not the list)
|
||||
*/
|
||||
openerp.base.TreeView = openerp.base.Controller.extend({
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Tree view');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.DiagramView = openerp.base.Controller.extend({
|
||||
//
|
||||
});
|
||||
|
||||
openerp.base.views.add('graph', 'openerp.base.GraphView');
|
||||
openerp.base.GraphView = openerp.base.Controller.extend({
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Graph view');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ProcessView = openerp.base.Controller.extend({
|
||||
|
|
|
@ -128,19 +128,18 @@
|
|||
<table class="view-manager-main-table">
|
||||
<tr>
|
||||
<td class="view-manager-main-content">
|
||||
<!-- TODO prefix id with the element_id of the controller t-attf-id="#{prefix}_localid" -->
|
||||
<div style="text-align:right;">
|
||||
<!--
|
||||
<input t-foreach="views" t-as="view" t-att-id="" t-att-value="view[1]"/>
|
||||
-->
|
||||
<t t-foreach="views" t-as="view">
|
||||
<input t-attf-id="#{prefix}_button_#{view[1]}" type="button" t-att-value="view[1]"/>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-id="#{prefix}_search"></div>
|
||||
<t t-foreach="views" t-as="view">
|
||||
<div t-attf-id="#{prefix}_view_#{view[1]}"></div>
|
||||
</t>
|
||||
<!-- TODO prefix id with the element_id of the controller t-attf-id="#{prefix}_localid" -->
|
||||
<div class="views-switchers">
|
||||
<t t-foreach="views" t-as="view">
|
||||
<button type="button" t-att-data-view-type="view[1]">
|
||||
<t t-esc="view[1]"/>
|
||||
</button>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-id="#{prefix}_search"/>
|
||||
<t t-foreach="views" t-as="view">
|
||||
<div t-attf-id="#{prefix}_view_#{view[1]}"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="view-manager-main-sidebar">
|
||||
</td>
|
||||
|
@ -328,6 +327,21 @@
|
|||
<t t-if="filters.length" t-raw="filters.render(defaults)"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.fields.date">
|
||||
<label style="display: block" t-att-title="attrs.help"
|
||||
t-att-for="element_id">
|
||||
<t t-esc="attrs.string || attrs.name"/>
|
||||
<span t-if="attrs.help">(?)</span>
|
||||
</label>
|
||||
<div style="white-space: nowrap;" t-att-id="element_id">
|
||||
<input t-att-name="attrs.name" type="text" class="field_date"
|
||||
t-att-value="defaults[attrs.name] || ''"/>
|
||||
to
|
||||
<input t-att-name="attrs.name" type="text" class="field_date"
|
||||
t-att-value="defaults[attrs.name] || ''"/>
|
||||
<t t-if="filters.length" t-raw="filters.render(defaults)"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.field.selection">
|
||||
<label style="display: block" t-att-title="attrs.help"
|
||||
t-att-for="element_id">
|
||||
|
|
|
@ -179,7 +179,9 @@ $(document).ready(function () {
|
|||
equal(event.limit, 42);
|
||||
start();
|
||||
});
|
||||
dataset.fetch(20, 42);
|
||||
dataset.fetch({
|
||||
name : { type : 'char' }
|
||||
}, 20, 42);
|
||||
});
|
||||
asyncTest("Domain and context propagation", 3, function () {
|
||||
var dataset = new openerp.base.DataSet(
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
$(document).ready(function () {
|
||||
var openerp;
|
||||
function get_widget(attrs) {
|
||||
var widget = new openerp.base.search.DateField(
|
||||
{attrs: attrs}, {name: 'foo'}, {inputs: []});
|
||||
$('#qunit-fixture').html(widget.render({}));
|
||||
widget.start();
|
||||
return widget;
|
||||
}
|
||||
|
||||
module('search-date', {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init(true);
|
||||
window.openerp.base.chrome(openerp);
|
||||
window.openerp.base.views(openerp);
|
||||
window.openerp.base.search(openerp);
|
||||
}
|
||||
});
|
||||
test('no values', function () {
|
||||
var widget = get_widget();
|
||||
deepEqual(widget.get_values(), {});
|
||||
strictEqual(widget.get_context(), null);
|
||||
strictEqual(widget.get_domain(), null);
|
||||
});
|
||||
test('filled from', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
|
||||
deepEqual(widget.get_values(), {from: '1912-06-23'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(), [['foo', '>=', '1912-06-23']]);
|
||||
});
|
||||
test('filled to', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(widget.get_values(), {to: '1954-06-07'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(), [['foo', '<=', '1954-06-07']]);
|
||||
});
|
||||
test('filled both', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(widget.get_values(), {from: '1912-06-23', to: '1954-06-07'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(),
|
||||
[['foo', '>=', '1912-06-23'], ['foo', '<=', '1954-06-07']]);
|
||||
});
|
||||
test('custom context', function () {
|
||||
var widget = get_widget({context: {__id: -1}});
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(
|
||||
widget.get_context(),
|
||||
{__id: -1,
|
||||
own_values: {
|
||||
self: {from: '1912-06-23', to: '1954-06-07'}}});
|
||||
});
|
||||
test('custom filter_domain', function () {
|
||||
var widget = get_widget({filter_domain: {__id: -42}});
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(
|
||||
widget.get_domain(),
|
||||
{__id: -42,
|
||||
own_values: {
|
||||
self: {from: '1912-06-23', to: '1954-06-07'}}});
|
||||
});
|
||||
});
|
|
@ -12,11 +12,18 @@
|
|||
|
||||
<!-- jquery -->
|
||||
<script src="/base/static/lib/jquery/jquery-1.5.1.js"></script>
|
||||
<script src="/base/static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js"></script>
|
||||
|
||||
<script src="/base/static/lib/qweb/qweb.js"></script>
|
||||
|
||||
<script src="/base/static/src/js/base.js"></script>
|
||||
<script src="/base/static/src/js/chrome.js"></script>
|
||||
<script src="/base/static/src/js/data.js"></script>
|
||||
|
||||
<script src="/base/static/src/js/views.js"></script>
|
||||
<script src="/base/static/src/js/search.js"></script>
|
||||
<script type="text/javascript">
|
||||
QWeb.add_template('/base/static/src/xml/base.xml');
|
||||
</script>
|
||||
</head>
|
||||
<body id="oe" class="openerp">
|
||||
<h1 id="qunit-header">OpenERP Base Test Suite</h1>
|
||||
|
@ -24,7 +31,9 @@
|
|||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
<script type="text/javascript" src="/base/static/test/dataset.js"></script>
|
||||
<script type="text/javascript" src="/base/static/test/registry.js"></script>
|
||||
<script type="text/javascript" src="/base/static/test/search-date.js"></script>
|
||||
</html>
|
||||
|
|
|
@ -97,3 +97,55 @@ class LoadTest(unittest2.TestCase):
|
|||
}]
|
||||
}]
|
||||
)
|
||||
|
||||
class ActionMungerTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
self.menu = base.controllers.main.Menu()
|
||||
def test_actual_treeview(self):
|
||||
action = {
|
||||
"views": [[False, "tree"], [False, "form"],
|
||||
[False, "calendar"]],
|
||||
"view_type": "tree",
|
||||
"view_id": False,
|
||||
"view_mode": "tree,form,calendar"
|
||||
}
|
||||
changed = action.copy()
|
||||
del action['view_type']
|
||||
base.controllers.main.fix_view_modes(changed)
|
||||
|
||||
self.assertEqual(changed, action)
|
||||
|
||||
def test_list_view(self):
|
||||
action = {
|
||||
"views": [[False, "tree"], [False, "form"],
|
||||
[False, "calendar"]],
|
||||
"view_type": "form",
|
||||
"view_id": False,
|
||||
"view_mode": "tree,form,calendar"
|
||||
}
|
||||
base.controllers.main.fix_view_modes(action)
|
||||
|
||||
self.assertEqual(action, {
|
||||
"views": [[False, "list"], [False, "form"],
|
||||
[False, "calendar"]],
|
||||
"view_id": False,
|
||||
"view_mode": "list,form,calendar"
|
||||
})
|
||||
|
||||
def test_redundant_views(self):
|
||||
|
||||
action = {
|
||||
"views": [[False, "tree"], [False, "form"],
|
||||
[False, "calendar"], [42, "tree"]],
|
||||
"view_type": "form",
|
||||
"view_id": False,
|
||||
"view_mode": "tree,form,calendar"
|
||||
}
|
||||
base.controllers.main.fix_view_modes(action)
|
||||
|
||||
self.assertEqual(action, {
|
||||
"views": [[False, "list"], [False, "form"],
|
||||
[False, "calendar"], [42, "list"]],
|
||||
"view_id": False,
|
||||
"view_mode": "list,form,calendar"
|
||||
})
|
||||
|
|
|
@ -32,7 +32,7 @@ class ViewTest(unittest2.TestCase):
|
|||
|
||||
def test_convert_literal_domain(self):
|
||||
e = xml.etree.ElementTree.Element(
|
||||
'field', domain="[('somefield', '=', 3)]")
|
||||
'field', domain=" [('somefield', '=', 3)] ")
|
||||
self.view.parse_domains_and_contexts(e, None)
|
||||
|
||||
self.assertEqual(
|
||||
|
@ -75,7 +75,7 @@ class ViewTest(unittest2.TestCase):
|
|||
|
||||
def test_convert_literal_context(self):
|
||||
e = xml.etree.ElementTree.Element(
|
||||
'field', context="{'some_prop': 3}")
|
||||
'field', context=" {'some_prop': 3} ")
|
||||
self.view.parse_domains_and_contexts(e, None)
|
||||
|
||||
self.assertEqual(
|
||||
|
|
Loading…
Reference in New Issue