[MERGE]
bzr revid: nicolas.vanhoren@openerp.com-20110513145314-q71g21r1o4trx6v8
This commit is contained in:
commit
348a3386b3
|
@ -357,6 +357,28 @@ class DataSet(openerpweb.Controller):
|
|||
reads = Model.read(ids, fields or False, request.context)
|
||||
reads.sort(key=lambda obj: ids.index(obj['id']))
|
||||
return reads
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, ids, fields=False):
|
||||
return self.do_search_read(request, model, ids, fields)
|
||||
def search_read(self, request, model, ids, fields=False):
|
||||
""" Performs a read()
|
||||
|
||||
:param request: a JSON-RPC request object
|
||||
:type request: openerpweb.JsonRequest
|
||||
:param str model: the name of the model to search on
|
||||
:param ids: the ids of the records
|
||||
:type ids: [?]
|
||||
:param fields: a list of the fields to return in the result records
|
||||
:type fields: [str]
|
||||
:returns: a list of result records
|
||||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
|
||||
reads = Model.read(ids, fields or False, request.context)
|
||||
reads.sort(key=lambda obj: ids.index(obj['id']))
|
||||
return reads
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get(self, request, model, ids, fields=False):
|
||||
|
@ -424,6 +446,19 @@ class DataSet(openerpweb.Controller):
|
|||
m = req.session.model(model)
|
||||
r = m.default_get(fields, context)
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def name_search(self, req, model, search_str, domain=[], context={}):
|
||||
m = req.session.model(model)
|
||||
r = m.name_search(search_str+'%', domain, '=ilike', context)
|
||||
return {'result': r}
|
||||
|
||||
class DataGroup(openerpweb.Controller):
|
||||
_cp_path = "/base/group"
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, group_by_fields, domain=None, context=None):
|
||||
Model = request.session.model(model)
|
||||
return Model.read_group(domain or False, False, group_by_fields, 0, False, context or False)
|
||||
|
||||
class View(openerpweb.Controller):
|
||||
def fields_view_get(self, request, model, view_id, view_type,
|
||||
|
|
|
@ -116,7 +116,7 @@ var QWeb2 = {
|
|||
var new_dict = this.extend({}, old_dict);
|
||||
new_dict['__caller__'] = old_dict['__template__'];
|
||||
if (callback) {
|
||||
new_dict[0] = callback(context, new_dict);
|
||||
new_dict['__content__'] = callback(context, new_dict);
|
||||
}
|
||||
var r = context.engine._render(template, new_dict);
|
||||
if (_import) {
|
||||
|
@ -485,9 +485,6 @@ QWeb2.Element = (function() {
|
|||
format_expression : function(e) {
|
||||
/* Naive format expression builder. Replace reserved words and variables to dict[variable]
|
||||
* Does not handle spaces before dot yet, and causes problems for anonymous functions. Use t-js="" for that */
|
||||
if (e === '0') {
|
||||
return "dict['0']";
|
||||
}
|
||||
if (QWeb2.expressions_cache[e]) {
|
||||
return QWeb2.expressions_cache[e];
|
||||
}
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/data.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/views.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/form.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/list.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/search.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/views.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/m2o.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/base/static/lib/jquery.ui/css/smoothness/jquery-ui-1.8.9.custom.css" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/base/static/lib/jquery.ui.notify/css/ui.notify.css" />
|
||||
|
|
|
@ -221,8 +221,6 @@ body.openerp {
|
|||
height: 63px;
|
||||
width: 200px;
|
||||
margin-right: 10px;
|
||||
line-height: 63px;
|
||||
text-align: center;
|
||||
border: 1px solid white;
|
||||
border-right-color: black;
|
||||
border-bottom-color: black;
|
||||
|
@ -232,7 +230,12 @@ body.openerp {
|
|||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#CECECE',GradientType=0 );
|
||||
}
|
||||
.openerp .company_logo {
|
||||
vertical-align: middle
|
||||
margin-top: 7px;
|
||||
margin-left: 10px;
|
||||
display: block;
|
||||
background: url(/base/static/src/img/logo.png);
|
||||
width:180px;
|
||||
height:46px;
|
||||
}
|
||||
.openerp .header_title {
|
||||
float: left;
|
||||
|
@ -440,6 +443,9 @@ body.openerp {
|
|||
.openerp .searchview_group_content {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.openerp .searchview_group_content .oe-searchview-render-line {
|
||||
width:0;
|
||||
}
|
||||
|
||||
|
||||
.openerp .oe-searchview-render-line {
|
||||
|
@ -452,12 +458,12 @@ body.openerp {
|
|||
margin: 2px;
|
||||
}
|
||||
|
||||
.openerp .searchview_extended_add_proposition, .openerp .searchview_extended_add_group {
|
||||
.openerp .searchview_extended_add_proposition span, .openerp .searchview_extended_add_group span {
|
||||
background: url(../img/icons/gtk-add.png) repeat-y;
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.openerp .searchview_extended_delete_group, .openerp .searchview_extended_delete_prop {
|
||||
.openerp .searchview_extended_delete_group span, .openerp .searchview_extended_delete_prop span {
|
||||
background: url(../img/icons/gtk-remove.png) repeat-y;
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
@ -770,15 +776,61 @@ body.openerp {
|
|||
background-position: 21px 0;
|
||||
}
|
||||
|
||||
.openerp .kitten-mode-activated {
|
||||
.openerp.kitten-mode-activated .main_table {
|
||||
background: url(http://placekitten.com/g/1500/800) repeat;
|
||||
}
|
||||
|
||||
.openerp .kitten-mode-activated .header {
|
||||
.openerp.kitten-mode-activated .header {
|
||||
background: url(http://placekitten.com/g/211/65) repeat;
|
||||
}
|
||||
|
||||
.openerp .kitten-mode-activated .secondary_menu {
|
||||
.openerp.kitten-mode-activated .secondary_menu {
|
||||
background: url(http://placekitten.com/g/212/100) repeat;
|
||||
}
|
||||
|
||||
.openerp.kitten-mode-activated .menu {
|
||||
background: #828282;
|
||||
background: -moz-linear-gradient(top, #828282 0%, #4D4D4D 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#828282), color-stop(100%,#4D4D4D));
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#828282', endColorstr='#4D4D4D',GradientType=0 );
|
||||
}
|
||||
.openerp.kitten-mode-activated .menu a {
|
||||
background: none;
|
||||
}
|
||||
.openerp.kitten-mode-activated .menu span {
|
||||
background: none;
|
||||
}
|
||||
.openerp.kitten-mode-activated .sidebar-displaying-div li a,
|
||||
.openerp.kitten-mode-activated .oe-application .view-manager-main-content h2.oe_view_title,
|
||||
.openerp.kitten-mode-activated .oe-application .view-manager-main-content a.searchview_group_string,
|
||||
.openerp.kitten-mode-activated .oe-application .view-manager-main-content label {
|
||||
color: white;
|
||||
}
|
||||
.openerp.kitten-mode-activated .menu,
|
||||
.openerp.kitten-mode-activated .header_corner,
|
||||
.openerp.kitten-mode-activated .header_title,
|
||||
.openerp.kitten-mode-activated .secondary_menu div,
|
||||
.openerp.kitten-mode-activated .oe-application,
|
||||
.openerp.kitten-mode-activated .oe_footer,
|
||||
.openerp.kitten-mode-activated .loading,
|
||||
.openerp.kitten-mode-activated .ui-dialog {
|
||||
opacity:0.8;
|
||||
filter:alpha(opacity=80);
|
||||
}
|
||||
.openerp.kitten-mode-activated .header .company_logo {
|
||||
background: url(http://placekitten.com/g/180/46);
|
||||
}
|
||||
.openerp.kitten-mode-activated .loading {
|
||||
background: #828282;
|
||||
border-color: #828282;
|
||||
}
|
||||
|
||||
/* Many2one Autosearch */
|
||||
.openerp .ui_combo {
|
||||
height: 20px;
|
||||
margin-right: 1px;
|
||||
top: 4px;
|
||||
width: 22px;
|
||||
}
|
||||
/* ------------- End autocomplete ------- */
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 473 B |
Binary file not shown.
After Width: | Height: | Size: 471 B |
|
@ -126,6 +126,7 @@ openerp.base = function(instance) {
|
|||
openerp.base.views(instance);
|
||||
openerp.base.search(instance);
|
||||
openerp.base.list(instance);
|
||||
openerp.base.m2o(instance);
|
||||
openerp.base.form(instance);
|
||||
};
|
||||
|
||||
|
|
|
@ -790,10 +790,6 @@ openerp.base.Header = openerp.base.Controller.extend({
|
|||
this.do_update();
|
||||
},
|
||||
do_update: function() {
|
||||
if(jQuery.param != undefined &&
|
||||
jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
|
||||
this.kitten = 1;
|
||||
}
|
||||
this.$element.html(QWeb.render("Header", this));
|
||||
}
|
||||
});
|
||||
|
@ -897,7 +893,7 @@ openerp.base.WebClient = openerp.base.Controller.extend({
|
|||
var params = {};
|
||||
if(jQuery.param != undefined &&
|
||||
jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
|
||||
params = {kitten:1};
|
||||
this.$element.addClass("kitten-mode-activated");
|
||||
}
|
||||
this.$element.html(QWeb.render("Interface", params));
|
||||
|
||||
|
|
|
@ -3,15 +3,139 @@ openerp.base.data = function(openerp) {
|
|||
|
||||
openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.base.DataGroup# */{
|
||||
/**
|
||||
* Management interface between views and the collection of selected OpenERP
|
||||
* records (represents the view's state?)
|
||||
* Management interface between views and grouped collections of OpenERP
|
||||
* records.
|
||||
*
|
||||
* The root DataGroup is instantiated with the relevant information
|
||||
* (a session, a model, a domain, a context and a group_by sequence), the
|
||||
* domain and context may be empty. It is then interacted with via
|
||||
* :js:func:`~openerp.base.DataGroup.list`, which is used to read the
|
||||
* content of the current grouping level, and
|
||||
* :js:func:`~openerp.base.DataGroup.get`, which is used to fetch an item
|
||||
* of the current grouping level.
|
||||
*
|
||||
* @constructs
|
||||
* @extends openerp.base.Controller
|
||||
*
|
||||
* @param {openerp.base.Session} session Current OpenERP session
|
||||
* @param {String} model name of the model managed by this DataGroup
|
||||
* @param {Array} domain search domain for this DataGroup
|
||||
* @param {Object} context context of the DataGroup's searches
|
||||
* @param {Array} group_by sequence of fields by which to group
|
||||
*/
|
||||
init: function(session) {
|
||||
init: function(session, model, domain, context, group_by) {
|
||||
this._super(session, null);
|
||||
this.model = model;
|
||||
this.context = context;
|
||||
this.domain = domain;
|
||||
|
||||
this.group_by = group_by;
|
||||
|
||||
this.groups = null;
|
||||
},
|
||||
fetch: function () {
|
||||
// internal method
|
||||
var d = new $.Deferred();
|
||||
var self = this;
|
||||
|
||||
if (this.groups) {
|
||||
d.resolveWith(this, [this.groups]);
|
||||
} else {
|
||||
this.rpc('/base/group/read', {
|
||||
model: this.model,
|
||||
context: this.context,
|
||||
domain: this.domain,
|
||||
group_by_fields: this.group_by
|
||||
}, function () { }).then(function (response) {
|
||||
self.groups = response.result;
|
||||
// read_group results are annoying: they use the name of the
|
||||
// field grouped on to hold the value and the count, so no
|
||||
// generic access to those values is possible.
|
||||
// Alias them to `value` and `length`.
|
||||
d.resolveWith(self, [_(response.result).map(function (group) {
|
||||
var field_name = self.group_by[0];
|
||||
return _.extend({}, group, {
|
||||
// provide field used for grouping
|
||||
grouped_on: field_name,
|
||||
length: group[field_name + '_count'],
|
||||
value: group[field_name]
|
||||
});
|
||||
})]);
|
||||
}, function () {
|
||||
d.rejectWith.apply(d, self, [arguments]);
|
||||
});
|
||||
}
|
||||
return d.promise();
|
||||
},
|
||||
/**
|
||||
* Retrieves the content of an item in the DataGroup, which results in
|
||||
* either a DataSet or new DataGroup instance.
|
||||
*
|
||||
* Calling :js:func:`~openerp.base.DataGroup.get` without having called
|
||||
* :js:func:`~openerp.base.DataGroup.list` beforehand will likely result
|
||||
* in an error.
|
||||
*
|
||||
* The resulting :js:class:`~openerp.base.DataGroup` or
|
||||
* :js:class:`~openerp.base.DataSet` will be provided through the relevant
|
||||
* callback function. In both functions, the current DataGroup will be
|
||||
* provided as context (``this``)
|
||||
*
|
||||
* @param {Number} index the index of the group to open in the datagroup's collection
|
||||
* @param {Function} ifDataSet executed if the item results in a DataSet, provided with the new dataset as parameter
|
||||
* @param {Function} ifDataGroup executed if the item results in a DataSet, provided with the new datagroup as parameter
|
||||
*/
|
||||
get: function (index, ifDataSet, ifDataGroup) {
|
||||
var group = this.groups[index];
|
||||
if (!group) {
|
||||
throw new Error("No group at index " + index);
|
||||
}
|
||||
|
||||
var child_context = _.extend({}, this.context, group.__context);
|
||||
if (group.__context.group_by.length) {
|
||||
var datagroup = new openerp.base.DataGroup(
|
||||
this.session, this.model, group.__domain, child_context,
|
||||
group.__context.group_by);
|
||||
ifDataGroup.call(this, datagroup);
|
||||
} else {
|
||||
var dataset = new openerp.base.DataSetSearch(this.session, this.model);
|
||||
dataset.domain = group.__domain;
|
||||
dataset.context = child_context;
|
||||
ifDataSet.call(this, dataset);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Gathers the content of the current data group (the current grouping
|
||||
* level), and provides it via a promise object to which callbacks should
|
||||
* be added::
|
||||
*
|
||||
* datagroup.list().then(function (list) {
|
||||
* // manipulate list here
|
||||
* });
|
||||
*
|
||||
* The argument to the callback is the list of elements fetched, the
|
||||
* context (``this``) is the datagroup itself.
|
||||
*
|
||||
* The items of a list are the standard objects returned by ``read_group``
|
||||
* with three properties added:
|
||||
*
|
||||
* ``length``
|
||||
* the number of records contained in the group (and all of its
|
||||
* sub-groups). This does *not* provide the size of the "next level"
|
||||
* of the group, unless the group is terminal (no more groups within
|
||||
* it).
|
||||
* ``grouped_on``
|
||||
* the name of the field this level was grouped on, this is mostly
|
||||
* used for display purposes, in order to know the name of the current
|
||||
* level of grouping. The ``grouped_on`` should be the same for all
|
||||
* objects of the list.
|
||||
* ``value``
|
||||
* the value which led to this group (this is the value all contained
|
||||
* records have for the current ``grouped_on`` field name).
|
||||
*
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
list: function () {
|
||||
return this.fetch();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -89,12 +213,12 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
|||
context: this.context
|
||||
}, callback);
|
||||
},
|
||||
create: function(data, callback) {
|
||||
create: function(data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/create', {
|
||||
model: this.model,
|
||||
data: data,
|
||||
context: this.context
|
||||
}, callback);
|
||||
}, callback, error_callback);
|
||||
},
|
||||
write: function (id, data, callback) {
|
||||
return this.rpc('/base/dataset/save', {
|
||||
|
@ -119,6 +243,15 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
|||
args: args
|
||||
}, callback);
|
||||
},
|
||||
name_search: function (search_str, callback) {
|
||||
search_str = search_str || '';
|
||||
return this.rpc('/base/dataset/name_search', {
|
||||
model: this.model,
|
||||
search_str: search_str,
|
||||
domain: this.domain || [],
|
||||
context: this.context
|
||||
}, callback);
|
||||
},
|
||||
exec_workflow: function (id, signal, callback) {
|
||||
return this.rpc('/base/dataset/exec_workflow', {
|
||||
model: this.model,
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
|
||||
openerp.base.dates = function(openerp) {
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone is assumed to be UTC (standard for OpenERP 6.1)
|
||||
* and will be converted to the browser's timezone.
|
||||
*
|
||||
* @param {String} str A string representing a datetime.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_datetime = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
|
@ -17,6 +27,13 @@ openerp.base.parse_datetime = function(str) {
|
|||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {String} str A string representing a date.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_date = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
|
@ -33,6 +50,13 @@ openerp.base.parse_date = function(str) {
|
|||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {String} str A string representing a time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_time = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
|
@ -49,7 +73,7 @@ openerp.base.parse_time = function(str) {
|
|||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Just a simple function to add some '0' if an integer it too small.
|
||||
*/
|
||||
var fts = function(str, size) {
|
||||
|
@ -61,8 +85,18 @@ var fts = function(str, size) {
|
|||
return to_add + str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone of the Date object is assumed to be the one of the
|
||||
* browser and it will be converted to UTC (standard for OpenERP 6.1).
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a datetime.
|
||||
*/
|
||||
openerp.base.format_datetime = function(obj) {
|
||||
if(! obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getUTCFullYear(),4) + "-" + fts(obj.getUTCMonth() + 1,2) + "-"
|
||||
|
@ -70,20 +104,35 @@ openerp.base.format_datetime = function(obj) {
|
|||
+ fts(obj.getUTCMinutes(),2) + ":" + fts(obj.getUTCSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a date.
|
||||
*/
|
||||
openerp.base.format_date = function(obj) {
|
||||
if(! obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getFullYear(),4) + "-" + fts(obj.getMonth() + 1,2) + "-"
|
||||
+ fts(obj.getDate(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a time.
|
||||
*/
|
||||
openerp.base.format_time = function(obj) {
|
||||
if(! obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getHours(),2) + ":" + fts(obj.getMinutes(),2) + ":"
|
||||
+ fts(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
openerp.base.form = function (openerp) {
|
||||
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
openerp.base.FormView = openerp.base.Controller.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).
|
||||
|
@ -143,14 +143,21 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base
|
|||
var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/);
|
||||
if (call) {
|
||||
var method = call[1], args = [];
|
||||
var argument_replacement = {
|
||||
'False' : false,
|
||||
'True' : true,
|
||||
'None' : null
|
||||
}
|
||||
_.each(call[2].split(','), function(a) {
|
||||
var field = _.trim(a);
|
||||
if (self.fields[field]) {
|
||||
if (field in argument_replacement) {
|
||||
args.push(argument_replacement[field]);
|
||||
} else if (self.fields[field]) {
|
||||
var value = self.fields[field].value;
|
||||
args.push(value == null ? false : value);
|
||||
} else {
|
||||
args.push(false);
|
||||
this.log("warning : on_change can't find field " + field, onchange);
|
||||
self.log("warning : on_change can't find field " + field, onchange);
|
||||
}
|
||||
});
|
||||
var ajax = {
|
||||
|
@ -365,7 +372,8 @@ openerp.base.form.compute_domain = function(expr, fields) {
|
|||
}
|
||||
}
|
||||
return _.indexOf(stack, false) == -1;
|
||||
},
|
||||
}
|
||||
|
||||
openerp.base.form.Widget = openerp.base.Controller.extend({
|
||||
init: function(view, node) {
|
||||
this.view = view;
|
||||
|
@ -532,7 +540,7 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
|||
on_confirmed: function() {
|
||||
var self = this;
|
||||
|
||||
this.execute_action(
|
||||
this.view.execute_action(
|
||||
this.node.attrs, this.view.dataset, this.session.action_manager,
|
||||
this.view.datarecord.id, function (result) {
|
||||
self.log("Button returned", result);
|
||||
|
@ -540,9 +548,6 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
|||
});
|
||||
}
|
||||
});
|
||||
// let WidgetButton execute actions
|
||||
_.extend(openerp.base.form.WidgetButton.prototype,
|
||||
openerp.base.ActionExecutor);
|
||||
|
||||
openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({
|
||||
init: function(view, node) {
|
||||
|
@ -649,7 +654,24 @@ openerp.base.form.FieldChar = openerp.base.form.Field.extend({
|
|||
openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldEmail";
|
||||
this.validation_regex = /@/;
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('button').click(this.on_button_clicked);
|
||||
},
|
||||
on_button_clicked: function() {
|
||||
if (!this.value || this.invalid) {
|
||||
this.notification.warn("E-mail error", "Can't send email to invalid e-mail address");
|
||||
} else {
|
||||
location.href = 'mailto:' + this.value;
|
||||
}
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
var show_value = (value != null && value !== false) ? value : '';
|
||||
this.$element.find('a').attr('href', 'mailto:' + show_value);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -659,44 +681,91 @@ openerp.base.form.FieldUrl = openerp.base.form.FieldChar.extend({
|
|||
openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.validation_regex = /^\d+(\.\d+)?$/;
|
||||
this.validation_regex = /^-?\d+(\.\d+)?$/;
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
var show_value = (value != null && value !== false) ? value.toFixed(2) : '';
|
||||
if (!value) {
|
||||
// As in GTK client, floats default to 0
|
||||
value = 0;
|
||||
}
|
||||
this._super.apply(this, [value]);
|
||||
var show_value = value.toFixed(2);
|
||||
this.$element.find('input').val(show_value);
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = this.$element.find('input').val().replace(/,/g, '.');
|
||||
},
|
||||
validate: function() {
|
||||
this._super.apply(this, arguments);
|
||||
if (!this.invalid) {
|
||||
this.value = Number(this.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldDate = openerp.base.form.FieldChar.extend({
|
||||
openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldDate";
|
||||
this.validation_regex = /^\d+-\d+-\d+$/;
|
||||
this.jqueryui_object = 'datetimepicker';
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('input').change(this.on_ui_change).datepicker({
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldDatetime = openerp.base.form.FieldChar.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldDatetime";
|
||||
this.validation_regex = /^\d+-\d+-\d+( \d+:\d+(:\d+)?)?$/;
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('input').change(this.on_ui_change).datetimepicker({
|
||||
this.$element.find('input').change(this.on_ui_change)[this.jqueryui_object]({
|
||||
dateFormat: 'yy-mm-dd',
|
||||
timeFormat: 'hh:mm:ss'
|
||||
});
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
if (value == null || value == false) {
|
||||
this.$element.find('input').val('');
|
||||
} else {
|
||||
this.value = this.parse(value);
|
||||
this.$element.find('input')[this.jqueryui_object]('setDate', this.value);
|
||||
}
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = this.$element.find('input')[this.jqueryui_object]('getDate') || false;
|
||||
if (this.value) {
|
||||
this.value = this.format(this.value);
|
||||
}
|
||||
},
|
||||
validate: function() {
|
||||
this.invalid = this.required && this.value === false;
|
||||
},
|
||||
parse: openerp.base.parse_datetime,
|
||||
format: openerp.base.format_datetime
|
||||
});
|
||||
|
||||
openerp.base.form.FieldDate = openerp.base.form.FieldDatetime.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.jqueryui_object = 'datepicker';
|
||||
},
|
||||
parse: openerp.base.parse_date,
|
||||
format: openerp.base.format_date
|
||||
});
|
||||
|
||||
openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.validation_regex = /^\d+:\d+$/;
|
||||
},
|
||||
set_value: function(value) {
|
||||
value = value || 0;
|
||||
this._super.apply(this, [value]);
|
||||
var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60));
|
||||
this.$element.find('input').val(show_value);
|
||||
},
|
||||
validate: function() {
|
||||
if (typeof(this.value) == "string") {
|
||||
this._super.apply(this, arguments);
|
||||
if (!this.invalid) {
|
||||
var time = this.value.split(':');
|
||||
this.value = parseInt(time[0], 10) + parseInt(time[1], 10) / 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -817,10 +886,33 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldMany2OneDatasSet = openerp.base.DataSetStatic.extend({
|
||||
start: function() {
|
||||
},
|
||||
write: function (id, data, callback) {
|
||||
this._super(id, data, callback);
|
||||
},
|
||||
});
|
||||
|
||||
openerp.base.form.FieldMany2OneViewManager = openerp.base.ViewManager.extend({
|
||||
init: function(session, element_id, dataset, views) {
|
||||
this._super(session, element_id, dataset, views);
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldMany2One";
|
||||
this.is_field_m2o = true;
|
||||
},
|
||||
start: function() {
|
||||
this.$element = $('#' + this.element_id);
|
||||
this.dataset = new openerp.base.form.FieldMany2OneDatasSet(this.session, this.field.relation);
|
||||
var views = [ [false,"list"], [false,"form"] ];
|
||||
this.viewmanager = new openerp.base.form.FieldMany2OneViewManager(this.view.session, this.element_id, this.dataset, views);
|
||||
new openerp.base.m2o(this.viewmanager, this.$element, this.field.relation, this.dataset, this.session)
|
||||
this.$element.find('input').change(this.on_ui_change);
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
|
@ -830,6 +922,16 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
this.value = value[0];
|
||||
}
|
||||
this.$element.find('input').val(show_value);
|
||||
this.$element.find('input').attr('m2o_id', this.value);
|
||||
},
|
||||
|
||||
get_value: function() {
|
||||
var val = this.$element.find('input').attr('m2o_id') || this.value
|
||||
return val;
|
||||
},
|
||||
|
||||
on_ui_change: function() {
|
||||
this.touched = this.view.touched = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -890,6 +992,8 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
|||
this._super(view, node);
|
||||
this.template = "FieldMany2Many";
|
||||
this.list_id = _.uniqueId("many2many");
|
||||
this.is_started = false;
|
||||
this.is_setted = false;
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
|
@ -899,23 +1003,35 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
|||
var self = this;
|
||||
this.list_view.m2m_field = this;
|
||||
this.list_view.start();
|
||||
var hack = {loaded: false};
|
||||
this.list_view.on_loaded.add_last(function() {
|
||||
if (! hack.loaded) {
|
||||
self.is_started = true;
|
||||
self.check_load();
|
||||
hack.loaded = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
set_value: function(value) {
|
||||
if (value != false) {
|
||||
this.dataset.ids = value;
|
||||
this.dataset.count = value.length;
|
||||
this.list_view.do_reload();
|
||||
this.is_setted = true;
|
||||
this.check_load();
|
||||
}
|
||||
},
|
||||
get_value: function() {
|
||||
return [[6,false,this.dataset.ids]];
|
||||
},
|
||||
check_load: function() {
|
||||
if(this.is_started && this.is_setted) {
|
||||
this.list_view.do_reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
do_delete: function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
var ids = [this.rows[$(e.currentTarget).closest('tr').prevAll().length].data.id.value];
|
||||
do_delete: function (ids) {
|
||||
this.dataset.ids = _.without.apply(null, [this.dataset.ids].concat(ids));
|
||||
this.dataset.count = this.dataset.ids.length;
|
||||
// there may be a faster way
|
||||
|
@ -937,12 +1053,20 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
|||
},
|
||||
do_add_record: function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
// TODO: need to open a popup with search view
|
||||
var pop = new openerp.base.form.Many2XSelectPopup(null, this.m2m_field.view.session);
|
||||
pop.select_element(this.model);
|
||||
var self = this;
|
||||
pop.on_select_element.add(function(element_id) {
|
||||
if(! _.detect(self.dataset.ids, function(x) {return x == element_id;})) {
|
||||
self.dataset.ids.push(element_id);
|
||||
self.dataset.count = self.dataset.ids.length;
|
||||
self.do_reload();
|
||||
}
|
||||
pop.stop();
|
||||
});
|
||||
},
|
||||
on_select_row: function(event) {
|
||||
var $target = $(event.currentTarget);
|
||||
var row = this.rows[$target.prevAll().length];
|
||||
var id = row.data.id.value;
|
||||
select_record: function(index) {
|
||||
var id = this.rows[index].data.id.value;
|
||||
if(! id) {
|
||||
return;
|
||||
}
|
||||
|
@ -959,6 +1083,97 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
identifier_prefix: "many2xselectpopup",
|
||||
template: "Many2XSelectPopup",
|
||||
select_element: function(model) {
|
||||
this.model = model;
|
||||
var html = this.render();
|
||||
jQuery(html).dialog({title: '',
|
||||
modal: true,
|
||||
minWidth: 800});
|
||||
this.start();
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.model);
|
||||
this.setup_search_view();
|
||||
},
|
||||
setup_search_view: function() {
|
||||
var self = this;
|
||||
if (this.searchview) {
|
||||
this.searchview.stop();
|
||||
}
|
||||
this.searchview = new openerp.base.SearchView(this, this.session, this.element_id + "_search",
|
||||
this.dataset, false, {});
|
||||
this.searchview.on_search.add(function(domains, contexts, groupbys) {
|
||||
self.view_list.do_search.call(
|
||||
self, domains, contexts, groupbys);
|
||||
});
|
||||
this.searchview.on_loaded.add_last(function () {
|
||||
var $buttons = self.searchview.$element.find(".oe_search-view-buttons");
|
||||
$buttons.append(QWeb.render("Many2XSelectPopup.search.buttons"));
|
||||
var $nbutton = $buttons.find(".oe_many2xselectpopup-search-new");
|
||||
$nbutton.click(function() {
|
||||
self.new_object();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_many2xselectpopup-search-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
});
|
||||
self.view_list = new openerp.base.form.Many2XPopupListView( null, self.session,
|
||||
self.element_id + "_view_list", self.dataset, false);
|
||||
self.view_list.popup = self;
|
||||
self.view_list.do_show();
|
||||
self.view_list.start();
|
||||
var tmphack = {"loaded": false};
|
||||
self.view_list.on_loaded.add_last(function() {
|
||||
if ( !tmphack.loaded ) {
|
||||
self.view_list.do_reload();
|
||||
tmphack.loaded = true;
|
||||
};
|
||||
});
|
||||
});
|
||||
this.searchview.start();
|
||||
},
|
||||
on_select_element: function(element_id) {
|
||||
},
|
||||
new_object: function() {
|
||||
var self = this;
|
||||
this.searchview.hide();
|
||||
this.view_list.$element.hide();
|
||||
this.dataset.index = null;
|
||||
this.view_form = new openerp.base.FormView({}, this.session,
|
||||
this.element_id + "_view_form", this.dataset, false);
|
||||
this.view_form.start();
|
||||
this.view_form.on_loaded.add_last(function() {
|
||||
var $buttons = self.view_form.$element.find(".oe_form_buttons");
|
||||
$buttons.html(QWeb.render("Many2XSelectPopup.form.buttons"));
|
||||
var $nbutton = $buttons.find(".oe_many2xselectpopup-form-save");
|
||||
$nbutton.click(function() {
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_many2xselectpopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
});
|
||||
});
|
||||
this.view_form.on_created.add_last(function(r, success) {
|
||||
if (r.result) {
|
||||
var id = arguments[0].result;
|
||||
self.on_select_element(id);
|
||||
}
|
||||
});
|
||||
this.view_form.do_show();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.Many2XPopupListView = openerp.base.ListView.extend({
|
||||
switch_to_record: function(index) {
|
||||
this.popup.on_select_element(this.dataset.ids[index]);
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldReference = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
|
@ -966,6 +1181,17 @@ openerp.base.form.FieldReference = openerp.base.form.Field.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldImage = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldImage";
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('img').show().attr('src', 'data:image/png;base64,' + this.value);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Registry of form widgets, called by :js:`openerp.base.FormView`
|
||||
*/
|
||||
|
@ -992,7 +1218,8 @@ openerp.base.form.widgets = new openerp.base.Registry({
|
|||
'float' : 'openerp.base.form.FieldFloat',
|
||||
'integer': 'openerp.base.form.FieldFloat',
|
||||
'progressbar': 'openerp.base.form.FieldProgressBar',
|
||||
'float_time': 'openerp.base.form.FieldFloat'
|
||||
'float_time': 'openerp.base.form.FieldFloatTime',
|
||||
'image': 'openerp.base.form.FieldImage'
|
||||
});
|
||||
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
openerp.base.list = function (openerp) {
|
||||
openerp.base.views.add('list', 'openerp.base.ListView');
|
||||
openerp.base.ListView = openerp.base.Controller.extend(
|
||||
/** @lends openerp.base.ListView# */ {
|
||||
openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ {
|
||||
defaults: {
|
||||
// records can be selected one by one
|
||||
'selectable': true,
|
||||
|
@ -61,7 +60,11 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
columns: this.columns,
|
||||
rows: this.rows
|
||||
});
|
||||
$(this.list).bind({
|
||||
this.groups = new openerp.base.ListView.Groups({
|
||||
options: this.options,
|
||||
columns: this.columns
|
||||
});
|
||||
$([this.list, this.groups]).bind({
|
||||
'selected': function (e, selection) {
|
||||
self.$element.find('#oe-list-delete')
|
||||
.toggle(!!selection.length);
|
||||
|
@ -80,7 +83,7 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
id, self.do_reload);
|
||||
},
|
||||
'row_link': function (e, index) {
|
||||
self.switch_to_record(index);
|
||||
self.select_record(index);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -233,7 +236,7 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
* @param {Number|null} index the record index (in the current dataset) to switch to
|
||||
* @param {String} [view="form"] the view type to switch to
|
||||
*/
|
||||
switch_to_record:function (index, view) {
|
||||
select_record:function (index, view) {
|
||||
view = view || 'form';
|
||||
this.dataset.index = index;
|
||||
_.delay(_.bind(function () {
|
||||
|
@ -290,6 +293,14 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.context = results.context;
|
||||
self.dataset.domain = results.domain;
|
||||
if (results.group_by.length) {
|
||||
self.groups.datagroup = new openerp.base.DataGroup(
|
||||
self.session, self.dataset.model,
|
||||
results.domain, results.context,
|
||||
results.group_by);
|
||||
self.$element.html(self.groups.render());
|
||||
return;
|
||||
}
|
||||
return self.do_reload();
|
||||
});
|
||||
},
|
||||
|
@ -338,7 +349,7 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
*/
|
||||
do_add_record: function () {
|
||||
this.notification.notify('Add', "New record");
|
||||
this.switch_to_record(null);
|
||||
this.select_record(null);
|
||||
},
|
||||
/**
|
||||
* Handles deletion of all selected lines
|
||||
|
@ -349,10 +360,7 @@ openerp.base.ListView = openerp.base.Controller.extend(
|
|||
}
|
||||
// TODO: implement reorder (drag and drop rows)
|
||||
});
|
||||
_.extend(openerp.base.ListView.prototype, openerp.base.ActionExecutor);
|
||||
|
||||
openerp.base.ListView.List = Class.extend(
|
||||
/** @lends openerp.base.ListView.List# */{
|
||||
openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List# */{
|
||||
/**
|
||||
* List display for the ListView, handles basic DOM events and transforms
|
||||
* them in the relevant higher-level events, to which the list view (or
|
||||
|
@ -464,10 +472,54 @@ openerp.base.ListView.List = Class.extend(
|
|||
// drag and drop
|
||||
// editable?
|
||||
});
|
||||
|
||||
openerp.base.TreeView = openerp.base.Controller.extend({
|
||||
openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Groups# */{
|
||||
/**
|
||||
* Grouped display for the ListView. Handles basic DOM events and interacts
|
||||
* with the :js:class:`~openerp.base.DataGroup` bound to it.
|
||||
*
|
||||
* Provides events similar to those of
|
||||
* :js:class:`~openerp.base.ListView.List`
|
||||
*/
|
||||
init: function (opts) {
|
||||
this.options = opts.options;
|
||||
this.columns = opts.columns;
|
||||
this.datagroup = {};
|
||||
},
|
||||
make_level: function (datagroup) {
|
||||
var self = this, $root = $('<dl>');
|
||||
datagroup.list().then(function (list) {
|
||||
_(list).each(function (group, index) {
|
||||
var $title = $('<dt>')
|
||||
.text(group.grouped_on + ': ' + group.value + ' (' + group.length + ')')
|
||||
.appendTo($root);
|
||||
$title.click(function () {
|
||||
datagroup.get(index, function (new_dataset) {
|
||||
var $content = $('<ul>').appendTo(
|
||||
$('<dd>').insertAfter($title));
|
||||
new_dataset.read_slice([], null, null, function (records) {
|
||||
_(records).each(function (record) {
|
||||
$('<li>')
|
||||
.appendTo($content)
|
||||
.text(_(record).map(function (value, key) {
|
||||
return key + ': ' + value;
|
||||
}).join(', '));
|
||||
});
|
||||
});
|
||||
}, function (new_datagroup) {
|
||||
console.log(new_datagroup);
|
||||
$('<dd>')
|
||||
.insertAfter($title)
|
||||
.append(self.make_level(new_datagroup));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return $root;
|
||||
},
|
||||
render: function () {
|
||||
return this.make_level(this.datagroup);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
openerp.base.m2o = function(openerp){
|
||||
|
||||
openerp.base.m2o = openerp.base.Controller.extend({
|
||||
init: function(view_manager, element_id, model, dataset, session){
|
||||
this._super(element_id, model, dataset, session);
|
||||
|
||||
this.view_manager = view_manager
|
||||
this.session = session;
|
||||
this.element = element_id.find('input');
|
||||
this.dataset = dataset;
|
||||
var cache = {};
|
||||
var lastXhr;
|
||||
this.relation = model;
|
||||
this.result_ids = []
|
||||
var self = this
|
||||
|
||||
var $input = this.element.autocomplete({
|
||||
|
||||
source: function(request, response){
|
||||
var search_val = request.term;
|
||||
if (search_val in cache) {
|
||||
response(cache[search_val]);
|
||||
return;
|
||||
}
|
||||
//pass request to server
|
||||
lastXhr = self.dataset.name_search(search_val, function(obj, status, xhr){
|
||||
var result = obj.result
|
||||
var values = [];
|
||||
if (!result.length) {
|
||||
values.push({'value': 'Create...', id: 'create'})
|
||||
}
|
||||
|
||||
$.each(result, function(i, val){
|
||||
values.push({
|
||||
value: val[1],
|
||||
id: val[0],
|
||||
orig_val: val[1]
|
||||
});
|
||||
self.result_ids.push(result[i][0])
|
||||
});
|
||||
|
||||
if (values.length > 10) {
|
||||
values = values.slice(0, 10);
|
||||
values.push({'value': 'More...', id: 'more'})
|
||||
}
|
||||
//process response
|
||||
cache[search_val] = values;
|
||||
response(values);
|
||||
});
|
||||
return;
|
||||
},
|
||||
|
||||
select: function(event, ui){
|
||||
ui.item.value = ui.item.orig_val? ui.item.orig_val : self.element.data( "autocomplete" ).term
|
||||
if (ui.item.id == 'more') {
|
||||
self.dataset.ids = self.result_ids;
|
||||
self.dataset.count = self.dataset.ids.length;
|
||||
self.dataset.domain = []
|
||||
self.element.val('')
|
||||
var pop = new openerp.base.form.Many2XSelectPopup(null, self.session);
|
||||
pop.select_element(self.relation, self.dataset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ui.item.id == 'create') {
|
||||
var val = self.element.val()
|
||||
self.dataset.create({'name': ui.item.value},
|
||||
function(r){}, function(r){
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = jQuery('<div>',
|
||||
{'id': element_id
|
||||
}).dialog({
|
||||
modal: true,
|
||||
minWidth: 800
|
||||
});
|
||||
self.element.val('')
|
||||
var event_form = new openerp.base.FormView(self.view_manager, self.session, element_id, self.dataset, false);
|
||||
event_form.start();
|
||||
});
|
||||
$input.val(self.element.data( "autocomplete" ).term);
|
||||
return true;
|
||||
}
|
||||
self.element.attr('m2o_id', ui.item.id);
|
||||
},
|
||||
|
||||
minLength: 0,
|
||||
|
||||
focus: function(event, ui) {
|
||||
if (ui.item.id == ('create')) {
|
||||
return true;
|
||||
}
|
||||
ui.item.value = self.element.data("autocomplete").term.length ? self.element.val() + '[' + ui.item.orig_val.substring(self.element.data("autocomplete").term.length) + ']' : this.lastSearch
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
$("<div type='button' class='ui_combo'> </div>")
|
||||
.attr("tabIndex", -1)
|
||||
.attr("title", "Show All Items")
|
||||
.insertAfter($input)
|
||||
.button({
|
||||
icons: {
|
||||
primary: "ui-icon-triangle-1-s"
|
||||
},
|
||||
text: false
|
||||
})
|
||||
.removeClass("ui-corner-all")
|
||||
.addClass("ui-corner-right ui-button-icon")
|
||||
.click(function() {
|
||||
// close if already visible
|
||||
if ($input.autocomplete("widget").is(":visible")) {
|
||||
$input.autocomplete( "close" );
|
||||
return;
|
||||
}
|
||||
$(this).blur();
|
||||
$input.autocomplete("search", "" );
|
||||
$input.focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -121,7 +121,10 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
|||
'lines': lines,
|
||||
'defaults': this.defaults
|
||||
});
|
||||
this.$element.html(render);
|
||||
// We don't understand why the following commented line does not work in Chrome but
|
||||
// the non-commented line does. As far as we investigated, only God knows.
|
||||
//this.$element.html(render);
|
||||
jQuery(render).appendTo(this.$element);
|
||||
|
||||
var f = this.$element.find('form');
|
||||
this.$element.find('form')
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*---------------------------------------------------------
|
||||
* OpenERP base library
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base.view_tree = function(openerp) {
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
openerp.base.TreeView = openerp.base.Controller.extend({
|
||||
/**
|
||||
* Genuine tree view (the one displayed as a tree, not the list)
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Tree view');
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
|
@ -17,17 +17,22 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
/**
|
||||
* Process an action
|
||||
* Supported actions: act_window
|
||||
*
|
||||
* If the action contains a 'no_sidebar' key, the resulting view will never contain a sidebar.
|
||||
*/
|
||||
do_action: function(action) {
|
||||
var self = this;
|
||||
action.flags = _.extend({
|
||||
sidebar : true,
|
||||
search_view : true,
|
||||
new_window : false,
|
||||
toolbar : true,
|
||||
pager : true
|
||||
}, action.flags || {});
|
||||
// instantiate the right controllers by understanding the action
|
||||
switch (action.type) {
|
||||
case 'ir.actions.act_window':
|
||||
if (action.target == 'new') {
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = $('<div id="'+element_id+'"></div>');
|
||||
var dialog = $('<div id="' + element_id + '"></div>');
|
||||
dialog.dialog({
|
||||
title: action.name,
|
||||
modal: true,
|
||||
|
@ -37,18 +42,20 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
// When dialog is closed with ESC key or close manually, branch to act_window_close logic
|
||||
self.do_action({ type: 'ir.actions.act_window_close' });
|
||||
});
|
||||
var viewmanager = new openerp.base.ViewManagerAction(this.session, element_id, action, false);
|
||||
var viewmanager = new openerp.base.ViewManagerAction(this.session, element_id, action);
|
||||
viewmanager.start();
|
||||
this.dialog_stack.push(viewmanager);
|
||||
} else if (action.flags.new_window) {
|
||||
this.rpc("/base/session/save_session_action", { the_action : action}, function(key) {
|
||||
var url = window.location.protocol + "//" + window.location.host +
|
||||
window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url);
|
||||
});
|
||||
} else {
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
var sidebar = true;
|
||||
if(action.no_sidebar) {
|
||||
sidebar = false;
|
||||
}
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this.session, this.element_id, action, sidebar);
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this.session, this.element_id, action);
|
||||
this.viewmanager.start();
|
||||
}
|
||||
break;
|
||||
|
@ -63,63 +70,6 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Mixin for action-executing objects, provides handling of OpenERP actions to
|
||||
* all clients.
|
||||
*
|
||||
* Mix into existing classes via ``_.extend`` of the class's prototype.
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
openerp.base.ActionExecutor =
|
||||
/**
|
||||
* @lends openerp.base.ActionExecutor#
|
||||
*/ {
|
||||
/**
|
||||
* Fetches and executes the action identified by ``action_data``.
|
||||
*
|
||||
* @param {Object} action_data the action descriptor data
|
||||
* @param {String} action_data.name the action name, used to uniquely identify the action to find and execute it
|
||||
* @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``)
|
||||
* @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
|
||||
* @param {Object} [action_data.context=null] additional action context, to add to the current context
|
||||
* @param {openerp.base.DataSet} dataset a dataset object used to communicate with the server
|
||||
* @param {openerp.base.ActionManager} action_manager object able to actually execute the action, if any is fetched
|
||||
* @param {Number} [record_id] the identifier of the object on which the action is to be applied
|
||||
* @param {Function} on_no_action callback to execute if the action does not generate any result (no new action)
|
||||
*/
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_no_action) {
|
||||
var handler = function (r) {
|
||||
if (r.result && r.result.constructor == Object) {
|
||||
action_manager.do_action(r.result);
|
||||
} else {
|
||||
on_no_action(r.result);
|
||||
}
|
||||
};
|
||||
|
||||
if (action_data.special) {
|
||||
handler({
|
||||
result : { type: 'ir.actions.act_window_close' }
|
||||
});
|
||||
} else {
|
||||
var context = _.extend({}, dataset.context, action_data.context || {});
|
||||
switch(action_data.type) {
|
||||
case 'object':
|
||||
return dataset.call(action_data.name, [record_id], [context], handler);
|
||||
case 'action':
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10) }, handler);
|
||||
default:
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registry for all the main views
|
||||
*/
|
||||
openerp.base.views = new openerp.base.Registry();
|
||||
|
||||
openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, dataset, views) {
|
||||
this._super(session, element_id);
|
||||
|
@ -240,7 +190,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
|||
});
|
||||
|
||||
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
init: function(session, element_id, action, sidebar) {
|
||||
init: function(session, element_id, action) {
|
||||
var dataset;
|
||||
if(!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(session, action.res_model);
|
||||
|
@ -251,9 +201,9 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
|||
}
|
||||
this._super(session, element_id, dataset, action.views);
|
||||
this.action = action;
|
||||
this.sidebar = sidebar;
|
||||
if (sidebar)
|
||||
if (action.flags.sidebar) {
|
||||
this.sidebar = new openerp.base.Sidebar(null, this);
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
var inital_view_loaded = this._super();
|
||||
|
@ -275,17 +225,14 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
|||
// init search view
|
||||
var searchview_id = this.action.search_view_id && this.action.search_view_id[0];
|
||||
|
||||
if (searchview_id) {
|
||||
var searchview_loaded = this.setup_search_view(
|
||||
searchview_id, search_defaults);
|
||||
var searchview_loaded = this.setup_search_view(
|
||||
searchview_id || false, search_defaults);
|
||||
|
||||
// schedule auto_search
|
||||
if (this.action['auto_search']) {
|
||||
$.when(searchview_loaded, inital_view_loaded)
|
||||
.then(this.searchview.do_search);
|
||||
}
|
||||
// schedule auto_search
|
||||
if (searchview_loaded != null && this.action['auto_search']) {
|
||||
$.when(searchview_loaded, inital_view_loaded)
|
||||
.then(this.searchview.do_search);
|
||||
}
|
||||
|
||||
},
|
||||
stop: function() {
|
||||
// should be replaced by automatic destruction implemented in BaseWidget
|
||||
|
@ -349,7 +296,10 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
|||
var i = $this.attr("data-i");
|
||||
var j = $this.attr("data-j");
|
||||
var action = self.sections[i].elements[j];
|
||||
(new openerp.base.ExternalActionManager(self.view_manager.session, null)) .handle_action(action);
|
||||
action.flags = {
|
||||
new_window : true
|
||||
}
|
||||
self.session.action_manager.do_action(action);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
@ -360,89 +310,51 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.ExternalActionManager = openerp.base.Controller.extend({
|
||||
handle_action: function(action) {
|
||||
if(action.type=="ir.actions.act_window") {
|
||||
if(action.target=="new") {
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = $('<div id="'+element_id+'"></div>');
|
||||
dialog.dialog({
|
||||
title: action.name
|
||||
});
|
||||
var viewmanager = new openerp.base.ViewManagerAction(this.session ,element_id, action, false);
|
||||
viewmanager.start();
|
||||
} else if (action.target == "current") {
|
||||
this.rpc("/base/session/save_session_action", {the_action:action}, function(key) {
|
||||
var url = window.location.protocol + "//" + window.location.host +
|
||||
window.location.pathname + "?" + jQuery.param({s_action:""+key});
|
||||
window.open(url);
|
||||
});
|
||||
openerp.base.View = openerp.base.Controller.extend({
|
||||
/**
|
||||
* Fetches and executes the action identified by ``action_data``.
|
||||
*
|
||||
* @param {Object} action_data the action descriptor data
|
||||
* @param {String} action_data.name the action name, used to uniquely identify the action to find and execute it
|
||||
* @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``)
|
||||
* @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
|
||||
* @param {Object} [action_data.context=null] additional action context, to add to the current context
|
||||
* @param {openerp.base.DataSet} dataset a dataset object used to communicate with the server
|
||||
* @param {openerp.base.ActionManager} action_manager object able to actually execute the action, if any is fetched
|
||||
* @param {Number} [record_id] the identifier of the object on which the action is to be applied
|
||||
* @param {Function} on_no_action callback to execute if the action does not generate any result (no new action)
|
||||
*/
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_no_action) {
|
||||
var handler = function (r) {
|
||||
if (r.result && r.result.constructor == Object) {
|
||||
action_manager.do_action(r.result);
|
||||
} else {
|
||||
on_no_action(r.result);
|
||||
}
|
||||
};
|
||||
|
||||
if (action_data.special) {
|
||||
handler({
|
||||
result : { type: 'ir.actions.act_window_close' }
|
||||
});
|
||||
} else {
|
||||
var context = _.extend({}, dataset.context, action_data.context || {});
|
||||
switch(action_data.type) {
|
||||
case 'object':
|
||||
return dataset.call(action_data.name, [record_id], [context], handler);
|
||||
case 'action':
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10) }, handler);
|
||||
default:
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
}
|
||||
// TODO: show an error like "not implemented" here
|
||||
// since we don't currently have any way to handle errors do you have any better idea
|
||||
// than using todos?
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('calendar', 'openerp.base.CalendarView');
|
||||
openerp.base.CalendarView = openerp.base.Controller.extend({
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Calendar view');
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('gantt', 'openerp.base.GanttView');
|
||||
openerp.base.GanttView = openerp.base.Controller.extend({
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Gantt view');
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
openerp.base.TreeView = openerp.base.Controller.extend({
|
||||
/**
|
||||
* Genuine tree view (the one displayed as a tree, not the list)
|
||||
* Registry for all the main views
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Tree view');
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.views.add('graph', 'openerp.base.GraphView');
|
||||
openerp.base.GraphView = openerp.base.Controller.extend({
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Graph view');
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
}
|
||||
});
|
||||
openerp.base.views = new openerp.base.Registry();
|
||||
|
||||
openerp.base.ProcessView = openerp.base.Controller.extend({
|
||||
});
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="oe_login" class="login"></div>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%"
|
||||
t-att-class="'main_table' + (typeof kitten == 'undefined' ? '' : ' kitten-mode-activated')">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" class="main_table">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div id="oe_header" class="header"></div>
|
||||
|
@ -55,8 +54,7 @@
|
|||
</t>
|
||||
<t t-name="Header">
|
||||
<a href="/" class="company_logo_link">
|
||||
<img t-att-src="typeof kitten == 'undefined' ? '/base/static/src/img/logo.png' :
|
||||
'http://placekitten.com/g/179/46'" border="0" class="company_logo"/>
|
||||
<div class="company_logo" />
|
||||
</a>
|
||||
<h1 class="header_title" t-if="session.session_is_valid()">
|
||||
<span class="company">$company</span> - (<span class="database">$database</span>)<br/>
|
||||
|
@ -259,7 +257,7 @@
|
|||
<t t-foreach="row" t-as="td">
|
||||
<td t-att-colspan="td.colspan gt 1 ? td.colspan : undefined"
|
||||
t-att-width="td.width ? td.width : undefined"
|
||||
t-att-nowrap="td.is_field_label ? 'true' : undefined"
|
||||
t-att-nowrap="td.is_field_label or td.is_field_m2o? 'true' : undefined"
|
||||
t-att-valign="td.table ? 'top' : undefined"
|
||||
t-att-id="td.element_id"
|
||||
t-att-class="'oe_form_' + (td.is_field_label ? 'label' : (td.field ? 'field_' + td.type : td.type))"
|
||||
|
@ -306,6 +304,20 @@
|
|||
t-att-class="'field_' + widget.type" style="width: 100%"
|
||||
/>
|
||||
</t>
|
||||
<t t-name="FieldEmail">
|
||||
<table cellpadding="0" cellspacing="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td width="100%">
|
||||
<t t-call="FieldChar"/>
|
||||
</td>
|
||||
<td width="16">
|
||||
<button class="button" title="Send an e-mail with your default e-mail client">
|
||||
<img src="/base/static/src/img/icons/terp-mail-message-new.png"/>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="FieldText">
|
||||
<textarea rows="6" style="width: 100%;"
|
||||
t-att-name="widget.name"
|
||||
|
@ -320,13 +332,6 @@
|
|||
t-att-class="'field_' + widget.type"
|
||||
/>
|
||||
</t>
|
||||
<t t-name="FieldDatetime">
|
||||
<input type="text" style="width: 100%"
|
||||
t-att-name="widget.name"
|
||||
t-att-id="widget.element_id + '_field'"
|
||||
t-att-class="'field_' + widget.type"
|
||||
/>
|
||||
</t>
|
||||
<t t-name="FieldSelection">
|
||||
<select
|
||||
t-att-name="widget.name"
|
||||
|
@ -345,7 +350,9 @@
|
|||
t-att-name="widget.name"
|
||||
t-att-id="widget.element_id + '_field'"
|
||||
t-att-class="'field_' + widget.type"
|
||||
t-att-type="widget.type"
|
||||
style="width: 100%;"/>
|
||||
|
||||
</t>
|
||||
<t t-name="FieldOne2Many">
|
||||
<div t-att-id="widget.element_id">
|
||||
|
@ -369,6 +376,15 @@
|
|||
<span></span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldImage">
|
||||
<img align="left" border="1" style="display: none"
|
||||
t-att-id="widget.element_id + '_field'"
|
||||
t-att-name="widget.name"
|
||||
t-att-class="'field_' + widget.type"
|
||||
t-att-width="widget.node.attrs.img_width || widget.node.attrs.width"
|
||||
t-att-height="widget.node.attrs.img_height || widget.node.attrs.height"
|
||||
/>
|
||||
</t>
|
||||
<t t-name="WidgetButton">
|
||||
<button type="button"
|
||||
t-att-id="widget.element_id + '_button'"
|
||||
|
@ -382,7 +398,7 @@
|
|||
<h2 class="oe_view_title"><t t-esc="view.attrs['string']"/></h2>
|
||||
<form>
|
||||
<t t-call="SearchView.render_lines"/>
|
||||
<div style="text-align:right;">
|
||||
<div class="oe_search-view-buttons" style="text-align:right;">
|
||||
<input type="submit" value="Search"/>
|
||||
<input type="reset" value="Clear"/>
|
||||
</div>
|
||||
|
@ -418,7 +434,7 @@
|
|||
<span t-if="attrs.help">(?)</span>
|
||||
</label>
|
||||
<div style="white-space: nowrap;">
|
||||
<input type="text" t-att-name="attrs.name"
|
||||
<input type="text" size="15" t-att-name="attrs.name"
|
||||
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined"
|
||||
t-att-id="element_id"
|
||||
t-att-value="defaults[attrs.name] || ''"/>
|
||||
|
@ -490,9 +506,10 @@
|
|||
<t t-set="expand" t-value="false"/>
|
||||
<t t-set="label" t-value="'Custom Filters'"/>
|
||||
<t t-set="content">
|
||||
<div class="searchview_extended_groups_list"/>
|
||||
<div class="searchview_extended_groups_list">
|
||||
</div>
|
||||
<button class="searchview_extended_add_group"
|
||||
type="button">Add group of conditions</button>
|
||||
type="button"><span>Add group of conditions</span></button>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
@ -504,10 +521,10 @@
|
|||
<option value="none">None of the following conditions must match</option>
|
||||
</select>
|
||||
<button class="searchview_extended_delete_group"
|
||||
type="button">Delete this group of conditions</button>
|
||||
type="button"><span>Delete this group of conditions</span></button>
|
||||
<div class="searchview_extended_propositions_list">
|
||||
</div>
|
||||
<button class="searchview_extended_add_proposition" type="button">Add condition</button>
|
||||
<button class="searchview_extended_add_proposition" type="button"><span>Add condition</span></button>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.extended_search.proposition">
|
||||
|
@ -523,7 +540,7 @@
|
|||
<select class="searchview_extended_prop_op"/>
|
||||
<span class="searchview_extended_prop_value"/>
|
||||
<button class="searchview_extended_delete_prop"
|
||||
type="button">Delete this condition</button>
|
||||
type="button"><span>Delete this condition</span></button>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.extended_search.proposition.char">
|
||||
|
@ -544,12 +561,12 @@
|
|||
<a class="toggle-sidebar"></a>
|
||||
<div t-att-id="element_id" class="sidebar-sub-div">
|
||||
<div class="sidebar-displaying-div">
|
||||
<t t-set="i" t-value="0"/>
|
||||
<t t-set="i" t-value="1-1"/> <!-- al do stupid things -->
|
||||
<t t-foreach="sections" t-as="section">
|
||||
<t t-if="section.elements.length > 0">
|
||||
<h2><t t-esc="section.label"/></h2>
|
||||
<ul>
|
||||
<t t-set="j" t-value="0"/>
|
||||
<t t-set="j" t-value="1-1"/>
|
||||
<t t-foreach="section.elements" t-as="element">
|
||||
<li><a t-att-data-i="i" t-att-data-j="j" href="#"><t t-esc="element.name"/></a></li>
|
||||
<t t-set="j" t-value="j+1"/>
|
||||
|
@ -570,4 +587,19 @@
|
|||
</p>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup">
|
||||
<div t-att-id="element_id">
|
||||
<div t-att-id="element_id + '_search'"></div>
|
||||
<div t-att-id="element_id + '_view_list'"></div>
|
||||
<div t-att-id="element_id + '_view_form'"></div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup.search.buttons">
|
||||
<button type="button" class="oe_many2xselectpopup-search-new">New</button>
|
||||
<button type="button" class="oe_many2xselectpopup-search-close">Close</button>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup.form.buttons">
|
||||
<button type="button" class="oe_many2xselectpopup-form-save">Save</button>
|
||||
<button type="button" class="oe_many2xselectpopup-form-close">Close</button>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<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 src="/base/static/src/js/m2o.js"></script>
|
||||
<script src="/base/static/src/js/form.js"></script>
|
||||
<script src="/base/static/src/js/list.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
'static/src/js/web_chat.js'
|
||||
],
|
||||
"css": [],
|
||||
# 'active': True,
|
||||
'active': False,
|
||||
}
|
||||
|
|
|
@ -307,8 +307,6 @@ Javascript
|
|||
|
||||
:returns: the dataset's current active id
|
||||
|
||||
.. js:class:: openerp.base.DataRecord(session, model, fields, values)
|
||||
|
||||
Ad-hoc objects and structural types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -1,27 +1,3 @@
|
|||
[global]
|
||||
server.environment = "development"
|
||||
# Some server parameters that you may want to tweak
|
||||
server.socket_host = "0.0.0.0"
|
||||
server.socket_port = 8080
|
||||
# Sets the number of threads the server uses
|
||||
server.thread_pool = 10
|
||||
|
||||
tools.sessions.on = True
|
||||
tools.sessions.persistent = False
|
||||
|
||||
# logging
|
||||
#log.access_file = "/var/log/openerp-web/access.log"
|
||||
#log.error_file = "/var/log/openerp-web/error.log"
|
||||
log.access_level = "INFO"
|
||||
log.error_level = "INFO"
|
||||
|
||||
# OpenERP Server
|
||||
openerp.server.host = 'localhost'
|
||||
openerp.server.port = '8070'
|
||||
openerp.server.protocol = 'socket'
|
||||
openerp.server.timeout = 450
|
||||
|
||||
# Regex for dbname %{subdomain}s for the subdomain
|
||||
#openerp.web.database.list = "%{subdomain}s_.*"
|
||||
#openerp.web.database.manager = False
|
||||
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
""" We assume that, just like the OpenERP server, the python part of the client
|
||||
doesn't need to handle timezone-aware datetimes, this could be changed in the future. """
|
||||
|
||||
import datetime
|
||||
|
||||
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
|
||||
|
@ -32,31 +29,60 @@ DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
|
|||
DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
def parse_datetime(str):
|
||||
"""
|
||||
Converts a string to a datetime object using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
No timezone information is added, the datetime is a naive instance, but
|
||||
according to OpenERP 6.1 specification the timezone is always UTC.
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def parse_date(str):
|
||||
"""
|
||||
Converts a string to a date object using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
|
||||
|
||||
def parse_time(str):
|
||||
"""
|
||||
Converts a string to a time object using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
|
||||
|
||||
def format_datetime(obj):
|
||||
"""
|
||||
Converts a datetime object to a string using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
The datetime instance should not have an attached timezone and be in UTC.
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def format_date(obj):
|
||||
"""
|
||||
Converts a date object to a string using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
def format_time(obj):
|
||||
"""
|
||||
Converts a time object to a string using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
|
|
@ -500,30 +500,42 @@ def main(argv):
|
|||
# change the timezone of the program to the OpenERP server's assumed timezone
|
||||
os.environ["TZ"] = "UTC"
|
||||
|
||||
# Parse config
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("-p", "--port", dest="socket_port", help="listening port", metavar="NUMBER", default=8002)
|
||||
op.add_option("-s", "--session-path", dest="storage_path",
|
||||
help="directory used for session storage", metavar="DIR",
|
||||
default=os.path.join(tempfile.gettempdir(), "cpsessions"))
|
||||
(o, args) = op.parse_args(argv[1:])
|
||||
|
||||
# Prepare cherrypy config from options
|
||||
if not os.path.exists(o.storage_path):
|
||||
os.mkdir(o.storage_path, 0700)
|
||||
config = {
|
||||
'server.socket_port': int(o.socket_port),
|
||||
DEFAULT_CONFIG = {
|
||||
'server.socket_port': 8002,
|
||||
'server.socket_host': '0.0.0.0',
|
||||
#'server.thread_pool' = 10,
|
||||
'tools.sessions.on': True,
|
||||
'tools.sessions.storage_type': 'file',
|
||||
'tools.sessions.storage_path': o.storage_path,
|
||||
'tools.sessions.storage_path': os.path.join(tempfile.gettempdir(), "cpsessions"),
|
||||
'tools.sessions.timeout': 60
|
||||
}
|
||||
|
||||
# Parse config
|
||||
op = optparse.OptionParser()
|
||||
op.add_option("-p", "--port", dest="server.socket_port", help="listening port",
|
||||
type="int", metavar="NUMBER")
|
||||
op.add_option("-s", "--session-path", dest="tools.sessions.storage_path",
|
||||
help="directory used for session storage", metavar="DIR")
|
||||
(o, args) = op.parse_args(argv[1:])
|
||||
o = vars(o)
|
||||
for k in o.keys():
|
||||
if o[k] == None:
|
||||
del(o[k])
|
||||
|
||||
# Setup and run cherrypy
|
||||
cherrypy.tree.mount(Root())
|
||||
cherrypy.config.update(config)
|
||||
|
||||
cherrypy.config.update(config=DEFAULT_CONFIG)
|
||||
if os.path.exists(os.path.join(os.path.dirname(
|
||||
os.path.dirname(__file__)),'openerp-web.cfg')):
|
||||
cherrypy.config.update(os.path.join(os.path.dirname(
|
||||
os.path.dirname(__file__)),'openerp-web.cfg'))
|
||||
if os.path.exists(os.path.expanduser('~/.openerp_webrc')):
|
||||
cherrypy.config.update(os.path.expanduser('~/.openerp_webrc'))
|
||||
cherrypy.config.update(o)
|
||||
|
||||
if not os.path.exists(cherrypy.config['tools.sessions.storage_path']):
|
||||
os.mkdir(cherrypy.config['tools.sessions.storage_path'], 0700)
|
||||
|
||||
cherrypy.server.subscribe()
|
||||
cherrypy.engine.start()
|
||||
cherrypy.engine.block()
|
||||
|
|
Loading…
Reference in New Issue