[MERGE] from trunk
bzr revid: xmo@openerp.com-20110816142515-ohq33zvua5uq8cd3
This commit is contained in:
commit
ffae7cb4b3
13
.bzrignore
13
.bzrignore
|
@ -1,12 +1,11 @@
|
|||
RE:lib/(?!populate.sh).*
|
||||
.*
|
||||
*.egg-info
|
||||
*.orig
|
||||
bin/
|
||||
build/
|
||||
dist/
|
||||
include/
|
||||
RE:^bin/
|
||||
RE:^dist/
|
||||
RE:^include/
|
||||
|
||||
share/
|
||||
man/
|
||||
lib/
|
||||
RE:^share/
|
||||
RE:^man/
|
||||
RE:^lib/
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"static/lib/underscore/underscore.string.js",
|
||||
"static/src/js/boot.js",
|
||||
"static/src/js/core.js",
|
||||
"static/src/js/dates.js",
|
||||
"static/src/js/formats.js",
|
||||
"static/src/js/chrome.js",
|
||||
"static/src/js/views.js",
|
||||
"static/src/js/data.js",
|
||||
|
|
|
@ -18,6 +18,7 @@ import openerpweb
|
|||
import openerpweb.ast
|
||||
import openerpweb.nonliterals
|
||||
|
||||
from babel.messages.pofile import read_po
|
||||
|
||||
# Should move to openerpweb.Xml2Json
|
||||
class Xml2Json:
|
||||
|
@ -156,6 +157,43 @@ class WebClient(openerpweb.Controller):
|
|||
'css': css
|
||||
}
|
||||
return r
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def translations(self, req, mods, lang):
|
||||
lang_model = req.session.model('res.lang')
|
||||
ids = lang_model.search([("code", "=", lang)])
|
||||
if ids:
|
||||
lang_obj = lang_model.read(ids[0], ["direction", "date_format", "time_format",
|
||||
"grouping", "decimal_point", "thousands_sep"])
|
||||
else:
|
||||
lang_obj = None
|
||||
|
||||
if lang.count("_") > 0:
|
||||
separator = "_"
|
||||
else:
|
||||
separator = "@"
|
||||
langs = lang.split(separator)
|
||||
langs = [separator.join(langs[:x]) for x in range(1, len(langs) + 1)]
|
||||
|
||||
transs = {}
|
||||
for addon_name in mods:
|
||||
transl = {"messages":[]}
|
||||
transs[addon_name] = transl
|
||||
for l in langs:
|
||||
f_name = os.path.join(openerpweb.path_addons, addon_name, "po", l + ".po")
|
||||
if not os.path.exists(f_name):
|
||||
continue
|
||||
try:
|
||||
with open(f_name) as t_file:
|
||||
po = read_po(t_file)
|
||||
except:
|
||||
continue
|
||||
for x in po:
|
||||
if x.id and x.string:
|
||||
transl["messages"].append({'id': x.id, 'string': x.string})
|
||||
return {"modules": transs,
|
||||
"lang_parameters": lang_obj}
|
||||
|
||||
|
||||
class Database(openerpweb.Controller):
|
||||
_cp_path = "/base/database"
|
||||
|
@ -251,10 +289,12 @@ class Session(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def login(self, req, db, login, password):
|
||||
req.session.login(db, login, password)
|
||||
ctx = req.session.get_context()
|
||||
|
||||
return {
|
||||
"session_id": req.session_id,
|
||||
"uid": req.session._uid,
|
||||
"context": ctx
|
||||
}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
@ -390,10 +430,10 @@ def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
|||
Values = req.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, context)
|
||||
|
||||
return [(id, name, clean_action(action, req.session))
|
||||
return [(id, name, clean_action(action, req.session, context=context))
|
||||
for id, name, action in actions]
|
||||
|
||||
def clean_action(action, session):
|
||||
def clean_action(action, session, context=None):
|
||||
action.setdefault('flags', {})
|
||||
if action['type'] != 'ir.actions.act_window':
|
||||
return action
|
||||
|
@ -401,7 +441,7 @@ def clean_action(action, session):
|
|||
if isinstance(action.get('context'), basestring):
|
||||
action['context'] = eval(
|
||||
action['context'],
|
||||
session.evaluation_context()) or {}
|
||||
session.evaluation_context(context=context)) or {}
|
||||
|
||||
if isinstance(action.get('domain'), basestring):
|
||||
action['domain'] = eval(
|
||||
|
@ -559,6 +599,7 @@ class DataSet(openerpweb.Controller):
|
|||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
|
||||
context, domain = eval_context_and_domain(
|
||||
request.session, request.context, domain)
|
||||
|
||||
|
@ -581,9 +622,14 @@ class DataSet(openerpweb.Controller):
|
|||
}
|
||||
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, ids, fields=False):
|
||||
return self.do_search_read(request, model, ids, fields)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get(self, request, model, ids, fields=False):
|
||||
return self.do_get(request, model, ids, fields)
|
||||
|
||||
def do_get(self, request, model, ids, fields=False):
|
||||
""" Fetches and returns the records of the model ``model`` whose ids
|
||||
are in ``ids``.
|
||||
|
@ -668,6 +714,12 @@ class DataSet(openerpweb.Controller):
|
|||
Model = req.session.model(model)
|
||||
return Model.default_get(fields, req.session.eval_context(req.context))
|
||||
|
||||
@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
|
||||
|
@ -760,8 +812,8 @@ class View(openerpweb.Controller):
|
|||
""" Parses an arbitrary string containing a domain, transforms it
|
||||
to either a literal domain or a :class:`openerpweb.nonliterals.Domain`
|
||||
|
||||
:param domain: the domain to parse, if the domain is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param domain: the domain to parse, if the domain is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
|
@ -777,8 +829,8 @@ class View(openerpweb.Controller):
|
|||
""" Parses an arbitrary string containing a context, transforms it
|
||||
to either a literal context or a :class:`openerpweb.nonliterals.Context`
|
||||
|
||||
:param context: the context to parse, if the context is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param context: the context to parse, if the context is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
|
@ -1001,6 +1053,19 @@ class Action(openerpweb.Controller):
|
|||
return clean_action(req.session.model('ir.actions.server').run(
|
||||
[action_id], req.session.eval_context(req.context)), req.session)
|
||||
|
||||
class TreeView(View):
|
||||
_cp_path = "/base/treeview"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def load(self, req, model, view_id, toolbar=False):
|
||||
return self.fields_view_get(req, model, view_id, 'tree', toolbar=toolbar)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def action(self, req, model, id):
|
||||
return load_actions_from_ir_values(
|
||||
req,'action', 'tree_but_open',[(model, id)],
|
||||
False, req.session.eval_context(req.context))
|
||||
|
||||
def export_csv(fields, result):
|
||||
fp = StringIO()
|
||||
writer = csv.writer(fp, quoting=csv.QUOTE_ALL)
|
||||
|
@ -1213,4 +1278,3 @@ class Export(View):
|
|||
return export_xls(field, result)
|
||||
else:
|
||||
return export_csv(field, result)
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
||||
#: addons/base/static/src/js/form.js:1459
|
||||
msgid "<em> Search More...</em>"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/js/form.js:1472
|
||||
#, python-format
|
||||
msgid "<em> Create \"<strong>%s</strong>\"</em>"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/js/form.js:1478
|
||||
msgid "<em> Create and Edit...</em>"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# niv <nicolas.vanhoren@openerp.com>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-09 17:30+0200\n"
|
||||
"PO-Revision-Date: 2011-08-09 17:31+0200\n"
|
||||
"Last-Translator: niv <nicolas.vanhoren@openerp.com>\n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.4\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: addons/base/static/src/js/form.js:1459
|
||||
msgid "<em> Search More...</em>"
|
||||
msgstr "<em> Chercher plus...</em>"
|
||||
|
||||
#: addons/base/static/src/js/form.js:1472
|
||||
#, python-format
|
||||
msgid "<em> Create \"<strong>%s</strong>\"</em>"
|
||||
msgstr "<em> Créer \"<strong>%s</strong>\"</em>"
|
||||
|
||||
#: addons/base/static/src/js/form.js:1478
|
||||
msgid "<em> Create and Edit...</em>"
|
||||
msgstr "<em> Créer et éditer...</em>"
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
// TODO: trim support
|
||||
// TODO: line number -> https://bugzilla.mozilla.org/show_bug.cgi?id=618650
|
||||
// TODO: templates orverwritten could be called by t-call="__super__" ?
|
||||
// TODO: t-set + t-value + children node == scoped variable ?
|
||||
var QWeb2 = {
|
||||
expressions_cache: {},
|
||||
reserved_words: 'true,false,NaN,null,undefined,debugger,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','),
|
||||
|
@ -21,6 +23,11 @@ var QWeb2 = {
|
|||
}
|
||||
throw new Error(prefix + ": " + message);
|
||||
},
|
||||
warning : function(message) {
|
||||
if (typeof(window) !== 'undefined' && window.console) {
|
||||
window.console.warn(message);
|
||||
}
|
||||
},
|
||||
trim: function(s, mode) {
|
||||
switch (mode) {
|
||||
case "left":
|
||||
|
@ -638,6 +645,9 @@ QWeb2.Element = (function() {
|
|||
compile_action_set : function(value) {
|
||||
var variable = this.format_expression(value);
|
||||
if (this.actions['value']) {
|
||||
if (this.children.length) {
|
||||
this.engine.tools.warning("@set with @value plus node chidren found. Children are ignored.");
|
||||
}
|
||||
this.top(variable + " = (" + (this.format_expression(this.actions['value'])) + ");");
|
||||
this.process_children = false;
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//---------------------------------------------------------
|
||||
// OpenERP Web Boostrap
|
||||
//---------------------------------------------------------
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP Web Boostrap Code
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @name openerp
|
||||
|
@ -14,13 +14,8 @@
|
|||
|
||||
/** @lends openerp */
|
||||
var openerp = this.openerp = {
|
||||
/**
|
||||
* Debug flag turns on logging
|
||||
*/
|
||||
// debug flag
|
||||
debug: true,
|
||||
// element_ids registry linked to all controllers on the page
|
||||
// TODO rename to elements, or keep gtk naming?
|
||||
screen: {},
|
||||
// Per session namespace
|
||||
// openerp.<module> will map to
|
||||
// openerp.sessions.sessionname.<module> using a closure
|
||||
|
@ -40,8 +35,6 @@
|
|||
// this unique id will be replaced by hostname_databasename by
|
||||
// openerp.base.Connection on the first connection
|
||||
_session_id: "session" + session_counter++,
|
||||
screen: openerp.screen,
|
||||
sessions: openerp.sessions,
|
||||
base: {},
|
||||
web_mobile: {}
|
||||
};
|
||||
|
@ -51,16 +44,17 @@
|
|||
}
|
||||
return new_instance;
|
||||
}
|
||||
// TODO add initrpc to init core only for RPC
|
||||
};
|
||||
})();
|
||||
|
||||
//---------------------------------------------------------
|
||||
// OpenERP base module split
|
||||
//---------------------------------------------------------
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP Web base module split
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base = function(instance) {
|
||||
openerp.base.core(instance);
|
||||
openerp.base.dates(instance);
|
||||
openerp.base.formats(instance);
|
||||
openerp.base.chrome(instance);
|
||||
openerp.base.data(instance);
|
||||
if (openerp.base.views) {
|
||||
|
|
|
@ -1,287 +1,9 @@
|
|||
/*---------------------------------------------------------
|
||||
* OpenERP base library
|
||||
* OpenERP Web chrome
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base.chrome = function(openerp) {
|
||||
|
||||
openerp.base.Session = openerp.base.Widget.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(parent, element_id, server, port) {
|
||||
this._super(parent, element_id);
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = true;
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
this.shortcuts = [];
|
||||
this.active_id = null;
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* 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) {
|
||||
var self = this;
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).then(function () {deferred.resolve.apply(deferred, arguments);},
|
||||
function(error) {deferred.reject(error, $.Event());});
|
||||
return deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
self.on_rpc_error(error, event);
|
||||
}
|
||||
});
|
||||
}).then(success_callback, error_callback).promise();
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
self.on_rpc_response();
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Notification = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
|
@ -307,10 +29,10 @@ openerp.base.Notification = openerp.base.Widget.extend({
|
|||
openerp.base.Dialog = openerp.base.OldWidget.extend({
|
||||
dialog_title: "",
|
||||
identifier_prefix: 'dialog',
|
||||
init: function (parent, options) {
|
||||
init: function (parent, dialog_options) {
|
||||
var self = this;
|
||||
this._super(parent);
|
||||
this.options = {
|
||||
this.dialog_options = {
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
min_width: 0,
|
||||
|
@ -320,27 +42,25 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
|||
max_height: '100%',
|
||||
autoOpen: false,
|
||||
buttons: {},
|
||||
beforeClose: function () {
|
||||
self.on_close();
|
||||
}
|
||||
beforeClose: function () { self.on_close(); }
|
||||
};
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
this.options.buttons[f.substr(10)] = this[f];
|
||||
this.dialog_options.buttons[f.substr(10)] = this[f];
|
||||
}
|
||||
}
|
||||
if (options) {
|
||||
this.set_options(options);
|
||||
if (dialog_options) {
|
||||
this.set_options(dialog_options);
|
||||
}
|
||||
},
|
||||
set_options: function(options) {
|
||||
options = options || {};
|
||||
options.width = this.get_width(options.width || this.options.width);
|
||||
options.min_width = this.get_width(options.min_width || this.options.min_width);
|
||||
options.max_width = this.get_width(options.max_width || this.options.max_width);
|
||||
options.height = this.get_height(options.height || this.options.height);
|
||||
options.min_height = this.get_height(options.min_height || this.options.min_height);
|
||||
options.max_height = this.get_height(options.max_height || this.options.max_width);
|
||||
options.width = this.get_width(options.width || this.dialog_options.width);
|
||||
options.min_width = this.get_width(options.min_width || this.dialog_options.min_width);
|
||||
options.max_width = this.get_width(options.max_width || this.dialog_options.max_width);
|
||||
options.height = this.get_height(options.height || this.dialog_options.height);
|
||||
options.min_height = this.get_height(options.min_height || this.dialog_options.min_height);
|
||||
options.max_height = this.get_height(options.max_height || this.dialog_options.max_width);
|
||||
|
||||
if (options.width !== 'auto') {
|
||||
if (options.width > options.max_width) options.width = options.max_width;
|
||||
|
@ -353,7 +73,7 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
|||
if (!options.title && this.dialog_title) {
|
||||
options.title = this.dialog_title;
|
||||
}
|
||||
_.extend(this.options, options);
|
||||
_.extend(this.dialog_options, options);
|
||||
},
|
||||
get_width: function(val) {
|
||||
return this.get_size(val.toString(), $(window.top).width());
|
||||
|
@ -370,20 +90,18 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
|||
return parseInt(val, 10);
|
||||
}
|
||||
},
|
||||
start: function (auto_open) {
|
||||
this.$dialog = $('<div id="' + this.element_id + '"></div>').dialog(this.options);
|
||||
if (auto_open !== false) {
|
||||
this.open();
|
||||
}
|
||||
start: function () {
|
||||
this.$dialog = $('<div id="' + this.element_id + '"></div>').dialog(this.dialog_options);
|
||||
this._super();
|
||||
return this;
|
||||
},
|
||||
open: function(options) {
|
||||
open: function(dialog_options) {
|
||||
// TODO fme: bind window on resize
|
||||
if (this.template) {
|
||||
this.$element.html(this.render());
|
||||
}
|
||||
this.set_options(options);
|
||||
this.$dialog.dialog(this.options).dialog('open');
|
||||
this.set_options(dialog_options);
|
||||
this.$dialog.dialog(this.dialog_options).dialog('open');
|
||||
},
|
||||
close: function() {
|
||||
// Closes the dialog but leave it in a state where it could be opened again.
|
||||
|
@ -913,7 +631,7 @@ openerp.base.Header = openerp.base.Widget.extend({
|
|||
},
|
||||
|
||||
on_logout: function() {
|
||||
this.$element.find('#shortcuts ul li').remove();
|
||||
this.$element.find('.oe-shortcuts ul').empty();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1005,12 +723,10 @@ openerp.base.Homepage = openerp.base.Widget.extend({
|
|||
openerp.base.Preferences = openerp.base.Widget.extend({
|
||||
});
|
||||
|
||||
openerp.base.ImportExport = openerp.base.Widget.extend({
|
||||
});
|
||||
|
||||
openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
init: function(element_id) {
|
||||
this._super(null, element_id);
|
||||
openerp.webclient = this;
|
||||
|
||||
QWeb.add_template("/base/static/src/xml/base.xml");
|
||||
var params = {};
|
||||
|
@ -1019,10 +735,10 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
|||
}
|
||||
this.$element.html(QWeb.render("Interface", params));
|
||||
|
||||
this.session = new openerp.base.Session(this,"oe_errors");
|
||||
this.session = new openerp.base.Session();
|
||||
this.loading = new openerp.base.Loading(this,"oe_loading");
|
||||
this.crashmanager = new openerp.base.CrashManager(this);
|
||||
this.crashmanager.start(false);
|
||||
this.crashmanager.start();
|
||||
|
||||
// Do you autorize this ? will be replaced by notify() in controller
|
||||
openerp.base.Widget.prototype.notification = new openerp.base.Notification(this, "oe_notification");
|
||||
|
@ -1038,8 +754,6 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
|||
this.menu = new openerp.base.Menu(this, "oe_menu", "oe_secondary_menu");
|
||||
this.menu.on_action.add(this.on_menu_action);
|
||||
this.header.on_action.add(this.on_menu_action);
|
||||
|
||||
|
||||
},
|
||||
start: function() {
|
||||
this.session.start();
|
||||
|
@ -1049,8 +763,10 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
|||
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
|
||||
},
|
||||
on_logged: function() {
|
||||
this.action_manager = new openerp.base.ActionManager(this, "oe_app");
|
||||
this.action_manager.start();
|
||||
if(this.action_manager)
|
||||
this.action_manager.stop();
|
||||
this.action_manager = new openerp.base.ActionManager(this);
|
||||
this.action_manager.appendTo($("#oe_app"));
|
||||
|
||||
// if using saved actions, load the action and give it to action manager
|
||||
var parameters = jQuery.deparam(jQuery.param.querystring());
|
||||
|
@ -1090,7 +806,8 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
|||
self.execute_home_action(home_action[0], ds);
|
||||
})
|
||||
},
|
||||
default_home: function () { },
|
||||
default_home: function () {
|
||||
},
|
||||
/**
|
||||
* Bundles the execution of the home action
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*---------------------------------------------------------
|
||||
* OpenERP controller framework
|
||||
* OpenERP Web core
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
openerp.base.core = function(openerp) {
|
||||
|
@ -305,16 +305,8 @@ openerp.base.Registry = openerp.base.Class.extend( /** @lends openerp.base.Regis
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Utility class that any class is allowed to extend to easy common manipulations.
|
||||
*
|
||||
* It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a
|
||||
* logging facility.
|
||||
*/
|
||||
openerp.base.SessionAware = openerp.base.Class.extend({
|
||||
init: function(session) {
|
||||
this.session = session;
|
||||
|
||||
openerp.base.CallbackEnabled = openerp.base.Class.extend({
|
||||
init: function() {
|
||||
// Transform on_* method into openerp.base.callbacks
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
|
@ -325,6 +317,19 @@ openerp.base.SessionAware = openerp.base.Class.extend({
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Utility class that any class is allowed to extend to easy common manipulations.
|
||||
*
|
||||
* It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a
|
||||
* logging facility.
|
||||
*/
|
||||
openerp.base.SessionAware = openerp.base.CallbackEnabled.extend({
|
||||
init: function(session) {
|
||||
this._super();
|
||||
this.session = session;
|
||||
},
|
||||
/**
|
||||
* Performs a JSON-RPC call
|
||||
|
@ -373,59 +378,6 @@ openerp.base.SessionAware = openerp.base.Class.extend({
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Base class for all visual components. Provides a lot of functionalities helpful
|
||||
* for the management of a part of the DOM.
|
||||
*
|
||||
* Widget handles:
|
||||
* - Rendering with QWeb.
|
||||
* - Life-cycle management and parenting (when a parent is destroyed, all its children are
|
||||
* destroyed too).
|
||||
* - Insertion in DOM.
|
||||
*
|
||||
* Widget also extends SessionAware for ease of use.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = openerp.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
* // identifier prefix, it is useful to put an obvious one for debugging
|
||||
* identifier_prefix: 'my-id-prefix-',
|
||||
*
|
||||
* init: function(parent) {
|
||||
* this._super(parent);
|
||||
* // stuff that you want to init before the rendering
|
||||
* },
|
||||
* start: function() {
|
||||
* this._super();
|
||||
* // stuff you want to make after the rendering, `this.$element` holds a correct value
|
||||
* this.$element.find(".my_button").click(/* an example of event binding * /);
|
||||
*
|
||||
* // if you have some asynchronous operations, it's a good idea to return
|
||||
* // a promise in start()
|
||||
* var promise = this.rpc(...);
|
||||
* return promise;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Now this class can simply be used with the following syntax:
|
||||
*
|
||||
* var my_widget = new MyWidget(this);
|
||||
* my_widget.appendTo($(".some-div"));
|
||||
*
|
||||
* With these two lines, the MyWidget instance was inited, rendered, it was inserted into the
|
||||
* DOM inside the ".some-div" div and its events were binded.
|
||||
*
|
||||
* And of course, when you don't need that widget anymore, just do:
|
||||
*
|
||||
* my_widget.stop();
|
||||
*
|
||||
* That will kill the widget in a clean way and erase its content from the dom.
|
||||
*/
|
||||
openerp.base.Widget = openerp.base.SessionAware.extend({
|
||||
/**
|
||||
* The name of the QWeb template that will be used for rendering. Must be
|
||||
|
@ -574,6 +526,18 @@ openerp.base.Widget = openerp.base.SessionAware.extend({
|
|||
}
|
||||
return false;
|
||||
},
|
||||
do_notify: function() {
|
||||
if (this.widget_parent) {
|
||||
return this.widget_parent.do_notify.apply(this,arguments);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
do_warn: function() {
|
||||
if (this.widget_parent) {
|
||||
return this.widget_parent.do_warn.apply(this,arguments);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
rpc: function(url, data, success, error) {
|
||||
var def = $.Deferred().then(success, error);
|
||||
var self = this;
|
||||
|
@ -599,5 +563,345 @@ openerp.base.OldWidget = openerp.base.Widget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.TranslationDataBase = openerp.base.Class.extend({
|
||||
init: function() {
|
||||
this.db = {};
|
||||
this.parameters = {"direction": 'ltr',
|
||||
"date_format": '%m/%d/%Y',
|
||||
"time_format": '%H:%M:%S',
|
||||
"grouping": "[]",
|
||||
"decimal_point": ".",
|
||||
"thousands_sep": ","};
|
||||
},
|
||||
set_bundle: function(translation_bundle) {
|
||||
var self = this;
|
||||
this.db = {};
|
||||
var modules = _.keys(translation_bundle.modules).sort();
|
||||
if (_.include(modules, "base")) {
|
||||
modules = ["base"].concat(_.without(modules, "base"));
|
||||
}
|
||||
_.each(modules, function(name) {
|
||||
self.add_module_translation(translation_bundle.modules[name]);
|
||||
});
|
||||
if (translation_bundle.lang_parameters) {
|
||||
this.parameters = translation_bundle.lang_parameters;
|
||||
}
|
||||
},
|
||||
add_module_translation: function(mod) {
|
||||
var self = this;
|
||||
_.each(mod.messages, function(message) {
|
||||
if (self.db[message.id] === undefined) {
|
||||
self.db[message.id] = message.string;
|
||||
}
|
||||
});
|
||||
},
|
||||
build_translation_function: function() {
|
||||
var self = this;
|
||||
var fcnt = function(str) {
|
||||
var tmp = self.get(str);
|
||||
return tmp === undefined ? str : tmp;
|
||||
}
|
||||
fcnt.database = this;
|
||||
return fcnt;
|
||||
},
|
||||
get: function(key) {
|
||||
if (this.db[key])
|
||||
return this.db[key];
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base._t = new openerp.base.TranslationDataBase().build_translation_function();
|
||||
|
||||
openerp.base.Session = openerp.base.CallbackEnabled.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(server, port) {
|
||||
this._super();
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = true;
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.user_context= {};
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
this.shortcuts = [];
|
||||
this.active_id = null;
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* 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) {
|
||||
var self = this;
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).then(function () {deferred.resolve.apply(deferred, arguments);},
|
||||
function(error) {deferred.reject(error, $.Event());});
|
||||
return deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
self.on_rpc_error(error, event);
|
||||
}
|
||||
});
|
||||
}).then(success_callback, error_callback).promise();
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
self.on_rpc_response();
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.user_context = result.context;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
this.user_context = this.get_cookie("user_context");
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
this.set_cookie('user_context', this.user_context);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var lang = self.user_context.lang;
|
||||
self.rpc('/base/webclient/translations',{
|
||||
mods: ["base"].concat(result),
|
||||
lang: lang})
|
||||
.then(function(transs) {
|
||||
openerp.base._t.database.set_bundle(transs);
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -268,9 +268,13 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
},
|
||||
/**
|
||||
* Read records.
|
||||
*
|
||||
* @param {Array} ids identifiers of the records to read
|
||||
* @param {Array} fields fields to read and return, by default all fields are returned
|
||||
* @param {Function} callback function called with read result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_ids: function (ids, fields, callback) {
|
||||
var self = this;
|
||||
return this.rpc('/base/dataset/get', {
|
||||
model: this.model,
|
||||
ids: ids,
|
||||
|
@ -282,13 +286,20 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
* Read a slice of the records represented by this DataSet, based on its
|
||||
* domain and context.
|
||||
*
|
||||
* @param {Number} [offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [limit=null] The maximum number of records to return
|
||||
* @params {Object} options
|
||||
* @param {Array} [options.fields] fields to read and return, by default all fields are returned
|
||||
* @param {Number} [options.offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [options.limit=null] The maximum number of records to return
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
},
|
||||
read_slice: function (options, callback) { return null; },
|
||||
/**
|
||||
* Read the indexed record.
|
||||
* Reads the current dataset record (from its index)
|
||||
*
|
||||
* @params {Array} [fields] fields to read and return, by default all fields are returned
|
||||
* @params {Function} callback function called with read_index result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_index: function (fields, callback) {
|
||||
var def = $.Deferred().then(callback);
|
||||
|
@ -304,6 +315,13 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
}
|
||||
return def.promise();
|
||||
},
|
||||
/**
|
||||
* Reads default values for the current model
|
||||
*
|
||||
* @param {Array} [fields] fields to get default values for, by default all defaults are read
|
||||
* @param {Function} callback function called with default_get result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
default_get: function(fields, callback) {
|
||||
return this.rpc('/base/dataset/default_get', {
|
||||
model: this.model,
|
||||
|
@ -311,6 +329,14 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
context: this.get_context()
|
||||
}, callback);
|
||||
},
|
||||
/**
|
||||
* Creates a new record in db
|
||||
*
|
||||
* @param {Object} data field values to set on the new record
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of creation error
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
create: function(data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/create', {
|
||||
model: this.model,
|
||||
|
@ -318,6 +344,15 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
context: this.get_context()
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Saves the provided data in an existing db record
|
||||
*
|
||||
* @param {Number|String} id identifier for the record to alter
|
||||
* @param {Object} data field values to write into the record
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of write error
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
write: function (id, data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/save', {
|
||||
model: this.model,
|
||||
|
@ -326,11 +361,27 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
context: this.get_context()
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Deletes an existing record from the database
|
||||
*
|
||||
* @param {Number|String} ids identifier of the record to delete
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of deletion error
|
||||
*/
|
||||
unlink: function(ids, callback, error_callback) {
|
||||
var self = this;
|
||||
return this.call_and_eval("unlink", [ids, this.get_context()], null, 1,
|
||||
callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls an arbitrary RPC method
|
||||
*
|
||||
* @param {String} method name of the method (on the current model) to call
|
||||
* @param {Array} [args] arguments to pass to the method
|
||||
* @param {Function} callback
|
||||
* @param {Function} error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call: function (method, args, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call', {
|
||||
model: this.model,
|
||||
|
@ -338,6 +389,17 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls an arbitrary method, with more crazy
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {Array} [args]
|
||||
* @param {Number} [domain_id] index of a domain to evaluate in the args array
|
||||
* @param {Number} [context_id] index of a context to evaluate in the args array
|
||||
* @param {Function} callback
|
||||
* @param {Function }error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call_and_eval: function (method, args, domain_id, context_id, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call', {
|
||||
model: this.model,
|
||||
|
@ -347,6 +409,15 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls a button method, usually returning some sort of action
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {Array} [args]
|
||||
* @param {Function} callback
|
||||
* @param {Function} error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call_button: function (method, args, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call_button', {
|
||||
model: this.model,
|
||||
|
@ -356,17 +427,34 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Fetches the "readable name" for records, based on intrinsic rules
|
||||
*
|
||||
* @param {Array} ids
|
||||
* @param {Function} callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
name_get: function(ids, callback) {
|
||||
return this.call_and_eval('name_get', [ids, this.get_context()], null, 1, callback);
|
||||
},
|
||||
/*
|
||||
* args = domain
|
||||
/**
|
||||
*
|
||||
* @param {String} name name to perform a search for/on
|
||||
* @param {Array} [domain=[]] filters for the objects returned, OpenERP domain
|
||||
* @param {String} [operator='ilike'] matching operator to use with the provided name value
|
||||
* @param {Number} [limit=100] maximum number of matches to return
|
||||
* @param {Function} callback function to call with name_search result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
name_search: function (name, args, operator, limit, callback) {
|
||||
name_search: function (name, domain, operator, limit, callback) {
|
||||
return this.call_and_eval('name_search',
|
||||
[name || '', args || false, operator || 'ilike', this.get_context(), limit || 100],
|
||||
[name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100],
|
||||
1, 3, callback);
|
||||
},
|
||||
/**
|
||||
* @param name
|
||||
* @param callback
|
||||
*/
|
||||
name_create: function(name, callback) {
|
||||
return this.call_and_eval('name_create', [name, this.get_context()], null, 1, callback);
|
||||
},
|
||||
|
@ -377,7 +465,10 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
signal: signal
|
||||
}, callback);
|
||||
},
|
||||
get_context: function() {
|
||||
get_context: function(request_context) {
|
||||
if (request_context) {
|
||||
return new openerp.base.CompoundContext(this.context, request_context);
|
||||
}
|
||||
return this.context;
|
||||
}
|
||||
});
|
||||
|
@ -387,9 +478,11 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
|||
// all local records
|
||||
this.ids = ids || [];
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
var self = this;
|
||||
offset = offset || 0;
|
||||
read_slice: function (options, callback) {
|
||||
var self = this,
|
||||
offset = options.offset || 0,
|
||||
limit = options.limit || false,
|
||||
fields = options.fields || false;
|
||||
var end_pos = limit && limit !== -1 ? offset + limit : undefined;
|
||||
return this.read_ids(this.ids.slice(offset, end_pos), fields, callback);
|
||||
},
|
||||
|
@ -426,25 +519,30 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
|||
// is it necessary ?
|
||||
this.ids = [];
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
/**
|
||||
* Read a slice of the records represented by this DataSet, based on its
|
||||
* domain and context.
|
||||
*
|
||||
* @params {Object} options
|
||||
* @param {Array} [options.fields] fields to read and return, by default all fields are returned
|
||||
* @param {Object} [options.context] context data to add to the request payload, on top of the DataSet's own context
|
||||
* @param {Array} [options.domain] domain data to add to the request payload, ANDed with the dataset's domain
|
||||
* @param {Number} [options.offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [options.limit=null] The maximum number of records to return
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (options, callback) {
|
||||
var self = this;
|
||||
offset = offset || 0;
|
||||
// cached search, not sure it's a good idea
|
||||
if(this.offset <= offset) {
|
||||
var start = offset - this.offset;
|
||||
if(this.ids.length - start >= limit) {
|
||||
// TODO: check if this could work do only read if possible
|
||||
// return read_ids(ids.slice(start,start+limit),fields,callback)
|
||||
}
|
||||
}
|
||||
var offset = options.offset || 0;
|
||||
return this.rpc('/base/dataset/search_read', {
|
||||
model: this.model,
|
||||
fields: fields,
|
||||
domain: this.domain,
|
||||
context: this.get_context(),
|
||||
fields: options.fields || false,
|
||||
domain: this.get_domain(options.domain),
|
||||
context: this.get_context(options.context),
|
||||
sort: this.sort(),
|
||||
offset: offset,
|
||||
limit: limit
|
||||
limit: options.limit || false
|
||||
}, function (result) {
|
||||
self.ids = result.ids;
|
||||
self.offset = offset;
|
||||
|
@ -453,6 +551,12 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
|||
}
|
||||
});
|
||||
},
|
||||
get_domain: function (other_domain) {
|
||||
if (other_domain) {
|
||||
return new openerp.base.CompoundDomain(this.domain, other_domain);
|
||||
}
|
||||
return this.domain;
|
||||
},
|
||||
/**
|
||||
* Reads or changes sort criteria on the dataset.
|
||||
*
|
||||
|
@ -628,48 +732,51 @@ openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({
|
|||
on_unlink: function(ids) {}
|
||||
});
|
||||
|
||||
openerp.base.CompoundContext = function() {
|
||||
this.__ref = "compound_context";
|
||||
this.__contexts = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.add = function(context) {
|
||||
this.__contexts.push(context);
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.set_eval_context = function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.get_eval_context = function() {
|
||||
return this.__eval_context;
|
||||
};
|
||||
|
||||
openerp.base.CompoundDomain = function() {
|
||||
this.__ref = "compound_domain";
|
||||
this.__domains = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.add = function(domain) {
|
||||
this.__domains.push(domain);
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.set_eval_context = function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.get_eval_context = function() {
|
||||
return this.__eval_context;
|
||||
};
|
||||
openerp.base.CompoundContext = openerp.base.Class.extend({
|
||||
init: function () {
|
||||
this.__ref = "compound_context";
|
||||
this.__contexts = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
},
|
||||
add: function (context) {
|
||||
this.__contexts.push(context);
|
||||
return this;
|
||||
},
|
||||
set_eval_context: function (eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
},
|
||||
get_eval_context: function () {
|
||||
return this.__eval_context;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.CompoundDomain = openerp.base.Class.extend({
|
||||
init: function () {
|
||||
this.__ref = "compound_domain";
|
||||
this.__domains = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
},
|
||||
add: function(domain) {
|
||||
this.__domains.push(domain);
|
||||
return this;
|
||||
},
|
||||
set_eval_context: function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
},
|
||||
get_eval_context: function() {
|
||||
return this.__eval_context;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
|
||||
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;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
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;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
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;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Just a simple function to add some '0' if an integer it too small.
|
||||
*/
|
||||
var fts = function(str, size) {
|
||||
str = "" + str;
|
||||
var to_add = "";
|
||||
_.each(_.range(size - str.length), function() {
|
||||
to_add = to_add + "0";
|
||||
});
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getUTCFullYear(),4) + "-" + fts(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ fts(obj.getUTCDate(),2) + " " + fts(obj.getUTCHours(),2) + ":"
|
||||
+ 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) {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getHours(),2) + ":" + fts(obj.getMinutes(),2) + ":"
|
||||
+ fts(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
};
|
|
@ -1,4 +1,6 @@
|
|||
openerp.base.form = function (openerp) {
|
||||
|
||||
var _t = openerp.base._t;
|
||||
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{
|
||||
|
@ -19,7 +21,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
|||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.set_default_options(options);
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
@ -36,7 +38,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
|||
this.registry = openerp.base.form.widgets;
|
||||
this.has_been_loaded = $.Deferred();
|
||||
this.$form_header = null;
|
||||
this.options = options || {};
|
||||
_.defaults(this.options, {"always_show_new_button": true});
|
||||
},
|
||||
start: function() {
|
||||
|
@ -156,7 +157,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
|||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
}
|
||||
if (this.default_focus_field) {
|
||||
if (this.default_focus_field && !this.embedded_view) {
|
||||
this.default_focus_field.focus();
|
||||
}
|
||||
},
|
||||
|
@ -452,12 +453,14 @@ openerp.base.form.SidebarAttachments = openerp.base.Widget.extend({
|
|||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[
|
||||
['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]
|
||||
])).read_slice(
|
||||
{fields: ['name', 'url', 'type']},
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
|
@ -511,36 +514,40 @@ openerp.base.form.compute_domain = function(expr, fields) {
|
|||
}
|
||||
}
|
||||
|
||||
var field = fields[ex[0]].get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
|
||||
var field = fields[ex[0]];
|
||||
if (!field) {
|
||||
throw new Error("Domain references unknown field : " + ex[0]);
|
||||
}
|
||||
var field_value = field.get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
|
||||
var op = ex[1];
|
||||
var val = ex[2];
|
||||
|
||||
switch (op.toLowerCase()) {
|
||||
case '=':
|
||||
case '==':
|
||||
stack.push(field == val);
|
||||
stack.push(field_value == val);
|
||||
break;
|
||||
case '!=':
|
||||
case '<>':
|
||||
stack.push(field != val);
|
||||
stack.push(field_value != val);
|
||||
break;
|
||||
case '<':
|
||||
stack.push(field < val);
|
||||
stack.push(field_value < val);
|
||||
break;
|
||||
case '>':
|
||||
stack.push(field > val);
|
||||
stack.push(field_value > val);
|
||||
break;
|
||||
case '<=':
|
||||
stack.push(field <= val);
|
||||
stack.push(field_value <= val);
|
||||
break;
|
||||
case '>=':
|
||||
stack.push(field >= val);
|
||||
stack.push(field_value >= val);
|
||||
break;
|
||||
case 'in':
|
||||
stack.push(_(val).contains(field));
|
||||
stack.push(_(val).contains(field_value));
|
||||
break;
|
||||
case 'not in':
|
||||
stack.push(!_(val).contains(field));
|
||||
stack.push(!_(val).contains(field_value));
|
||||
break;
|
||||
default:
|
||||
this.log("Unsupported operator in modifiers :", op);
|
||||
|
@ -679,6 +686,16 @@ openerp.base.form.WidgetNotebook = openerp.base.form.Widget.extend({
|
|||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.tabs();
|
||||
this.view.on_button_new.add_last(this.do_select_first_visible_tab);
|
||||
},
|
||||
do_select_first_visible_tab: function() {
|
||||
for (var i = 0; i < this.pages.length; i++) {
|
||||
var page = this.pages[i];
|
||||
if (page.invisible === false) {
|
||||
this.$element.tabs('select', page.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -696,8 +713,8 @@ openerp.base.form.WidgetNotebookPage = openerp.base.form.WidgetFrame.extend({
|
|||
this.$element_tab = $('#' + this.element_tab_id);
|
||||
},
|
||||
update_dom: function() {
|
||||
if (this.invisible) {
|
||||
this.notebook.$element.tabs('select', 0);
|
||||
if (this.invisible && this.index === this.notebook.$element.tabs('option', 'selected')) {
|
||||
this.notebook.do_select_first_visible_tab();
|
||||
}
|
||||
this.$element_tab.toggle(!this.invisible);
|
||||
this.$element.toggle(!this.invisible);
|
||||
|
@ -758,8 +775,7 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
|||
var self = this;
|
||||
|
||||
this.view.execute_action(
|
||||
this.node.attrs, this.view.dataset, this.session.action_manager,
|
||||
this.view.datarecord.id, function () {
|
||||
this.node.attrs, this.view.dataset, this.view.datarecord.id, function () {
|
||||
self.view.reload();
|
||||
});
|
||||
}
|
||||
|
@ -794,7 +810,7 @@ openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({
|
|||
var self = this;
|
||||
this.$element.find("label").dblclick(function() {
|
||||
var widget = self['for'] || self;
|
||||
console.log(widget.element_id , widget);
|
||||
self.log(widget.element_id , widget);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1306,7 +1322,7 @@ openerp.base.form.dialog = function(content, options) {
|
|||
}, options || {});
|
||||
options.autoOpen = true;
|
||||
var dialog = new openerp.base.Dialog(null, options);
|
||||
dialog.$dialog = $(content).dialog(dialog.options);
|
||||
dialog.$dialog = $(content).dialog(dialog.dialog_options);
|
||||
return dialog.$dialog;
|
||||
}
|
||||
|
||||
|
@ -1440,7 +1456,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
// search more... if more results that max
|
||||
if (values.length > self.limit) {
|
||||
values = values.slice(0, self.limit);
|
||||
values.push({label: "<em> Search More...</em>", action: function() {
|
||||
values.push({label: _t("<em> Search More...</em>"), action: function() {
|
||||
dataset.name_search(search_val, self.build_domain(), 'ilike'
|
||||
, false, function(data) {
|
||||
self._change_int_value(null);
|
||||
|
@ -1453,13 +1469,13 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
if (search_val.length > 0 &&
|
||||
!_.include(raw_result, search_val) &&
|
||||
(!self.value || search_val !== self.value[1])) {
|
||||
values.push({label: '<em> Create "<strong>' +
|
||||
$('<span />').text(search_val).html() + '</strong>"</em>', action: function() {
|
||||
values.push({label: _.sprintf(_t('<em> Create "<strong>%s</strong>"</em>'),
|
||||
$('<span />').text(search_val).html()), action: function() {
|
||||
self._quick_create(search_val);
|
||||
}});
|
||||
}
|
||||
// create...
|
||||
values.push({label: "<em> Create and Edit...</em>", action: function() {
|
||||
values.push({label: _t("<em> Create and Edit...</em>"), action: function() {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("form", undefined, {"default_name": search_val});
|
||||
}});
|
||||
|
@ -1492,7 +1508,6 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
var dataset = new openerp.base.DataSetStatic(self, self.field.relation, self.build_context());
|
||||
dataset.name_get([element_ids[0]], function(data) {
|
||||
self._change_int_ext_value(data[0]);
|
||||
pop.stop();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -1624,20 +1639,22 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
|||
modes = !!modes ? modes.split(",") : ["tree", "form"];
|
||||
var views = [];
|
||||
_.each(modes, function(mode) {
|
||||
var view = {view_id: false, view_type: mode == "tree" ? "list" : mode};
|
||||
var view = {
|
||||
view_id: false,
|
||||
view_type: mode == "tree" ? "list" : mode,
|
||||
options: { sidebar : false }
|
||||
};
|
||||
if (self.field.views && self.field.views[mode]) {
|
||||
view.embedded_view = self.field.views[mode];
|
||||
}
|
||||
if(view.view_type === "list") {
|
||||
view.options = {
|
||||
'selectable': self.multi_selection
|
||||
};
|
||||
view.options.selectable = self.multi_selection;
|
||||
}
|
||||
views.push(view);
|
||||
});
|
||||
this.views = views;
|
||||
|
||||
this.viewmanager = new openerp.base.ViewManager(this, this.element_id, this.dataset, views);
|
||||
this.viewmanager = new openerp.base.ViewManager(this, this.dataset, views);
|
||||
this.viewmanager.registry = openerp.base.views.clone({
|
||||
list: 'openerp.base.form.One2ManyListView',
|
||||
form: 'openerp.base.form.One2ManyFormView'
|
||||
|
@ -1663,7 +1680,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
|||
self.save_form_view();
|
||||
});
|
||||
setTimeout(function () {
|
||||
self.viewmanager.start();
|
||||
self.viewmanager.appendTo(self.$element);
|
||||
}, 0);
|
||||
},
|
||||
reload_current_view: function() {
|
||||
|
@ -1826,16 +1843,16 @@ openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
|||
pop.select_element(self.o2m.field.relation,{
|
||||
initial_view: "form",
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
auto_create: false,
|
||||
create_function: function(data) {
|
||||
return self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
});
|
||||
},
|
||||
parent_view: self.o2m.view
|
||||
}, self.o2m.build_domain(), self.o2m.build_context());
|
||||
pop.on_create.add(function(data) {
|
||||
self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
pop.stop();
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
pop.on_select_elements.add_last(function() {
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -1874,7 +1891,7 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
|||
self.on_ui_change();
|
||||
});
|
||||
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(new openerp.base.NullViewManager(this), this.list_id, this.dataset, false, {
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(this, this.list_id, this.dataset, false, {
|
||||
'addable': 'Add',
|
||||
'selectable': self.multi_selection
|
||||
});
|
||||
|
@ -1930,7 +1947,6 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
|||
self.reload_content();
|
||||
}
|
||||
});
|
||||
pop.stop();
|
||||
});
|
||||
},
|
||||
do_activate_record: function(index, id) {
|
||||
|
@ -1952,16 +1968,22 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
|||
* - initial_view: form or search (default search)
|
||||
* - disable_multiple_selection
|
||||
* - alternative_form_view
|
||||
* - auto_create (default true)
|
||||
* - create_function (defaults to a naive saving behavior)
|
||||
* - parent_view
|
||||
*/
|
||||
select_element: function(model, options, domain, context) {
|
||||
var self = this;
|
||||
this.model = model;
|
||||
this.domain = domain || [];
|
||||
this.context = context || {};
|
||||
this.options = _.defaults(options || {}, {"initial_view": "search", "auto_create": true});
|
||||
this.options = _.defaults(options || {}, {"initial_view": "search", "create_function": function() {
|
||||
return self.create_row.apply(self, arguments);
|
||||
}});
|
||||
this.initial_ids = this.options.initial_ids;
|
||||
openerp.base.form.dialog(this.render());
|
||||
this.created_elements = [];
|
||||
openerp.base.form.dialog(this.render(), {close:function() {
|
||||
self.check_exit();
|
||||
}});
|
||||
this.start();
|
||||
},
|
||||
start: function() {
|
||||
|
@ -2007,6 +2029,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
|||
}
|
||||
$sbutton.click(function() {
|
||||
self.on_select_elements(self.selected_ids);
|
||||
self.stop();
|
||||
});
|
||||
self.view_list = new openerp.base.form.SelectCreateListView(self,
|
||||
self.element_id + "_view_list", self.dataset, false,
|
||||
|
@ -2019,15 +2042,11 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
|||
});
|
||||
this.searchview.start();
|
||||
},
|
||||
on_create: function(data) {
|
||||
if (!this.options.auto_create)
|
||||
return;
|
||||
create_row: function(data) {
|
||||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain);
|
||||
wdataset.parent_view = this.options.parent_view;
|
||||
wdataset.create(data, function(r) {
|
||||
self.on_select_elements([r.result]);
|
||||
});
|
||||
return wdataset.create(data);
|
||||
},
|
||||
on_select_elements: function(element_ids) {
|
||||
},
|
||||
|
@ -2055,18 +2074,43 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
|||
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("SelectCreatePopup.form.buttons"));
|
||||
$buttons.html(QWeb.render("SelectCreatePopup.form.buttons", {widget:self}));
|
||||
var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save-new");
|
||||
$nbutton.click(function() {
|
||||
self._created = $.Deferred().then(function() {
|
||||
self._created = undefined;
|
||||
self.view_form.on_button_new();
|
||||
});
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save");
|
||||
$nbutton.click(function() {
|
||||
self._created = $.Deferred().then(function() {
|
||||
self._created = undefined;
|
||||
self.check_exit();
|
||||
});
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_selectcreatepopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
self.check_exit();
|
||||
});
|
||||
});
|
||||
this.dataset.on_create.add(function(data) {
|
||||
self.options.create_function(data).then(function(r) {
|
||||
self.created_elements.push(r.result);
|
||||
if (self._created) {
|
||||
self._created.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
this.dataset.on_create.add(this.on_create);
|
||||
this.view_form.do_show();
|
||||
},
|
||||
check_exit: function() {
|
||||
if (this.created_elements.length > 0) {
|
||||
this.on_select_elements(this.created_elements);
|
||||
}
|
||||
this.stop();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2076,6 +2120,7 @@ openerp.base.form.SelectCreateListView = openerp.base.ListView.extend({
|
|||
},
|
||||
select_record: function(index) {
|
||||
this.popup.on_select_elements([this.dataset.ids[index]]);
|
||||
this.popup.stop();
|
||||
},
|
||||
do_select: function(ids, records) {
|
||||
this._super(ids, records);
|
||||
|
@ -2199,8 +2244,8 @@ openerp.base.form.FieldBinary = openerp.base.form.Field.extend({
|
|||
delete(window[this.iframe]);
|
||||
if (size === false) {
|
||||
this.notification.warn("File Upload", "There was a problem while uploading your file");
|
||||
// TODO: use openerp web exception handler
|
||||
console.log("Error while uploading file : ", name);
|
||||
// TODO: use openerp web crashmanager
|
||||
this.log("Error while uploading file : ", name);
|
||||
} else {
|
||||
this.on_file_uploaded_and_valid.apply(this, arguments);
|
||||
this.on_ui_change();
|
||||
|
@ -2309,10 +2354,8 @@ openerp.base.form.widgets = new openerp.base.Registry({
|
|||
'url' : 'openerp.base.form.FieldUrl',
|
||||
'text' : 'openerp.base.form.FieldText',
|
||||
'text_wiki' : 'openerp.base.form.FieldText',
|
||||
// 'date' : 'openerp.base.form.FieldDate',
|
||||
// 'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
'date' : 'openerp.base.form.FieldChar',
|
||||
'datetime' : 'openerp.base.form.FieldChar',
|
||||
'date' : 'openerp.base.form.FieldDate',
|
||||
'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
'selection' : 'openerp.base.form.FieldSelection',
|
||||
'many2one' : 'openerp.base.form.FieldMany2One',
|
||||
'many2many' : 'openerp.base.form.FieldMany2Many',
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
|
||||
openerp.base.formats = 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;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
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;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
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;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Left-pad provided arg 1 with zeroes until reaching size provided by second
|
||||
* argument.
|
||||
*
|
||||
* @param {Number|String} str value to pad
|
||||
* @param {Number} size size to reach on the final padded value
|
||||
* @returns {String} padded string
|
||||
*/
|
||||
var zpad = function(str, size) {
|
||||
str = "" + str;
|
||||
return new Array(size - str.length + 1).join('0') + 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) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":"
|
||||
+ zpad(obj.getUTCMinutes(),2) + ":" + zpad(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) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
|
||||
+ zpad(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) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
|
||||
+ zpad(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a single atomic value based on a field descriptor
|
||||
*
|
||||
* @param {Object} value read from OpenERP
|
||||
* @param {Object} descriptor union of orm field and view field
|
||||
* @param {Object} [descriptor.widget] widget to use to display the value
|
||||
* @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
|
||||
* @param {Object} [descriptor.digits] used for the formatting of floats
|
||||
* @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
|
||||
*/
|
||||
openerp.base.format_value = function (value, descriptor, value_if_empty) {
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (descriptor.widget || descriptor.type) {
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = descriptor.digits ? descriptor.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a provided cell based on its field type
|
||||
*
|
||||
* @param {Object} row_data record whose values should be displayed in the cell
|
||||
* @param {Object} column column descriptor
|
||||
* @param {"button"|"field"} column.tag base control type
|
||||
* @param {String} column.type widget type for a field control
|
||||
* @param {String} [column.string] button label
|
||||
* @param {String} [column.icon] button icon
|
||||
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
|
||||
*/
|
||||
openerp.base.format_cell = function (row_data, column, value_if_empty) {
|
||||
var attrs = column.modifiers_for(row_data);
|
||||
if (attrs.invisible) { return ''; }
|
||||
if (column.tag === 'button') {
|
||||
return [
|
||||
'<button type="button" title="', column.string || '', '">',
|
||||
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
|
||||
' alt="', column.string || '', '"/>',
|
||||
'</button>'
|
||||
].join('')
|
||||
}
|
||||
|
||||
return openerp.base.format_value(
|
||||
row_data[column.id].value, column, value_if_empty);
|
||||
}
|
||||
|
||||
};
|
|
@ -1,63 +1,5 @@
|
|||
openerp.base.list = function (openerp) {
|
||||
openerp.base.views.add('list', 'openerp.base.ListView');
|
||||
openerp.base.list = {
|
||||
/**
|
||||
* Formats the rendring of a given value based on its field type
|
||||
*
|
||||
* @param {Object} row_data record whose values should be displayed in the cell
|
||||
* @param {Object} column column descriptor
|
||||
* @param {"button"|"field"} column.tag base control type
|
||||
* @param {String} column.type widget type for a field control
|
||||
* @param {String} [column.string] button label
|
||||
* @param {String} [column.icon] button icon
|
||||
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
|
||||
*/
|
||||
render_cell: function (row_data, column, value_if_empty) {
|
||||
var attrs = column.modifiers_for(row_data);
|
||||
if (attrs.invisible) { return ''; }
|
||||
if (column.tag === 'button') {
|
||||
return [
|
||||
'<button type="button" title="', column.string || '', '">',
|
||||
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
|
||||
' alt="', column.string || '', '"/>',
|
||||
'</button>'
|
||||
].join('')
|
||||
}
|
||||
|
||||
var value = row_data[column.id].value;
|
||||
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (column.widget || column.type) {
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = column.digits ? column.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ {
|
||||
defaults: {
|
||||
// records can be selected one by one
|
||||
|
@ -85,8 +27,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
* the default behaviors and possible options for the list view.
|
||||
*
|
||||
* @constructs
|
||||
* @param view_manager
|
||||
* @param session An OpenERP session object
|
||||
* @param parent parent object
|
||||
* @param element_id the id of the DOM elements this view should link itself to
|
||||
* @param {openerp.base.DataSet} dataset the dataset the view should work with
|
||||
* @param {String} view_id the listview's identifier, if any
|
||||
|
@ -102,16 +43,13 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.set_default_options(_.extend({}, this.defaults, options || {}));
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
||||
this.columns = [];
|
||||
|
||||
this.options = _.extend({}, this.defaults, options || {});
|
||||
|
||||
this.set_groups(new openerp.base.ListView.Groups(this));
|
||||
|
||||
if (this.dataset instanceof openerp.base.DataSetStatic) {
|
||||
|
@ -123,7 +61,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
/**
|
||||
* Retrieves the view's number of records per page (|| section)
|
||||
*
|
||||
* options > defaults > view_manager.action.limit > indefinite
|
||||
* options > defaults > parent.action.limit > indefinite
|
||||
*
|
||||
* @returns {Number|null}
|
||||
*/
|
||||
|
@ -131,7 +69,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
if (this._limit === undefined) {
|
||||
this._limit = (this.options.limit
|
||||
|| this.defaults.limit
|
||||
|| (this.view_manager.action || {}).limit
|
||||
|| (this.widget_parent.action || {}).limit
|
||||
|| null);
|
||||
}
|
||||
return this._limit;
|
||||
|
@ -157,7 +95,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
self.do_delete(ids);
|
||||
},
|
||||
'action': function (e, action_name, id, callback) {
|
||||
self.do_action(action_name, id, callback);
|
||||
self.do_button_action(action_name, id, callback);
|
||||
},
|
||||
'row_link': function (e, id, dataset) {
|
||||
self.do_activate_record(dataset.index, id, dataset);
|
||||
|
@ -267,7 +205,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
})
|
||||
.val(self._limit || 'NaN');
|
||||
});
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
if (!this.sidebar && this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id);
|
||||
this.sidebar.start();
|
||||
this.sidebar.add_toolbar(data.fields_view.toolbar);
|
||||
|
@ -389,9 +327,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
view = view || 'form';
|
||||
this.dataset.index = index;
|
||||
_.delay(_.bind(function () {
|
||||
if(this.view_manager) {
|
||||
this.view_manager.on_mode_switch(view);
|
||||
}
|
||||
this.do_switch_view(view);
|
||||
}, this));
|
||||
},
|
||||
do_show: function () {
|
||||
|
@ -416,8 +352,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
* Reloads the list view based on the current settings (dataset & al)
|
||||
*
|
||||
* @param {Boolean} [grouped] Should the list be displayed grouped
|
||||
* @param {Object} [context] context to send the server while loading the view
|
||||
*/
|
||||
reload_view: function (grouped) {
|
||||
reload_view: function (grouped, context) {
|
||||
var self = this;
|
||||
var callback = function (field_view_get) {
|
||||
self.on_loaded(field_view_get, grouped);
|
||||
|
@ -428,7 +365,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
return this.rpc('/base/listview/load', {
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
context: this.dataset.get_context(),
|
||||
context: this.dataset.get_context(context),
|
||||
toolbar: this.options.sidebar
|
||||
}, callback);
|
||||
}
|
||||
|
@ -464,11 +401,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
* @param {Object} results results of evaluating domain and process for a search
|
||||
*/
|
||||
do_actual_search: function (results) {
|
||||
this.dataset.context = results.context;
|
||||
this.dataset.domain = results.domain;
|
||||
this.groups.datagroup = new openerp.base.DataGroup(
|
||||
this, this.model,
|
||||
results.domain, results.context,
|
||||
this.dataset.get_domain(results.domain),
|
||||
this.dataset.get_context(results.context),
|
||||
results.group_by);
|
||||
this.groups.datagroup.sort = this.dataset._sort;
|
||||
|
||||
|
@ -476,7 +412,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
results.group_by = null;
|
||||
}
|
||||
|
||||
this.reload_view(!!results.group_by).then(
|
||||
this.reload_view(!!results.group_by, results.context).then(
|
||||
$.proxy(this, 'reload_content'));
|
||||
},
|
||||
/**
|
||||
|
@ -519,17 +455,16 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
* @param {Object} id id of the record the action should be called on
|
||||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
do_action: function (name, id, callback) {
|
||||
do_button_action: function (name, id, callback) {
|
||||
var self = this,
|
||||
action = _.detect(this.columns, function (field) {
|
||||
return field.name === name;
|
||||
});
|
||||
if (!action) { return; }
|
||||
this.execute_action(
|
||||
action, this.dataset, this.session.action_manager, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
this.execute_action(action, this.dataset, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -541,11 +476,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
*/
|
||||
do_activate_record: function (index, id, dataset) {
|
||||
var self = this;
|
||||
_.extend(this.dataset, {
|
||||
domain: dataset.domain,
|
||||
context: dataset.get_context()
|
||||
}).read_slice([], 0, false, function () {
|
||||
self.select_record(index);
|
||||
this.dataset.read_slice({
|
||||
context: dataset.get_context(),
|
||||
domain: dataset.get_domain()
|
||||
}, function () {
|
||||
self.select_record(index);
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -644,7 +579,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
}
|
||||
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
|
||||
.html(openerp.base.list.render_cell(aggregation, column));
|
||||
.html(openerp.base.format_cell(aggregation, column));
|
||||
});
|
||||
}
|
||||
// TODO: implement reorder (drag and drop rows)
|
||||
|
@ -732,7 +667,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
|||
this.$current = this.$_element.clone(true);
|
||||
this.$current.empty().append(
|
||||
QWeb.render('ListView.rows', _.extend({
|
||||
render_cell: openerp.base.list.render_cell}, this)));
|
||||
render_cell: openerp.base.format_cell}, this)));
|
||||
},
|
||||
/**
|
||||
* Gets the ids of all currently selected records, if any
|
||||
|
@ -837,7 +772,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
|||
var old_index = this.dataset.index;
|
||||
this.dataset.index = record_index;
|
||||
read_p = this.dataset.read_index(
|
||||
_.filter(_.pluck(this.columns, 'name'), _.identity),
|
||||
_.pluck(_(this.columns).filter(function (r) {return r.tag === 'field';}), 'name'),
|
||||
function (record) {
|
||||
var form_record = self.transform_record(record);
|
||||
self.rows.splice(record_index, 1, form_record);
|
||||
|
@ -863,7 +798,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
|||
row: this.rows[record_index],
|
||||
row_parity: (record_index % 2 === 0) ? 'even' : 'odd',
|
||||
row_index: record_index,
|
||||
render_cell: openerp.base.list.render_cell
|
||||
render_cell: openerp.base.format_cell
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -1023,7 +958,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
|||
row_data[group.grouped_on] = group;
|
||||
var group_column = _(self.columns).detect(function (column) {
|
||||
return column.id === group.grouped_on; });
|
||||
$group_column.html(openerp.base.list.render_cell(
|
||||
$group_column.html(openerp.base.format_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
));
|
||||
if (group.openable) {
|
||||
|
@ -1099,10 +1034,11 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
|||
d = new $.Deferred(),
|
||||
page = this.datagroup.openable ? this.page : view.page;
|
||||
|
||||
dataset.read_slice(
|
||||
_.filter(_.pluck(_.select(this.columns, function(x) {return x.tag == "field";}), 'name'), _.identity),
|
||||
page * limit, limit,
|
||||
function (records) {
|
||||
dataset.read_slice({
|
||||
fields: _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name'),
|
||||
offset: page * limit,
|
||||
limit: limit
|
||||
}, function (records) {
|
||||
if (!self.datagroup.openable) {
|
||||
view.configure_pager(dataset);
|
||||
} else {
|
||||
|
|
|
@ -3,7 +3,6 @@ openerp.base.search = function(openerp) {
|
|||
openerp.base.SearchView = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id, dataset, view_id, defaults) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
@ -361,9 +360,9 @@ openerp.base.search.fields = new openerp.base.Registry({
|
|||
'selection': 'openerp.base.search.SelectionField',
|
||||
'datetime': 'openerp.base.search.DateTimeField',
|
||||
'date': 'openerp.base.search.DateField',
|
||||
'one2many': 'openerp.base.search.OneToManyField',
|
||||
'many2one': 'openerp.base.search.ManyToOneField',
|
||||
'many2many': 'openerp.base.search.ManyToManyField'
|
||||
'many2many': 'openerp.base.search.CharField',
|
||||
'one2many': 'openerp.base.search.CharField'
|
||||
});
|
||||
openerp.base.search.Invalid = openerp.base.Class.extend( /** @lends openerp.base.search.Invalid# */{
|
||||
/**
|
||||
|
@ -622,39 +621,6 @@ openerp.base.search.CharField = openerp.base.search.Field.extend( /** @lends ope
|
|||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.BooleanField = openerp.base.search.Field.extend({
|
||||
template: 'SearchView.field.selection',
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.attrs.selection = [
|
||||
['true', 'Yes'],
|
||||
['false', 'No']
|
||||
];
|
||||
},
|
||||
/**
|
||||
* Search defaults likely to be boolean values (for a boolean field).
|
||||
*
|
||||
* In the HTML, we only get strings, and our strings here are
|
||||
* <code>'true'</code> and <code>'false'</code>, so ensure we get only
|
||||
* those by truth-testing the default value.
|
||||
*
|
||||
* @param {Object} defaults default values for this search view
|
||||
*/
|
||||
render: function (defaults) {
|
||||
var name = this.attrs.name;
|
||||
if (name in defaults) {
|
||||
defaults[name] = defaults[name] ? "true" : "false";
|
||||
}
|
||||
return this._super(defaults);
|
||||
},
|
||||
get_value: function () {
|
||||
switch (this.$element.val()) {
|
||||
case 'false': return false;
|
||||
case 'true': return true;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
openerp.base.search.NumberField = openerp.base.search.Field.extend(/** @lends openerp.base.search.NumberField# */{
|
||||
get_value: function () {
|
||||
if (!this.$element.val()) {
|
||||
|
@ -691,93 +657,73 @@ openerp.base.search.FloatField = openerp.base.search.NumberField.extend(/** @len
|
|||
return parseFloat(value);
|
||||
}
|
||||
});
|
||||
openerp.base.search.SelectionField = openerp.base.search.Field.extend({
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.Field
|
||||
*/
|
||||
openerp.base.search.SelectionField = openerp.base.search.Field.extend(/** @lends openerp.base.search.SelectionField# */{
|
||||
template: 'SearchView.field.selection',
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.BooleanField = openerp.base.search.SelectionField.extend(/** @lends openerp.base.search.BooleanField# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.search.BooleanField
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.attrs.selection = [
|
||||
['true', 'Yes'],
|
||||
['false', 'No']
|
||||
];
|
||||
},
|
||||
/**
|
||||
* Search defaults likely to be boolean values (for a boolean field).
|
||||
*
|
||||
* In the HTML, we only want/get strings, and our strings here are ``true``
|
||||
* and ``false``, so ensure we use precisely those by truth-testing the
|
||||
* default value (iif there is one in the view's defaults).
|
||||
*
|
||||
* @param {Object} defaults default values for this search view
|
||||
* @returns {String} rendered boolean field
|
||||
*/
|
||||
render: function (defaults) {
|
||||
var name = this.attrs.name;
|
||||
if (name in defaults) {
|
||||
defaults[name] = defaults[name] ? "true" : "false";
|
||||
}
|
||||
return this._super(defaults);
|
||||
},
|
||||
get_value: function () {
|
||||
switch (this.$element.val()) {
|
||||
case 'false': return false;
|
||||
case 'true': return true;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
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({
|
||||
this.$element.addClass('field_date').datepicker({
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
},
|
||||
stop: function () {
|
||||
this.$element.find('input').datepicker('destroy');
|
||||
this.$element.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();
|
||||
|
||||
if (!values_array || !values_array[0]) {
|
||||
throw new openerp.base.search.Invalid(
|
||||
this.attrs.name, null, "widget not ready");
|
||||
}
|
||||
var from = values_array[0].value,
|
||||
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}});
|
||||
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.CharField.extend({
|
||||
// TODO: .relation, .context, .domain
|
||||
});
|
||||
openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({
|
||||
// TODO: @widget
|
||||
// TODO: .selection, .context, .domain
|
||||
init: function (view_section, field, view) {
|
||||
this._super(view_section, field, view);
|
||||
var self = this;
|
||||
|
@ -845,9 +791,6 @@ openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({
|
|||
return this._super();
|
||||
}
|
||||
});
|
||||
openerp.base.search.ManyToManyField = openerp.base.search.CharField.extend({
|
||||
// TODO: .related_columns (Array), .context, .domain
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearch = openerp.base.OldWidget.extend({
|
||||
template: 'SearchView.extended_search',
|
||||
|
@ -930,11 +873,10 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
|||
this._super();
|
||||
var _this = this;
|
||||
this.add_prop();
|
||||
this.$element.find('.searchview_extended_add_proposition').click(function (e) {
|
||||
this.$element.find('.searchview_extended_add_proposition').click(function () {
|
||||
_this.add_prop();
|
||||
});
|
||||
var delete_btn = this.$element.find('.searchview_extended_delete_group');
|
||||
delete_btn.click(function (e) {
|
||||
this.$element.find('.searchview_extended_delete_group').click(function () {
|
||||
_this.stop();
|
||||
});
|
||||
},
|
||||
|
@ -944,7 +886,7 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
|||
}).compact().value();
|
||||
var choice = this.$element.find(".searchview_extended_group_choice").val();
|
||||
var op = choice == "all" ? "&" : "|";
|
||||
return [].concat(choice == "none" ? ['!'] : [],
|
||||
return choice == "none" ? ['!'] : [].concat(
|
||||
_.map(_.range(_.max([0,props.length - 1])), function() { return op; }),
|
||||
props);
|
||||
},
|
||||
|
@ -956,10 +898,7 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
|||
parent.check_last_element();
|
||||
},
|
||||
set_last_group: function(is_last) {
|
||||
if(is_last)
|
||||
this.$element.addClass("last_group");
|
||||
else
|
||||
this.$element.removeClass("last_group");
|
||||
this.$element.toggleClass('last_group', is_last);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -982,8 +921,7 @@ openerp.base.search.ExtendedSearchProposition = openerp.base.OldWidget.extend({
|
|||
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.$element.find('.searchview_extended_delete_prop').click(function () {
|
||||
_this.stop();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -5,22 +5,202 @@
|
|||
openerp.base.view_tree = function(openerp) {
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
openerp.base.TreeView = openerp.base.Widget.extend({
|
||||
/**
|
||||
* Genuine tree view (the one displayed as a tree, not the list)
|
||||
*/
|
||||
openerp.base.TreeView = openerp.base.View.extend({
|
||||
/**
|
||||
* Indicates that this view is not searchable, and thus that no search
|
||||
* view should be displayed (if there is one active).
|
||||
*/
|
||||
searchable : false,
|
||||
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
||||
this.records = {};
|
||||
|
||||
this.options = _.extend({}, this.defaults, options || {});
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Tree view');
|
||||
return this.rpc("/base/treeview/load", {
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
toolbar: this.view_manager ? !!this.view_manager.sidebar : false
|
||||
}, this.on_loaded);
|
||||
},
|
||||
/**
|
||||
* Returns the list of fields needed to correctly read objects.
|
||||
*
|
||||
* Gathers the names of all fields in fields_view_get, and adds the
|
||||
* field_parent (children_field in the tree view) if it's not already one
|
||||
* of the fields to fetch
|
||||
*
|
||||
* @returns {Array} an array of fields which can be provided to DataSet.read_slice and others
|
||||
*/
|
||||
fields_list: function () {
|
||||
var fields = _.keys(this.fields);
|
||||
if (!_(fields).contains(this.children_field)) {
|
||||
fields.push(this.children_field);
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
on_loaded: function (fields_view) {
|
||||
var self = this;
|
||||
var has_toolbar = !!fields_view.arch.attrs.toolbar;
|
||||
// field name in OpenERP is kinda stupid: this is the name of the field
|
||||
// holding the ids to the children of the current node, why call it
|
||||
// field_parent?
|
||||
this.children_field = fields_view['field_parent'];
|
||||
this.fields_view = fields_view;
|
||||
_(this.fields_view.arch.children).each(function (field) {
|
||||
if (field.attrs.modifiers) {
|
||||
field.attrs.modifiers = JSON.parse(field.attrs.modifiers);
|
||||
}
|
||||
});
|
||||
this.fields = fields_view.fields;
|
||||
this.hook_row_click();
|
||||
this.$element.html(QWeb.render('TreeView', {
|
||||
'title': this.fields_view.arch.attrs.string,
|
||||
'fields_view': this.fields_view.arch.children,
|
||||
'fields': this.fields,
|
||||
'toolbar': has_toolbar
|
||||
}));
|
||||
|
||||
this.dataset.read_slice({fields: this.fields_list()}, function (records) {
|
||||
if (!has_toolbar) {
|
||||
// WARNING: will do a second read on the same ids, but only on
|
||||
// first load so not very important
|
||||
self.getdata(null, _(records).pluck('id'));
|
||||
return;
|
||||
}
|
||||
|
||||
var $select = self.$element.find('select')
|
||||
.change(function () {
|
||||
var $option = $(this).find(':selected');
|
||||
self.getdata($option.val(), $option.data('children'));
|
||||
});
|
||||
_(records).each(function (record) {
|
||||
self.records[record.id] = record;
|
||||
$('<option>')
|
||||
.val(record.id)
|
||||
.text(record.name)
|
||||
.data('children', record[self.children_field])
|
||||
.appendTo($select);
|
||||
});
|
||||
|
||||
if (!_.isEmpty(records)) {
|
||||
$select.change();
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Sets up opening a row
|
||||
*/
|
||||
hook_row_click: function () {
|
||||
var self = this;
|
||||
this.$element.delegate('.treeview-td span, .treeview-tr span', 'click', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.activate($(this).closest('tr').data('id'));
|
||||
});
|
||||
|
||||
this.$element.delegate('.treeview-tr', 'click', function () {
|
||||
var is_loaded = 0,
|
||||
$this = $(this),
|
||||
record_id = $this.data('id'),
|
||||
record = self.records[record_id],
|
||||
children_ids = record[self.children_field];
|
||||
|
||||
_(children_ids).each(function(childid) {
|
||||
if (self.$element.find('#treerow_' + childid).length) {
|
||||
if (self.$element.find('#treerow_' + childid).is(':hidden')) {
|
||||
is_loaded = -1;
|
||||
} else {
|
||||
is_loaded++;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (is_loaded === 0) {
|
||||
if (!$this.parent().hasClass('oe-open')) {
|
||||
self.getdata(record_id, children_ids);
|
||||
}
|
||||
} else {
|
||||
self.showcontent(record_id, is_loaded < 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
// get child data of selected value
|
||||
getdata: function (id, children_ids) {
|
||||
var self = this;
|
||||
|
||||
self.dataset.read_ids(children_ids, this.fields_list(), function (records) {
|
||||
_(records).each(function (record) {
|
||||
self.records[record.id] = record;
|
||||
});
|
||||
|
||||
var $curr_node = self.$element.find('#treerow_' + id);
|
||||
var children_rows = QWeb.render('TreeView.rows', {
|
||||
'records': records,
|
||||
'children_field': self.children_field,
|
||||
'fields_view': self.fields_view.arch.children,
|
||||
'fields': self.fields,
|
||||
'level': $curr_node.data('level') || 0,
|
||||
'render': openerp.base.format_value
|
||||
});
|
||||
|
||||
if ($curr_node.length) {
|
||||
$curr_node.addClass('oe-open');
|
||||
$curr_node.after(children_rows);
|
||||
} else {
|
||||
self.$element.find('tbody').html(children_rows);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Get details in listview
|
||||
activate: function(id) {
|
||||
var self = this;
|
||||
this.rpc('/base/treeview/action', {
|
||||
id: id,
|
||||
model: this.dataset.model,
|
||||
context: new openerp.base.CompoundContext(
|
||||
this.dataset.get_context(), {
|
||||
active_model: this.dataset.model,
|
||||
active_id: id,
|
||||
active_ids: [id]})
|
||||
}, function (actions) {
|
||||
if (!actions.length) { return; }
|
||||
var action = actions[0][2];
|
||||
self.do_action(action);
|
||||
});
|
||||
},
|
||||
|
||||
// show & hide the contents
|
||||
showcontent: function (record_id, show) {
|
||||
this.$element.find('#treerow_' + record_id)
|
||||
.toggleClass('oe-open', show);
|
||||
|
||||
_(this.records[record_id][this.children_field]).each(function (child_id) {
|
||||
var $child_row = this.$element.find('#treerow_' + child_id);
|
||||
if ($child_row.hasClass('oe-open')) {
|
||||
this.showcontent(child_id, false);
|
||||
}
|
||||
$child_row.toggle(show);
|
||||
}, this);
|
||||
},
|
||||
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
this.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -4,72 +4,83 @@
|
|||
|
||||
openerp.base.views = function(openerp) {
|
||||
|
||||
/**
|
||||
* Registry for all the client actions key: tag value: widget
|
||||
*/
|
||||
openerp.base.client_actions = new openerp.base.Registry();
|
||||
|
||||
openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
// process all kind of actions
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.viewmanager = null;
|
||||
this.current_dialog = null;
|
||||
// Temporary linking view_manager to session.
|
||||
// Will use parent to find it when implementation will be done.
|
||||
this.session.action_manager = this;
|
||||
identifier_prefix: "actionmanager",
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.inner_viewmanager = null;
|
||||
this.dialog = null;
|
||||
this.dialog_viewmanager = null;
|
||||
this.client_widget = null;
|
||||
},
|
||||
do_action: function(action, on_closed) {
|
||||
render: function() {
|
||||
return "<div id='"+this.element_id+"'></div>";
|
||||
},
|
||||
dialog_stop: function () {
|
||||
if (this.dialog) {
|
||||
this.dialog_viewmanager.stop();
|
||||
this.dialog_viewmanager = null;
|
||||
this.dialog.stop();
|
||||
this.dialog = null;
|
||||
}
|
||||
},
|
||||
inner_stop: function () {
|
||||
if (this.inner_viewmanager) {
|
||||
this.inner_viewmanager.stop();
|
||||
this.inner_viewmanager = null;
|
||||
}
|
||||
},
|
||||
do_action: function(action, on_close) {
|
||||
var type = action.type.replace(/\./g,'_');
|
||||
var popup = action.target === 'new';
|
||||
action.flags = _.extend({
|
||||
sidebar : action.target != 'new',
|
||||
search_view : action.target != 'new',
|
||||
new_window : false,
|
||||
views_switcher : action.target != 'new',
|
||||
action_buttons : action.target != 'new',
|
||||
pager : action.target != 'new'
|
||||
views_switcher : !popup,
|
||||
search_view : !popup,
|
||||
action_buttons : !popup,
|
||||
sidebar : !popup,
|
||||
pager : !popup
|
||||
}, action.flags || {});
|
||||
// instantiate the right controllers by understanding the action
|
||||
if (!(action.type in this)) {
|
||||
console.log("Action manager can't handle action of type " + action.type, action);
|
||||
if (!(type in this)) {
|
||||
this.log("Action manager can't handle action of type " + action.type, action);
|
||||
return;
|
||||
}
|
||||
this[action.type](action, on_closed);
|
||||
this[type](action, on_close);
|
||||
},
|
||||
|
||||
'ir.actions.act_window': function (action, on_closed) {
|
||||
if (!action.target && this.current_dialog) {
|
||||
action.flags.new_window = true;
|
||||
}
|
||||
if (action.target == 'new') {
|
||||
var dialog = this.current_dialog = new openerp.base.ActionDialog(this, {
|
||||
title: action.name,
|
||||
width: '50%'
|
||||
});
|
||||
if (on_closed) {
|
||||
dialog.close_callback = on_closed;
|
||||
ir_actions_act_window: function (action, on_close) {
|
||||
if (action.target === 'new') {
|
||||
if (this.dialog == null) {
|
||||
this.dialog = new openerp.base.Dialog(this, { title: action.name, width: '80%' });
|
||||
if(on_close)
|
||||
this.dialog.on_close.add(on_close);
|
||||
this.dialog.start();
|
||||
} else {
|
||||
this.dialog_viewmanager.stop();
|
||||
}
|
||||
dialog.start(false);
|
||||
var viewmanager = dialog.viewmanager = new openerp.base.ViewManagerAction(this, dialog.element_id, action);
|
||||
viewmanager.start();
|
||||
dialog.open();
|
||||
} else if (action.flags.new_window) {
|
||||
action.flags.new_window = false;
|
||||
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
|
||||
this.dialog_viewmanager.appendTo(this.dialog.$element);
|
||||
this.dialog.open();
|
||||
} else {
|
||||
this.dialog_stop();
|
||||
this.inner_stop();
|
||||
this.inner_viewmanager = new openerp.base.ViewManagerAction(this, action);
|
||||
this.inner_viewmanager.appendTo(this.$element);
|
||||
}
|
||||
/* new window code
|
||||
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);
|
||||
if (on_closed) {
|
||||
on_closed();
|
||||
}
|
||||
var url = window.location.protocol + "//" + window.location.host + window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url,'_blank');
|
||||
});
|
||||
} else {
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this, this.element_id, action);
|
||||
this.viewmanager.start();
|
||||
}
|
||||
*/
|
||||
},
|
||||
'ir.actions.act_window_close': function (action, on_closed) {
|
||||
this.close_dialog();
|
||||
ir_actions_act_window_close: function (action, on_closed) {
|
||||
this.dialog_stop();
|
||||
},
|
||||
'ir.actions.server': function (action, on_closed) {
|
||||
ir_actions_server: function (action, on_closed) {
|
||||
var self = this;
|
||||
this.rpc('/base/action/run', {
|
||||
action_id: action.id,
|
||||
|
@ -78,47 +89,28 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
|||
self.do_action(action, on_closed)
|
||||
});
|
||||
},
|
||||
'ir.actions.client': function (action) {
|
||||
var Handler = openerp.base.client_actions.get_object(action.tag);
|
||||
new Handler(this, this.element_id, action.params).start();
|
||||
},
|
||||
close_dialog: function () {
|
||||
if (this.current_dialog) {
|
||||
this.current_dialog.stop();
|
||||
this.current_dialog = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ActionDialog = openerp.base.Dialog.extend({
|
||||
identifier_prefix: 'action_dialog',
|
||||
on_close: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.close_callback) {
|
||||
this.close_callback();
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
ir_actions_client: function (action) {
|
||||
this.client_widget = openerp.base.client_actions.get_object(action.tag);
|
||||
new this.client_widget(this, this.element_id, action.params).start();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id, dataset, views) {
|
||||
this._super(parent, element_id);
|
||||
identifier_prefix: "viewmanager",
|
||||
init: function(parent, dataset, views) {
|
||||
this._super(parent);
|
||||
this.model = dataset.model;
|
||||
this.dataset = dataset;
|
||||
this.searchview = null;
|
||||
this.active_view = null;
|
||||
this.views_src = _.map(views, function(x)
|
||||
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
this.views = {};
|
||||
this.flags = this.flags || {};
|
||||
this.registry = openerp.base.views;
|
||||
},
|
||||
render: function() {
|
||||
return QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src})
|
||||
},
|
||||
/**
|
||||
* @returns {jQuery.Deferred} initial view loading promise
|
||||
*/
|
||||
|
@ -126,28 +118,26 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
|||
this._super();
|
||||
var self = this;
|
||||
this.dataset.start();
|
||||
|
||||
this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src}));
|
||||
this.$element.find('.oe_vm_switch button').click(function() {
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
|
||||
var views_ids = {};
|
||||
_.each(this.views_src, function(view) {
|
||||
self.views[view.view_type] = $.extend({}, view, {
|
||||
controller : null,
|
||||
options : _.extend({
|
||||
sidebar_id : self.element_id + '_sidebar_' + view.view_type
|
||||
}, self.flags)
|
||||
sidebar_id : self.element_id + '_sidebar_' + view.view_type,
|
||||
action : self.action,
|
||||
action_views_ids : views_ids
|
||||
}, self.flags, view.options || {})
|
||||
});
|
||||
views_ids[view.view_type] = view.view_id;
|
||||
});
|
||||
if (this.flags.views_switcher === false) {
|
||||
this.$element.find('.oe_vm_switch').hide();
|
||||
}
|
||||
// switch to the first one in sequence
|
||||
return this.on_mode_switch(this.views_src[0].view_type);
|
||||
|
||||
},
|
||||
stop: function() {
|
||||
},
|
||||
/**
|
||||
* Asks the view manager to switch visualization mode.
|
||||
|
@ -168,7 +158,8 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
|||
if (view.embedded_view) {
|
||||
controller.set_embedded_view(view.embedded_view);
|
||||
}
|
||||
if (view_type === 'list' && this.flags.search_view === false && this.action && this.action['auto_search']) {
|
||||
controller.do_switch_view.add_last(this.on_mode_switch);
|
||||
if (view_type === 'list' && this.flags.search_view === false && this.action && this.action['auto_search']) {
|
||||
// In case the search view is not instantiated: manually call ListView#search
|
||||
var domains = !_(self.action.domain).isEmpty()
|
||||
? [self.action.domain] : [],
|
||||
|
@ -217,11 +208,12 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
|||
},
|
||||
/**
|
||||
* Event launched when a controller has been inited.
|
||||
*
|
||||
*
|
||||
* @param {String} view_type type of view
|
||||
* @param {String} view the inited controller
|
||||
*/
|
||||
on_controller_inited: function(view_type, view) {},
|
||||
on_controller_inited: function(view_type, view) {
|
||||
},
|
||||
/**
|
||||
* Sets up the current viewmanager's search view.
|
||||
*
|
||||
|
@ -238,9 +230,8 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
|||
this.searchview.hide();
|
||||
}
|
||||
this.searchview.on_search.add(function(domains, contexts, groupbys) {
|
||||
self.views[self.active_view].controller.do_search.call(
|
||||
self, domains.concat(self.domains()),
|
||||
contexts.concat(self.contexts()), groupbys);
|
||||
var controller = self.views[self.active_view].controller;
|
||||
controller.do_search.call(controller, domains, contexts, groupbys);
|
||||
});
|
||||
return this.searchview.start();
|
||||
},
|
||||
|
@ -254,50 +245,22 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
|||
on_remove: function() {
|
||||
},
|
||||
on_edit: function() {
|
||||
},
|
||||
/**
|
||||
* Domains added on searches by the view manager, to override in subsequent
|
||||
* view manager in order to add new pieces of domains to searches
|
||||
*
|
||||
* @returns an empty list
|
||||
*/
|
||||
domains: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Contexts added on searches by the view manager.
|
||||
*
|
||||
* @returns an empty list
|
||||
*/
|
||||
contexts: function () {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.base.ViewManager, {
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
if(parent)
|
||||
this.session = parent.session;
|
||||
this.action = {flags: {}};
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Will move to action Manager
|
||||
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
init: function(parent, element_id, action) {
|
||||
init: function(parent, action) {
|
||||
this.session = parent.session;
|
||||
this.action = action;
|
||||
var dataset;
|
||||
if (!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null);
|
||||
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context, action.domain);
|
||||
} else {
|
||||
dataset = new openerp.base.DataSetStatic(this, action.res_model, {}, [action.res_id]);
|
||||
if (action.context) {
|
||||
// TODO fme: should normalize all DataSets constructors to (session, model, context, ...)
|
||||
dataset.context = action.context;
|
||||
}
|
||||
this.action.flags.search_view = false;
|
||||
dataset = new openerp.base.DataSetStatic(this, action.res_model, action.context, [action.res_id]);
|
||||
dataset.index = 0;
|
||||
}
|
||||
this._super(parent, element_id, dataset, action.views);
|
||||
this._super(parent, dataset, action.views);
|
||||
this.action = action;
|
||||
this.flags = this.action.flags || {};
|
||||
if (action.res_model == 'board.board' && action.views.length == 1 && action.views) {
|
||||
|
@ -307,6 +270,7 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
|||
},
|
||||
start: function() {
|
||||
var inital_view_loaded = this._super();
|
||||
|
||||
var search_defaults = {};
|
||||
_.each(this.action.context, function (value, key) {
|
||||
var match = /^search_default_(.*)$/.exec(key);
|
||||
|
@ -329,32 +293,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
|||
}
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
// should be replaced by automatic destruction implemented in Widget
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* adds action domain to the search domains
|
||||
*
|
||||
* @returns the action's domain
|
||||
*/
|
||||
domains: function () {
|
||||
if (!this.action.domain) {
|
||||
return [];
|
||||
}
|
||||
return [this.action.domain];
|
||||
},
|
||||
/**
|
||||
* adds action context to the search contexts
|
||||
*
|
||||
* @returns the action's context
|
||||
*/
|
||||
contexts: function () {
|
||||
if (!this.action.context) {
|
||||
return [];
|
||||
}
|
||||
return [this.action.context];
|
||||
},
|
||||
on_mode_switch: function (view_type) {
|
||||
this._super(view_type);
|
||||
this.shortcut_check(this.views[view_type]);
|
||||
|
@ -394,8 +332,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
|||
$shortcut_toggle.addClass("oe-shortcut-remove");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -491,7 +427,9 @@ openerp.base.View = openerp.base.Widget.extend({
|
|||
_.defaults(this.options, {
|
||||
// All possible views options should be defaulted here
|
||||
sidebar_id: null,
|
||||
sidebar: true
|
||||
sidebar: true,
|
||||
action: null,
|
||||
action_views_ids: {}
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -503,17 +441,12 @@ openerp.base.View = openerp.base.Widget.extend({
|
|||
* @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 {Object} [record_id] the identifier of the object on which the action is to be applied
|
||||
* @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action)
|
||||
*/
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_closed) {
|
||||
execute_action: function (action_data, dataset, record_id, on_closed) {
|
||||
var self = this;
|
||||
if (action_manager.current_dialog) {
|
||||
on_closed = action_manager.current_dialog.close_callback;
|
||||
}
|
||||
var handler = function (r) {
|
||||
action_manager.close_dialog();
|
||||
var action = r.result;
|
||||
if (action && action.constructor == Object) {
|
||||
action.context = action.context || {};
|
||||
|
@ -522,38 +455,36 @@ openerp.base.View = openerp.base.Widget.extend({
|
|||
active_ids: [record_id || false],
|
||||
active_model: dataset.model
|
||||
});
|
||||
action.flags = {
|
||||
new_window: true
|
||||
};
|
||||
action_manager.do_action(action, on_closed);
|
||||
self.do_action(action, on_closed);
|
||||
} else if (on_closed) {
|
||||
on_closed(action);
|
||||
}
|
||||
};
|
||||
|
||||
if (!action_data.special) {
|
||||
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
switch(action_data.type) {
|
||||
case 'object':
|
||||
return dataset.call_button(action_data.name, [[record_id], context], handler);
|
||||
case 'action':
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
|
||||
default:
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
} else {
|
||||
action_manager.close_dialog();
|
||||
}
|
||||
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
|
||||
if (action_data.special) {
|
||||
handler({result: {"type":"ir.actions.act_window_close"}});
|
||||
} else if (action_data.type=="object") {
|
||||
return dataset.call_button(action_data.name, [[record_id], context], handler);
|
||||
} else if (action_data.type=="action") {
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
|
||||
} else {
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Directly set a view to use instead of calling fields_view_get. This method must
|
||||
* be called before start(). When an embedded view is set, underlying implementations
|
||||
* of openerp.base.View must use the provided view instead of any other one.
|
||||
*
|
||||
*
|
||||
* @param embedded_view A view.
|
||||
*/
|
||||
set_embedded_view: function(embedded_view) {
|
||||
this.embedded_view = embedded_view;
|
||||
this.options.sidebar = false;
|
||||
},
|
||||
do_switch_view: function(view) {
|
||||
},
|
||||
set_common_sidebar_sections: function(sidebar) {
|
||||
sidebar.add_section('customize', "Customize", [
|
||||
|
@ -598,16 +529,16 @@ openerp.base.View = openerp.base.Widget.extend({
|
|||
}
|
||||
},
|
||||
on_sidebar_edit_workflow: function() {
|
||||
console.log('Todo');
|
||||
this.log('Todo');
|
||||
},
|
||||
on_sidebar_customize_object: function() {
|
||||
console.log('Todo');
|
||||
this.log('Todo');
|
||||
},
|
||||
on_sidebar_import: function() {
|
||||
},
|
||||
on_sidebar_export: function() {
|
||||
var export_view = new openerp.base.DataExport(this, this.dataset);
|
||||
export_view.start(false);
|
||||
export_view.start();
|
||||
},
|
||||
on_sidebar_translate: function() {
|
||||
},
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
</td>
|
||||
<td valign="top">
|
||||
<div id="oe_app" class="oe-application">
|
||||
<div style="width: 100%;">&nbsp;</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -79,7 +78,7 @@
|
|||
</table>
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="super_admin_pwd">Super admin password:</label></td>
|
||||
<td><label for="super_admin_pwd">Master password:</label></td>
|
||||
<td><input type="password" name="super_admin_pwd"
|
||||
class="required" autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
|
@ -104,7 +103,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="create_admin_pwd">Super admin password:</label></td>
|
||||
<td><label for="create_admin_pwd">Admin password:</label></td>
|
||||
<td><input type="password" name="create_admin_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -139,7 +138,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="drop_password">Password:</label></td>
|
||||
<td><label for="drop_password">Master Password:</label></td>
|
||||
<td><input type="password" name="drop_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -171,7 +170,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="backup_pwd">Password:</label></td>
|
||||
<td><label for="backup_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="backup_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -196,7 +195,7 @@
|
|||
autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="restore_pwd">Password:</label></td>
|
||||
<td><label for="restore_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="restore_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -214,23 +213,23 @@
|
|||
<table width="100%">
|
||||
<tr>
|
||||
<td class="option_string">
|
||||
CHANGE DATABASE PASSWORD
|
||||
CHANGE MASTER PASSWORD
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="old_pwd">Old password:</label></td>
|
||||
<td><label for="old_pwd">Master password:</label></td>
|
||||
<td><input type="password" name="old_pwd" class="required"
|
||||
minlength="1" autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="new_pwd">New password:</label></td>
|
||||
<td><label for="new_pwd">New master password:</label></td>
|
||||
<td><input type="password" name="new_pwd" class="required"
|
||||
minlength="1"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="confirm_pwd">Confirm password:</label></td>
|
||||
<td><label for="confirm_pwd">Confirm new master password:</label></td>
|
||||
<td><input type="password" name="confirm_pwd" class="required"
|
||||
equalTo="input[name=new_pwd]" minlength="1"/></td>
|
||||
</tr>
|
||||
|
@ -458,6 +457,41 @@
|
|||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="TreeView">
|
||||
<h2 class="oe_view_title"><t t-esc="title"/></h2>
|
||||
<select t-if="toolbar" style="width: 30%">
|
||||
</select>
|
||||
<table class="oe-treeview-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
class="treeview-header">
|
||||
<t t-esc="fields[field.attrs.name].string" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
<tr t-name="TreeView.rows"
|
||||
t-foreach="records" t-as="record"
|
||||
t-att-id="'treerow_' + record.id"
|
||||
t-att-data-id="record.id" t-att-data-level="level + 1">
|
||||
<t t-set="children" t-value="record[children_field]"/>
|
||||
<t t-set="has_children" t-value="children and children.length"/>
|
||||
|
||||
<td t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
t-att-data-id="record.id"
|
||||
t-att-style="!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px' : undefined"
|
||||
t-att-class="!field_index and has_children ? 'treeview-tr' : 'treeview-td'">
|
||||
<span t-if="!field.attrs.modifiers.invisible">
|
||||
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<table t-name="ListView" class="oe-listview-content">
|
||||
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
|
||||
<thead class="ui-widget-header">
|
||||
|
@ -522,14 +556,9 @@
|
|||
</tfoot>
|
||||
</table>
|
||||
<t t-name="ListView.rows" t-foreach="rows" t-as="row">
|
||||
<t t-call="ListView.row">
|
||||
<t t-set="style" t-value="null"/>
|
||||
<t-if test="row.color">
|
||||
<t t-set="style" t-value="'color: ' + row.color"/>
|
||||
</t-if>
|
||||
</t>
|
||||
<t t-call="ListView.row"/>
|
||||
</t>
|
||||
<tr t-name="ListView.row" t-att-style="style" t-att-class="row_parity"
|
||||
<tr t-name="ListView.row" t-att-class="row_parity"
|
||||
t-att-data-index="row_index">
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<td t-if="column.meta">
|
||||
|
@ -943,22 +972,6 @@
|
|||
<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] || ''"
|
||||
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined"/>
|
||||
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">
|
||||
|
@ -1110,11 +1123,17 @@
|
|||
</t>
|
||||
<t t-name="SelectCreatePopup.search.buttons">
|
||||
<button type="button" class="oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
|
||||
<button type="button" class="oe_selectcreatepopup-search-close">Close</button>
|
||||
<button type="button" class="oe_selectcreatepopup-search-close">Cancel</button>
|
||||
</t>
|
||||
<t t-name="SelectCreatePopup.form.buttons">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save</button>
|
||||
<button type="button" class="oe_selectcreatepopup-form-close">Close</button>
|
||||
<t t-if="widget.options.disable_multiple_selection">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save</button>
|
||||
</t>
|
||||
<t t-if="! widget.options.disable_multiple_selection">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save-new">Save & New</button>
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save & Close</button>
|
||||
</t>
|
||||
<button type="button" class="oe_selectcreatepopup-form-close">Cancel</button>
|
||||
</t>
|
||||
<t t-name="FormOpenPopup">
|
||||
<div t-att-id="element_id">
|
||||
|
@ -1123,7 +1142,7 @@
|
|||
</t>
|
||||
<t t-name="FormOpenPopup.form.buttons">
|
||||
<button type="button" class="oe_formopenpopup-form-save">Save</button>
|
||||
<button type="button" class="oe_formopenpopup-form-close">Close</button>
|
||||
<button type="button" class="oe_formopenpopup-form-close">Cancel</button>
|
||||
</t>
|
||||
<t t-name="ListView.row.frame" t-extend="WidgetFrame">
|
||||
<t t-jquery="tr">
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
$(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.core(openerp);
|
||||
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'}}});
|
||||
});
|
||||
});
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<script src="/base/static/src/js/boot.js"></script>
|
||||
<script src="/base/static/src/js/core.js"></script>
|
||||
<script src="/base/static/src/js/dates.js"></script>
|
||||
<script src="/base/static/src/js/formats.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>
|
||||
|
@ -39,6 +39,5 @@
|
|||
</body>
|
||||
<script type="text/javascript" src="/base/static/test/class.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>
|
||||
<script type="text/javascript" src="/base/static/test/form.js"></script>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -9,14 +9,23 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
// Dhtmlx scheduler ?
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.set_default_options(options);
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
this.domain = this.dataset.domain || [];
|
||||
this.context = this.dataset.context || {};
|
||||
this.has_been_loaded = $.Deferred();
|
||||
this.options = options || {};
|
||||
this.creating_event_id = null;
|
||||
this.dataset_events = [];
|
||||
if (this.options.action_views_ids.form) {
|
||||
this.form_dialog = new openerp.base_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
|
||||
this.form_dialog.start();
|
||||
}
|
||||
this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
|
||||
'#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
|
||||
'#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
|
||||
'#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ];
|
||||
},
|
||||
start: function() {
|
||||
this.rpc("/base_calendar/calendarview/load", {"model": this.model, "view_id": this.view_id, 'toolbar': true}, this.on_loaded);
|
||||
|
@ -44,14 +53,19 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
this.fields = this.fields_view.fields;
|
||||
|
||||
//* Calendar Fields *
|
||||
this.calendar_fields['date_start'] = {'name': this.date_start, 'kind': this.fields[this.date_start]['type']};
|
||||
this.calendar_fields.date_start = {'name': this.date_start, 'kind': this.fields[this.date_start].type};
|
||||
|
||||
if (this.date_delay) {
|
||||
this.calendar_fields['date_delay'] = {'name': this.date_delay, 'kind': this.fields[this.date_delay]['type']};
|
||||
if (this.fields[this.date_delay].type != 'float') {
|
||||
throw new Error("Calendar view has a 'date_delay' type != float");
|
||||
}
|
||||
this.calendar_fields.date_delay = {'name': this.date_delay, 'kind': this.fields[this.date_delay].type};
|
||||
}
|
||||
|
||||
if (this.date_stop) {
|
||||
this.calendar_fields['date_stop'] = {'name': this.date_stop, 'kind': this.fields[this.date_stop]['type']};
|
||||
this.calendar_fields.date_stop = {'name': this.date_stop, 'kind': this.fields[this.date_stop].type};
|
||||
}
|
||||
if (!this.date_delay && !this.date_stop) {
|
||||
throw new Error("Calendar view has none of the following attributes : 'date_stop', 'date_delay'");
|
||||
}
|
||||
|
||||
for (var fld = 0; fld < this.fields_view.arch.children.length; fld++) {
|
||||
|
@ -90,7 +104,8 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
scheduler.config.multi_day = true; //Multi day events are not rendered in daily and weekly views
|
||||
scheduler.config.start_on_monday = true;
|
||||
scheduler.config.scroll_hour = 8;
|
||||
scheduler.config.drag_resize = scheduler.config.drag_create = !!this.date_stop;
|
||||
scheduler.config.drag_resize = true;
|
||||
scheduler.config.drag_create = true;
|
||||
|
||||
// Initialize Sceduler
|
||||
this.mode = this.mode || 'month';
|
||||
|
@ -100,6 +115,8 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
scheduler.attachEvent('onEventAdded', this.do_create_event);
|
||||
scheduler.attachEvent('onEventDeleted', this.do_delete_event);
|
||||
scheduler.attachEvent('onEventChanged', this.do_save_event);
|
||||
scheduler.attachEvent('onDblClick', this.do_edit_event);
|
||||
scheduler.attachEvent('onBeforeLightbox', this.do_edit_event);
|
||||
|
||||
this.mini_calendar = scheduler.renderCalendar({
|
||||
container: this.sidebar.navigator.element_id,
|
||||
|
@ -116,25 +133,15 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
refresh_minical: function() {
|
||||
scheduler.updateCalendar(this.mini_calendar);
|
||||
},
|
||||
load_scheduler: function() {
|
||||
var self = this;
|
||||
this.dataset.read_slice([], 0, false, function(events) {
|
||||
if (self.session.locale_code) {
|
||||
// TODO: replace $LAB
|
||||
$LAB.setOptions({AlwaysPreserveOrder: true}).script([
|
||||
'/base_calendar/static/lib/dhtmlxScheduler/sources/locale_' + self.session.locale_code + '.js',
|
||||
'/base_calendar/static/lib/dhtmlxScheduler/sources/locale_recurring_' + self.session.locale_code + '.js'
|
||||
]).wait(function() {
|
||||
self.on_events_loaded(events);
|
||||
});
|
||||
} else {
|
||||
self.on_events_loaded(events);
|
||||
}
|
||||
});
|
||||
reload_event: function(id) {
|
||||
this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded);
|
||||
},
|
||||
on_events_loaded: function(events) {
|
||||
get_color: function(index) {
|
||||
index = index % this.COLOR_PALETTE.length;
|
||||
return this.COLOR_PALETTE[index];
|
||||
},
|
||||
on_events_loaded: function(events, fn_filter, no_filter_reload) {
|
||||
var self = this;
|
||||
scheduler.clearAll();
|
||||
|
||||
//To parse Events we have to convert date Format
|
||||
var res_events = [],
|
||||
|
@ -147,111 +154,81 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
break;
|
||||
}
|
||||
|
||||
if (this.color_field) {
|
||||
var filter = evt[this.color_field];
|
||||
if (filter) {
|
||||
var filter_item = {
|
||||
value: (typeof filter === 'object') ? filter[0] : filter,
|
||||
label: (typeof filter === 'object') ? filter[1] : filter
|
||||
}
|
||||
if (typeof(fn_filter) === 'function' && !fn_filter(filter_item.value)) {
|
||||
continue;
|
||||
}
|
||||
var filter_index = _.indexOf(sidebar_ids, filter_item.value);
|
||||
if (filter_index === -1) {
|
||||
evt.color = filter_item.color = this.get_color(sidebar_ids.length);
|
||||
sidebar_items.push(filter_item);
|
||||
sidebar_ids.push(filter_item.value);
|
||||
} else {
|
||||
evt.color = this.get_color(filter_index);
|
||||
}
|
||||
evt.textColor = '#ffffff';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fields[this.date_start]['type'] == 'date') {
|
||||
evt[this.date_start] = openerp.base.parse_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
if (this.date_stop && evt[this.date_stop] && this.fields[this.date_stop]['type'] == 'date') {
|
||||
evt[this.date_stop] = openerp.base.parse_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
if (this.color_field) {
|
||||
var user = evt[this.color_field];
|
||||
if (user) {
|
||||
if (_.indexOf(sidebar_ids, user[0]) === -1) {
|
||||
sidebar_items.push({
|
||||
id: user[0],
|
||||
name: user[1],
|
||||
// TODO: use color table
|
||||
color: '#dddddd'
|
||||
});
|
||||
sidebar_ids.push(user[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
res_events.push(this.convert_event(evt));
|
||||
}
|
||||
scheduler.parse(res_events, 'json');
|
||||
this.refresh_scheduler();
|
||||
this.refresh_minical();
|
||||
this.sidebar.responsible.on_events_loaded(sidebar_items);
|
||||
if (!no_filter_reload) {
|
||||
this.sidebar.responsible.on_events_loaded(sidebar_items);
|
||||
}
|
||||
},
|
||||
convert_event: function(event) {
|
||||
var starts = event[this.date_start],
|
||||
ends = event[this.date_delay] || 1,
|
||||
span = 0,
|
||||
convert_event: function(evt) {
|
||||
var date_start = openerp.base.parse_datetime(evt[this.date_start]),
|
||||
date_stop = this.date_stop ? openerp.base.parse_datetime(evt[this.date_stop]) : null,
|
||||
date_delay = evt[this.date_delay] || null,
|
||||
res_text = '',
|
||||
res_description = [];
|
||||
|
||||
var parse_start_date = openerp.base.parse_datetime(starts);
|
||||
if (event[this.date_stop]) {
|
||||
var parse_end_date = openerp.base.parse_datetime(event[this.date_stop]);
|
||||
}
|
||||
if (this.info_fields) {
|
||||
var fld = event[this.info_fields[0]];
|
||||
|
||||
if (typeof fld == 'object') {
|
||||
res_text = fld[fld.length -1];
|
||||
} else {
|
||||
res_text = fld;
|
||||
}
|
||||
var fld = evt[this.info_fields[0]];
|
||||
res_text = (typeof fld == 'object') ? fld[fld.length -1] : res_text = fld;
|
||||
|
||||
var sliced_info_fields = this.info_fields.slice(1);
|
||||
for (sl_fld in sliced_info_fields) {
|
||||
var slc_fld = event[sliced_info_fields[sl_fld]];
|
||||
|
||||
for (var sl_fld in sliced_info_fields) {
|
||||
var slc_fld = evt[sliced_info_fields[sl_fld]];
|
||||
if (typeof slc_fld == 'object') {
|
||||
res_description.push(slc_fld[slc_fld.length - 1]);
|
||||
} else {
|
||||
if(slc_fld) res_description.push(slc_fld);
|
||||
} else if (slc_fld) {
|
||||
res_description.push(slc_fld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (starts && ends) {
|
||||
var n = 0,
|
||||
h = ends;
|
||||
if (ends == this.day_length) {
|
||||
span = 1;
|
||||
} else if (ends > this.day_length) {
|
||||
n = ends / this.day_length;
|
||||
h = ends % this.day_length;
|
||||
n = parseInt(Math.floor(n));
|
||||
|
||||
if (h > 0) {
|
||||
span = n + 1;
|
||||
} else {
|
||||
span = n;
|
||||
}
|
||||
}
|
||||
var start = parse_start_date.setTime((parse_start_date.getTime() + (h * 60 * 60) + (n * 24 * 60 * 60)));
|
||||
ends = parse_start_date;
|
||||
if (!date_stop && date_delay) {
|
||||
date_stop = date_start.clone().addHours(date_delay);
|
||||
}
|
||||
|
||||
if (starts && this.date_stop) {
|
||||
ends = parse_end_date;
|
||||
if (event[this.date_stop] == undefined) {
|
||||
var start = parse_start_date.setTime((parse_start_date.getTime() + (h * 60 * 60) + (n * 24 * 60 * 60)));
|
||||
ends = parse_start_date;
|
||||
}
|
||||
var tds = parse_start_date.getTime(),
|
||||
tde = parse_end_date.getTime();
|
||||
|
||||
if (tds >= tde) {
|
||||
tde = tds + 60 * 60;
|
||||
parse_end_date.setTime(tde);
|
||||
ends = parse_end_date;
|
||||
}
|
||||
n = (tde - tds) / (60 * 60);
|
||||
if (n >= this.day_length) {
|
||||
span = Math.ceil(n / 24);
|
||||
}
|
||||
}
|
||||
return {
|
||||
'start_date': parse_start_date.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_date': ends.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
var r = {
|
||||
'start_date': date_start.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_date': date_stop.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'text': res_text,
|
||||
'id': event['id'],
|
||||
'id': evt.id,
|
||||
'title': res_description.join()
|
||||
}
|
||||
if (evt.color) {
|
||||
r.color = evt.color;
|
||||
}
|
||||
if (evt.textColor) {
|
||||
r.textColor = evt.textColor;
|
||||
}
|
||||
return r;
|
||||
},
|
||||
do_create_event: function(event_id, event_obj) {
|
||||
var self = this,
|
||||
|
@ -262,8 +239,10 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
scheduler.changeEventId(event_id, id);
|
||||
self.refresh_minical();
|
||||
}, function(r, event) {
|
||||
// TODO: open form view
|
||||
self.notification.warn(self.name, "Could not create event");
|
||||
self.creating_event_id = event_id;
|
||||
self.form_dialog.form.on_record_loaded(data);
|
||||
self.form_dialog.open();
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
do_save_event: function(event_id, event_obj) {
|
||||
|
@ -274,47 +253,62 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
});
|
||||
},
|
||||
do_delete_event: function(event_id, event_obj) {
|
||||
var self = this;
|
||||
// dhtmlx sends this event even when it does not exist in openerp.
|
||||
// Eg: use cancel in dhtmlx new event dialog
|
||||
if (_.indexOf(this.dataset.ids, event_id) > -1) {
|
||||
this.dataset.unlink(parseInt(event_id, 10, function() {
|
||||
if (_.indexOf(this.dataset.ids, parseInt(event_id, 10)) > -1) {
|
||||
this.dataset.unlink(parseInt(event_id, 10), function() {
|
||||
self.refresh_minical();
|
||||
}));
|
||||
});
|
||||
}
|
||||
},
|
||||
do_edit_event: function(event_id) {
|
||||
event_id = parseInt(event_id, 10);
|
||||
var index = _.indexOf(this.dataset.ids, event_id);
|
||||
if (index > -1) {
|
||||
this.dataset.index = index;
|
||||
this.form_dialog.form.do_show();
|
||||
this.form_dialog.open();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
get_event_data: function(event_obj) {
|
||||
var data = {
|
||||
name: event_obj.text
|
||||
};
|
||||
var date_format = this.calendar_fields.date_start.kind == 'time' ? 'HH:mm:ss' : 'yyyy-MM-dd HH:mm:ss';
|
||||
data[this.date_start] = event_obj.start_date.toString(date_format);
|
||||
data[this.date_start] = openerp.base.format_datetime(event_obj.start_date);
|
||||
if (this.date_stop) {
|
||||
data[this.date_stop] = event_obj.end_date.toString(date_format);
|
||||
data[this.date_stop] = openerp.base.format_datetime(event_obj.end_date);
|
||||
}
|
||||
if (this.date_delay) {
|
||||
var tds = (event_obj.start_date.getOrdinalNumber() / 1e3 >> 0) - (event_obj.start_date.getOrdinalNumber() < 0);
|
||||
var tde = (event_obj.end_date.getOrdinalNumber() / 1e3 >> 0) - (event_obj.end_date.getOrdinalNumber() < 0);
|
||||
var n = (tde - tds) / (60 * 60);
|
||||
if (n > this.day_length) {
|
||||
var d = Math.floor(n / 24),
|
||||
h = n % 24;
|
||||
n = d * this.day_length + h;
|
||||
}
|
||||
data[this.date_delay] = n;
|
||||
var diff_seconds = Math.round((event_obj.end_date.getTime() - event_obj.start_date.getTime()) / 1000);
|
||||
data[this.date_delay] = diff_seconds / 3600;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
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.context = self.context = results.context;
|
||||
self.dataset.domain = self.domain = results.domain;
|
||||
self.dataset.read_slice(_.keys(self.fields), 0, self.limit, self.on_events_loaded);
|
||||
scheduler.clearAll();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.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.context = self.context = results.context;
|
||||
self.dataset.domain = self.domain = results.domain;
|
||||
self.dataset.read_slice({
|
||||
fields: _.keys(self.fields),
|
||||
offset:0,
|
||||
limit: self.limit
|
||||
}, function(events) {
|
||||
self.dataset_events = events;
|
||||
self.on_events_loaded(events);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
do_show: function () {
|
||||
|
@ -331,53 +325,39 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base_calendar.CalendarFormDialog = openerp.base.Dialog.extend({
|
||||
init: function(view, options, view_id, dataset) {
|
||||
this._super(view, options);
|
||||
this.dataset = dataset;
|
||||
this.view_id = view_id;
|
||||
this.view = view;
|
||||
},
|
||||
popup_event: function(event_id) {
|
||||
var self = this;
|
||||
if (event_id) event_id = parseInt(event_id, 10);
|
||||
var action = {
|
||||
res_model: this.dataset.model,
|
||||
res_id: event_id,
|
||||
views: [[false, 'form']],
|
||||
type: 'ir.actions.act_window',
|
||||
view_type: 'form',
|
||||
view_mode: 'form',
|
||||
flags : {
|
||||
search_view: false,
|
||||
sidebar : false,
|
||||
views_switcher : false,
|
||||
action_buttons : false,
|
||||
pager: false
|
||||
}
|
||||
}
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = $('<div>', {
|
||||
'id': element_id
|
||||
}).dialog({
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("destroy");
|
||||
},
|
||||
Save: function() {
|
||||
var view_manager = action_manager.viewmanager;
|
||||
var _dialog = this;
|
||||
view_manager.views[view_manager.active_view].controller.do_save(function(r) {
|
||||
$(_dialog).dialog("destroy");
|
||||
// self.start();
|
||||
self.load_scheduler();
|
||||
})
|
||||
}
|
||||
}
|
||||
start: function() {
|
||||
this._super();
|
||||
this.form = new openerp.base.FormView(this, this.element_id, this.dataset, this.view_id, {
|
||||
sidebar: false,
|
||||
pager: false
|
||||
});
|
||||
var action_manager = new openerp.base.ActionManager(this, element_id);
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
//Default_get
|
||||
if (!event_id) {
|
||||
this.dataset.index = null;
|
||||
this.form.start();
|
||||
this.form.on_created.add_last(this.on_form_dialog_saved);
|
||||
this.form.on_saved.add_last(this.on_form_dialog_saved);
|
||||
},
|
||||
on_form_dialog_saved: function() {
|
||||
var id = this.dataset.ids[this.dataset.index];
|
||||
if (this.view.creating_event_id) {
|
||||
scheduler.changeEventId(this.view.creating_event_id, id);
|
||||
this.view.creating_event_id = null;
|
||||
}
|
||||
this.view.reload_event(id);
|
||||
this.close();
|
||||
},
|
||||
on_close: function() {
|
||||
if (this.view.creating_event_id) {
|
||||
scheduler.deleteEvent(this.view.creating_event_id);
|
||||
this.view.creating_event_id = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -386,10 +366,25 @@ openerp.base_calendar.SidebarResponsible = openerp.base.Widget.extend({
|
|||
init: function(parent, element_id, view) {
|
||||
this._super(parent, element_id);
|
||||
this.view = view;
|
||||
this.$element.delegate('input:checkbox', 'change', this.on_filter_click);
|
||||
},
|
||||
on_events_loaded: function(users) {
|
||||
this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { users : users }));
|
||||
// TODO: bind checkboxes reload sheduler
|
||||
on_events_loaded: function(filters) {
|
||||
this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
|
||||
},
|
||||
on_filter_click: function(e) {
|
||||
var responsibles = [],
|
||||
$e = $(e.target);
|
||||
this.$element.find('div.oe_calendar_responsible input:checked').each(function() {
|
||||
responsibles.push($(this).val());
|
||||
});
|
||||
scheduler.clearAll();
|
||||
if (responsibles.length) {
|
||||
this.view.on_events_loaded(this.view.dataset_events, function(filter_value) {
|
||||
return _.indexOf(responsibles, filter_value.toString()) > -1;
|
||||
}, true);
|
||||
} else {
|
||||
this.view.on_events_loaded(this.view.dataset_events, false, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -401,7 +396,6 @@ openerp.base_calendar.SidebarNavigator = openerp.base.Widget.extend({
|
|||
on_events_loaded: function(events) {
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// DEBUG_RPC:rpc.request:('execute', 'addons-dsh-l10n_us', 1, '*', ('ir.filters', 'get_filters', u'res.partner'))
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="CalendarView.sidebar.responsible">
|
||||
<div t-foreach="users" t-as="user" class="oe_calendar_responsible" t-attf-style="background: #{user.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="user.id"/>
|
||||
<span><t t-esc="user.name"/></span>
|
||||
<div t-foreach="filters" t-as="filter" class="oe_calendar_responsible" t-attf-style="background: #{filter.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="filter.value"/>
|
||||
<span><t t-esc="filter.label"/></span>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -228,9 +228,9 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
|||
action_buttons : false,
|
||||
pager: false
|
||||
};
|
||||
new openerp.base.ActionManager(
|
||||
this, this.view.element_id + '_action_' + action.id)
|
||||
.do_action(action);
|
||||
var am = new openerp.base.ActionManager(this);
|
||||
am.appendTo($("#"+this.view.element_id + '_action_' + action.id));
|
||||
am.do_action(action);
|
||||
},
|
||||
render: function() {
|
||||
// We should start with three columns available
|
||||
|
@ -244,8 +244,8 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
|||
return QWeb.render(this.template, this);
|
||||
},
|
||||
do_reload: function() {
|
||||
this.view.view_manager.stop();
|
||||
this.view.view_manager.start();
|
||||
this.view.widget_parent.stop();
|
||||
this.view.widget_parent.start();
|
||||
}
|
||||
});
|
||||
openerp.base.form.DashBoardLegacy = openerp.base.form.DashBoard.extend({
|
||||
|
@ -290,7 +290,7 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
|||
this.dataset.domain = [['type', '=', 'manual']];
|
||||
},
|
||||
start: function () {
|
||||
$.when(this.dataset.read_slice(['state', 'action_id', 'category_id']),
|
||||
$.when(this.dataset.read_slice({fields: ['state', 'action_id', 'category_id']}),
|
||||
this.dataset.call('progress'))
|
||||
.then(this.on_records_loaded);
|
||||
},
|
||||
|
@ -333,7 +333,6 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
|||
type: 'object',
|
||||
name: 'action_launch'
|
||||
}, self.dataset,
|
||||
self.session.action_manager,
|
||||
$(this).data('id'), function () {
|
||||
// after action popup closed, refresh configuration
|
||||
// thingie
|
||||
|
@ -354,8 +353,8 @@ openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
|||
start: function () {
|
||||
var self = this;
|
||||
this.dataset.read_slice(
|
||||
['name', 'web_icon_data', 'web_icon_hover_data'],
|
||||
null, null, function (applications) {
|
||||
{fields: ['name', 'web_icon_data', 'web_icon_hover_data']},
|
||||
function (applications) {
|
||||
// Create a matrix of 3*x applications
|
||||
var rows = [];
|
||||
while (applications.length) {
|
||||
|
@ -385,7 +384,8 @@ openerp.base_dashboard.Widgets = openerp.base.View.extend({
|
|||
this.widgets = new openerp.base.DataSetSearch(this, 'res.widget');
|
||||
},
|
||||
start: function () {
|
||||
this.user_widgets.read_slice(['widget_id', 'user_id'], null, null,
|
||||
this.user_widgets.read_slice(
|
||||
{fields: ['widget_id', 'user_id']},
|
||||
this.on_widgets_list_loaded);
|
||||
},
|
||||
on_widgets_list_loaded: function (user_widgets) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -86,7 +86,7 @@ openerp.base_default_home = function (openerp) {
|
|||
$.blockUI({
|
||||
message: '<img src="/base_default_home/static/src/img/throbber.gif">'
|
||||
});
|
||||
Modules.read_slice(['id'], null, null, function (records) {
|
||||
Modules.read_slice({fields: ['id']}, function (records) {
|
||||
if (!(records.length === 1)) { return; }
|
||||
Modules.call('state_update',
|
||||
[_.pluck(records, 'id'), 'to install', ['uninstalled']],
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
/*---------------------------------------------------------
|
||||
* OpenERP base_gantt
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base_gantt = function (openerp) {
|
||||
QWeb.add_template('/base_gantt/static/src/xml/base_gantt.xml');
|
||||
openerp.base.views.add('gantt', 'openerp.base_gantt.GanttView');
|
||||
openerp.base_gantt.GanttView = openerp.base.Widget.extend({
|
||||
openerp.base_gantt.GanttView = openerp.base.View.extend({
|
||||
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager;
|
||||
init: function(parent, element_id, dataset, view_id) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
@ -29,7 +27,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
this.calendar_fields = {};
|
||||
this.info_fields = [];
|
||||
this.domain = this.dataset._domain ? this.dataset._domain: [];
|
||||
this.context = {};
|
||||
this.context = this.dataset.context || {};
|
||||
},
|
||||
|
||||
start: function() {
|
||||
|
@ -52,8 +50,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
this.color_field = this.fields_view.arch.attrs.color;
|
||||
this.day_length = this.fields_view.arch.attrs.day_length || 8;
|
||||
this.colors = this.fields_view.arch.attrs.colors;
|
||||
|
||||
this.text = this.fields_view.arch.children[0].children[0].attrs.name;
|
||||
var arch_children = this.fields_view.arch.children[0];
|
||||
this.text = arch_children.children[0] ? arch_children.children[0].attrs.name : arch_children.attrs.name;
|
||||
this.parent = this.fields_view.arch.children[0].attrs.link;
|
||||
|
||||
this.format = "yyyy-MM-dd";
|
||||
|
@ -81,7 +79,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
get_events: function() {
|
||||
|
||||
var self = this;
|
||||
this.dataset.read_slice(false, false, false, function(result) {
|
||||
this.dataset.read_slice({}, function(result) {
|
||||
self.load_event(result);
|
||||
});
|
||||
|
||||
|
@ -100,7 +98,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
|
||||
if (result.length != 0){
|
||||
var show_event = [];
|
||||
for (i in result){
|
||||
for (var i in result){
|
||||
var res = result[i];
|
||||
if (res[this.date_start] != false){
|
||||
|
||||
|
@ -132,7 +130,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
var child_event = {};
|
||||
var temp_id = "";
|
||||
var final_events = [];
|
||||
for (i in show_event) {
|
||||
for (var i in show_event) {
|
||||
|
||||
var res = show_event[i];
|
||||
|
||||
|
@ -161,11 +159,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
if (duration == false)
|
||||
duration = 0
|
||||
|
||||
if (self.grp.length == 0){
|
||||
self.grp.push({'group_by' : this.parent})
|
||||
}
|
||||
if (self.grp != undefined){
|
||||
for (j in self.grp){
|
||||
if (self.grp.length){
|
||||
for (var j in self.grp){
|
||||
var grp_key = res[self.grp[j]['group_by']];
|
||||
if (typeof(grp_key) == "object"){
|
||||
grp_key = res[self.grp[j]['group_by']][1];
|
||||
|
@ -175,7 +170,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
}
|
||||
|
||||
if (grp_key == false){
|
||||
grp_key = "False";
|
||||
grp_key = "Undefined";
|
||||
}
|
||||
|
||||
if (j == 0){
|
||||
|
@ -207,9 +202,17 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
all_events[id] = {'parent': temp_id, 'evt':[id , text, start_date, duration, 100, "", color_box[color]]};
|
||||
final_events.push(id);
|
||||
}
|
||||
else {
|
||||
if (i == 0) {
|
||||
var mod_id = "_" + i;
|
||||
all_events[mod_id] = {'parent': "", 'evt': [mod_id, this.name, start_date, start_date, 100, "", "white"]};
|
||||
}
|
||||
all_events[id] = {'parent': mod_id, 'evt':[id , text, start_date, duration, 100, "", color_box[color]]};
|
||||
final_events.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (i in final_events){
|
||||
for (var i in final_events){
|
||||
var evt_id = final_events[i];
|
||||
var evt_date = all_events[evt_id]['evt'][2];
|
||||
while (all_events[evt_id]['parent'] != "") {
|
||||
|
@ -225,7 +228,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
var evt_duration = "";
|
||||
var evt_end_date = "";
|
||||
|
||||
for (i in final_events){
|
||||
for (var i in final_events){
|
||||
evt_id = final_events[i];
|
||||
evt_date = all_events[evt_id]['evt'][2];
|
||||
evt_duration = all_events[evt_id]['evt'][3];
|
||||
|
@ -242,42 +245,27 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
}
|
||||
}
|
||||
|
||||
for (j in self.grp){
|
||||
for (i in all_events){
|
||||
res = all_events[i];
|
||||
if ((typeof(res['evt'][3])) == "object"){
|
||||
res['evt'][3] = self.hours_between(res['evt'][2],res['evt'][3]);
|
||||
}
|
||||
|
||||
k = res['evt'][0].toString().indexOf('_');
|
||||
if (k != -1){
|
||||
if (res['evt'][0].substring(k) == "_"+j){
|
||||
if (j == 0){
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
project.addTask(task);
|
||||
} else {
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var j in self.grp) {
|
||||
self.render_events(all_events, j);
|
||||
}
|
||||
for (i in final_events){
|
||||
|
||||
if (!self.grp.length) {
|
||||
self.render_events(all_events, 0);
|
||||
}
|
||||
|
||||
for (var i in final_events){
|
||||
evt_id = final_events[i];
|
||||
res = all_events[evt_id];
|
||||
|
||||
task=new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
|
||||
oth_hgt = 264;
|
||||
min_hgt = 150;
|
||||
name_min_wdt = 150;
|
||||
gantt_hgt = jQuery(window).height() - oth_hgt;
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
var oth_hgt = 264;
|
||||
var min_hgt = 150;
|
||||
var name_min_wdt = 150;
|
||||
var gantt_hgt = jQuery(window).height() - oth_hgt;
|
||||
var search_wdt = jQuery("#oe_app_search").width();
|
||||
|
||||
if (gantt_hgt > min_hgt){
|
||||
jQuery('#GanttDiv').height(gantt_hgt).width(search_wdt);
|
||||
|
@ -291,13 +279,13 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_resize_drag_end(task, "drag");});
|
||||
ganttChartControl.attachEvent("onTaskDblClick", function(task) {self.open_popup(task);});
|
||||
|
||||
taskdiv = jQuery("div.taskPanel").parent();
|
||||
var taskdiv = jQuery("div.taskPanel").parent();
|
||||
taskdiv.addClass('ganttTaskPanel');
|
||||
taskdiv.prev().addClass('ganttDayPanel');
|
||||
$gantt_panel = jQuery(".ganttTaskPanel , .ganttDayPanel");
|
||||
var $gantt_panel = jQuery(".ganttTaskPanel , .ganttDayPanel");
|
||||
|
||||
ganttrow = jQuery('.taskPanel').closest('tr');
|
||||
gtd = ganttrow.children(':first-child');
|
||||
var ganttrow = jQuery('.taskPanel').closest('tr');
|
||||
var gtd = ganttrow.children(':first-child');
|
||||
gtd.children().addClass('task-name');
|
||||
|
||||
jQuery(".toggle-sidebar").click(function(e) {
|
||||
|
@ -319,9 +307,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
$gantt_panel.width(1);
|
||||
jQuery(".ganttTaskPanel").parent().width(1);
|
||||
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
day_wdt = jQuery(".ganttDayPanel").children().children().width();
|
||||
name_wdt = jQuery('.task-name').width();
|
||||
var search_wdt = jQuery("#oe_app_search").width();
|
||||
var day_wdt = jQuery(".ganttDayPanel").children().children().width();
|
||||
jQuery('#GanttDiv').css('width','100%');
|
||||
|
||||
if (search_wdt - day_wdt <= name_min_wdt){
|
||||
|
@ -345,7 +332,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
|
||||
var self = this;
|
||||
|
||||
dat = this.convert_str_date(dat);
|
||||
var dat = this.convert_str_date(dat);
|
||||
|
||||
var day = Math.floor(duration/self.day_length);
|
||||
var hrs = duration % self.day_length;
|
||||
|
@ -356,47 +343,98 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
return dat;
|
||||
},
|
||||
|
||||
hours_between: function(date1, date2) {
|
||||
hours_between: function(date1, date2, parent_task) {
|
||||
|
||||
var ONE_DAY = 1000 * 60 * 60 * 24;
|
||||
var date1_ms = date1.getTime();
|
||||
var date2_ms = date2.getTime();
|
||||
var difference_ms = Math.abs(date1_ms - date2_ms);
|
||||
|
||||
d = Math.floor(difference_ms / ONE_DAY);
|
||||
h = (difference_ms % ONE_DAY)/(1000 * 60 * 60);
|
||||
num = (d * this.day_length) + h;
|
||||
var d = parent_task? Math.ceil(difference_ms / ONE_DAY) : Math.floor(difference_ms / ONE_DAY);
|
||||
var h = (difference_ms % ONE_DAY)/(1000 * 60 * 60);
|
||||
var num = (d * this.day_length) + h;
|
||||
return parseFloat(num.toFixed(2));
|
||||
|
||||
},
|
||||
|
||||
render_events : function(all_events, j) {
|
||||
|
||||
var self = this;
|
||||
for (var i in all_events){
|
||||
var res = all_events[i];
|
||||
if ((typeof(res['evt'][3])) == "object"){
|
||||
res['evt'][3] = self.hours_between(res['evt'][2],res['evt'][3], true);
|
||||
}
|
||||
|
||||
k = res['evt'][0].toString().indexOf('_');
|
||||
|
||||
if (k != -1) {
|
||||
if (res['evt'][0].substring(k) == "_"+j){
|
||||
if (j == 0){
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
project.addTask(task);
|
||||
} else {
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
open_popup : function(task) {
|
||||
var event_id = task.getId();
|
||||
|
||||
if(event_id.toString().search("_") != -1)
|
||||
return;
|
||||
if (event_id) {
|
||||
event_id = parseInt(event_id, 10);
|
||||
var dataset_event_index = jQuery.inArray(event_id, this.ids);
|
||||
} else {
|
||||
var dataset_event_index = null;
|
||||
if(event_id) event_id = parseInt(event_id, 10);
|
||||
|
||||
var action = {
|
||||
"res_model": this.dataset.model,
|
||||
"res_id": event_id,
|
||||
"views":[[false,"form"]],
|
||||
"type":"ir.actions.act_window",
|
||||
"view_type":"form",
|
||||
"view_mode":"form"
|
||||
}
|
||||
this.dataset.index = dataset_event_index;
|
||||
|
||||
action.flags = {
|
||||
search_view: false,
|
||||
sidebar : false,
|
||||
views_switcher : false,
|
||||
pager: false
|
||||
}
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = jQuery('<div>',
|
||||
{'id': element_id
|
||||
}).dialog({
|
||||
title: 'Gantt Chart',
|
||||
modal: true,
|
||||
minWidth: 800,
|
||||
position: 'top'
|
||||
});
|
||||
var event_form = new openerp.base.FormView(this.view_manager, this.session, element_id, this.dataset, false);
|
||||
event_form.start();
|
||||
var dialog = jQuery('<div>', {
|
||||
'id': element_id
|
||||
}).dialog({
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("destroy");
|
||||
},
|
||||
Save: function() {
|
||||
var view_manager = action_manager.viewmanager;
|
||||
var _dialog = this;
|
||||
view_manager.views[view_manager.active_view].controller.do_save(function(r) {
|
||||
$(_dialog).dialog("destroy");
|
||||
self.reload_gantt();
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
var action_manager = new openerp.base.ActionManager(this, element_id);
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
|
||||
//Default_get
|
||||
if(!event_id) action_manager.viewmanager.dataset.index = null;
|
||||
},
|
||||
|
||||
on_drag_start : function(task){
|
||||
st_date = task.getEST();
|
||||
var st_date = task.getEST();
|
||||
if(st_date.getHours()){
|
||||
self.hh = st_date.getHours();
|
||||
self.mm = st_date.getMinutes();
|
||||
|
@ -460,7 +498,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
|
||||
reload_gantt: function() {
|
||||
var self = this;
|
||||
this.dataset.read_slice(false, false, false, function(response) {
|
||||
this.dataset.read_slice({}, function(response) {
|
||||
ganttChartControl.clearAll();
|
||||
jQuery("#GanttDiv").children().remove();
|
||||
self.load_event(response);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -89,7 +89,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
|||
}
|
||||
this.dataset.domain = domain;
|
||||
this.dataset.context = this.view_manager.dataset.context;
|
||||
this.dataset.read_slice(_(this.fields).keys(), 0, false, function(res) {
|
||||
this.dataset.read_slice({fields: _(this.fields).keys()}, function(res) {
|
||||
self.schedule_chart(res);
|
||||
});
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
|||
}
|
||||
views.push(view);
|
||||
});
|
||||
this.session.action_manager.do_action({
|
||||
this.do_action({
|
||||
"res_model" : this.dataset.model,
|
||||
"domain" : this.dataset.domain,
|
||||
"views" : views,
|
||||
|
@ -468,9 +468,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
|||
}
|
||||
self.dataset.context = results.context;
|
||||
self.dataset.domain = results.domain;
|
||||
self.dataset.read_slice([], 0, false,function(response){
|
||||
self.load_chart(response);
|
||||
});
|
||||
self.dataset.read_slice({}, $.proxy(self, 'load_chart'));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2011 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
|
@ -12,7 +12,7 @@ openerp.web_mobile.FormView = openerp.base.Widget.extend({
|
|||
view_id = this.action.views[1][0];
|
||||
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.action.res_model, null, null);
|
||||
this.dataset.read_slice(false, false, false, function (result) {
|
||||
this.dataset.read_slice({}, function (result) {
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (result[i].id == id) {
|
||||
|
@ -101,4 +101,4 @@ openerp.web_mobile.FormView = openerp.base.Widget.extend({
|
|||
},
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
<script type="text/javascript" src="/base/static/src/js/base.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/dates.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/formats.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/list_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/form_mobile.js"></script>
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
[extractors]
|
||||
qweb = npybabel:extract_qweb
|
||||
[javascript: static/src/js/**.js]
|
||||
[qweb: static/src/xml/**.xml]
|
||||
|
|
@ -113,6 +113,98 @@ initializing the addon.
|
|||
Creating new standard roles
|
||||
---------------------------
|
||||
|
||||
Widget
|
||||
++++++
|
||||
|
||||
This is the base class for all visual components. It provides a number of
|
||||
services for the management of a DOM subtree:
|
||||
|
||||
* Rendering with QWeb
|
||||
|
||||
* Parenting-child relations
|
||||
|
||||
* Life-cycle management (including facilitating children destruction when a
|
||||
parent object is removed)
|
||||
|
||||
* DOM insertion, via jQuery-powered insertion methods. Insertion targets can
|
||||
be anything the corresponding jQuery method accepts (generally selectors,
|
||||
DOM nodes and jQuery objects):
|
||||
|
||||
:js:func:`~openerp.base.Widget.appendTo`
|
||||
Renders the widget and inserts it as the last child of the target, uses
|
||||
`.appendTo()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.prependTo`
|
||||
Renders the widget and inserts it as the first child of the target, uses
|
||||
`.prependTo()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.insertAfter`
|
||||
Renders the widget and inserts it as the preceding sibling of the target,
|
||||
uses `.insertAfter()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.insertBefore`
|
||||
Renders the widget and inserts it as the following sibling of the target,
|
||||
uses `.insertBefore()`_
|
||||
|
||||
:js:class:`~openerp.base.Widget` inherits from
|
||||
:js:class:`~openerp.base.SessionAware`, so subclasses can easily access the
|
||||
RPC layers.
|
||||
|
||||
Subclassing Widget
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the
|
||||
:js:func:`~openerp.base.Class.extend` method), and provides a number of
|
||||
abstract properties and concrete methods (which you may or may not want to
|
||||
override). Creating a subclass looks like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
var MyWidget = openerp.base.Widget.extend({
|
||||
// QWeb template to use when rendering the object
|
||||
template: "MyQWebTemplate",
|
||||
// autogenerated id prefix, specificity helps when debugging
|
||||
identifier_prefix: 'my-id-prefix-',
|
||||
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
// insert code to execute before rendering, for object
|
||||
// initialization
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
// post-rendering initialization code, at this point
|
||||
// ``this.$element`` has been initialized
|
||||
this.$element.find(".my_button").click(/* an example of event binding * /);
|
||||
|
||||
// if ``start`` is asynchronous, return a promise object so callers
|
||||
// know when the object is done initializing
|
||||
return this.rpc(/* … */)
|
||||
}
|
||||
});
|
||||
|
||||
The new class can then be used in the following manner:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// Create the instance
|
||||
var my_widget = new MyWidget(this);
|
||||
// Render and insert into DOM
|
||||
my_widget.appendTo(".some-div");
|
||||
|
||||
After these two lines have executed (and any promise returned by ``appendTo``
|
||||
has been resolved if needed), the widget is ready to be used.
|
||||
|
||||
If the widget is not needed anymore (because it's transient), simply terminate
|
||||
it:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
my_widget.stop();
|
||||
|
||||
will unbind all DOM events, remove the widget's content from the DOM and
|
||||
destroy all widget data.
|
||||
|
||||
Views
|
||||
+++++
|
||||
|
||||
|
@ -236,193 +328,6 @@ replace ``addons`` by the directory in which your own addon lives.
|
|||
and run ``nosetests addons`` instead of the ``unit2`` command,
|
||||
the result should be exactly the same.
|
||||
|
||||
APIs
|
||||
----
|
||||
|
||||
Javascript
|
||||
++++++++++
|
||||
|
||||
.. js:class:: openerp.base.Widget(view, node)
|
||||
|
||||
:param openerp.base.Controller view: The view to which the widget belongs
|
||||
:param Object node: the ``fields_view_get`` descriptor for the widget
|
||||
|
||||
.. js:attribute:: $element
|
||||
|
||||
The widget's root element as jQuery object
|
||||
|
||||
.. js:class:: openerp.base.DataSet(session, model)
|
||||
|
||||
:param openerp.base.Session session: the RPC session object
|
||||
:param String model: the model managed by this dataset
|
||||
|
||||
The DataSet is the abstraction for a sequence of records stored in
|
||||
database.
|
||||
|
||||
It provides interfaces for reading records based on search
|
||||
criteria, and for selecting and fetching records based on
|
||||
activated ids.
|
||||
|
||||
.. js:function:: fetch([offset][, limit])
|
||||
|
||||
:param Number offset: the index from which records should start
|
||||
being returned (section)
|
||||
:param Number limit: the maximum number of records to return
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Asynchronously fetches the records selected by the DataSet's
|
||||
domain and context, in the provided sort order if any.
|
||||
|
||||
Only fetches the fields selected by the DataSet.
|
||||
|
||||
On success, triggers :js:func:`on_fetch`
|
||||
|
||||
.. js:function:: on_fetch(records, event)
|
||||
|
||||
:param Array records: an array of
|
||||
:js:class:`openerp.base.DataRecord`
|
||||
matching the DataSet's selection
|
||||
:param event: a data holder letting the event handler fetch
|
||||
meta-informations about the event.
|
||||
:type event: OnFetchEvent
|
||||
|
||||
Fired after :js:func:`fetch` is done fetching the records
|
||||
selected by the DataSet.
|
||||
|
||||
.. js:function:: active_ids
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Asynchronously fetches the active records for this DataSet.
|
||||
|
||||
On success, triggers :js:func:`on_active_ids`
|
||||
|
||||
.. js:function:: on_active_ids(records)
|
||||
|
||||
:param Array records: an array of
|
||||
:js:class:`openerp.base.DataRecord`
|
||||
matching the currently active ids
|
||||
|
||||
Fired after :js:func:`active_ids` fetched the records matching
|
||||
the DataSet's active ids.
|
||||
|
||||
.. js:function:: active_id
|
||||
|
||||
:returns: the dataset instance in was called on
|
||||
|
||||
Asynchronously fetches the current active record.
|
||||
|
||||
On success, triggers :js:func:`on_active_id`
|
||||
|
||||
.. js:function:: on_active_id(record)
|
||||
|
||||
:param Object record: the record fetched by
|
||||
:js:func:`active_id`, or ``null``
|
||||
:type record: openerp.base.DataRecord
|
||||
|
||||
Fired after :js:func:`active_id` fetched the record matching
|
||||
the dataset's active id
|
||||
|
||||
.. js:function:: set(options)
|
||||
|
||||
:param Object options: the options to set on the dataset
|
||||
:type options: DataSetOptions
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Configures the data set by setting various properties on it
|
||||
|
||||
.. js:function:: prev
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id preceding the current one in the active ids
|
||||
sequence of the dataset.
|
||||
|
||||
If the current active id is at the start of the sequence,
|
||||
wraps back to the last id of the sequence.
|
||||
|
||||
.. js:function:: next
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id following the current one in the active ids
|
||||
sequence.
|
||||
|
||||
If the current active id is the last of the sequence, wraps
|
||||
back to the beginning of the active ids sequence.
|
||||
|
||||
.. js:function:: select(ids)
|
||||
|
||||
:param Array ids: the identifiers to activate on the dataset
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates all the ids specified in the dataset, resets the
|
||||
current active id to be the first id of the new sequence.
|
||||
|
||||
The internal order will be the same as the ids list provided.
|
||||
|
||||
.. js:function:: get_active_ids
|
||||
|
||||
:returns: the list of current active ids for the dataset
|
||||
|
||||
.. js:function:: activate(id)
|
||||
|
||||
:param Number id: the id to activate
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id provided in the dataset. If no ids are
|
||||
selected, selects the id in the dataset.
|
||||
|
||||
If ids are already selected and the provided id is not in that
|
||||
selection, raises an error.
|
||||
|
||||
.. js:function:: get_active_id
|
||||
|
||||
:returns: the dataset's current active id
|
||||
|
||||
Ad-hoc objects and structural types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These objects are not associated with any specific class, they're
|
||||
generally literal objects created on the spot. Names are merely
|
||||
convenient ways to refer to them and their properties.
|
||||
|
||||
.. js:class:: OnFetchEvent
|
||||
|
||||
.. js:attribute:: context
|
||||
|
||||
The context used for the :js:func:`fetch` call (domain set on
|
||||
the :js:class:`openerp.base.DataSet` when ``fetch`` was
|
||||
called)
|
||||
|
||||
.. js:attribute:: domain
|
||||
|
||||
The domain used for the :js:func:`fetch` call
|
||||
|
||||
.. js:attribute:: limit
|
||||
|
||||
The limit with which the original :js:func:`fetch` call was
|
||||
performed
|
||||
|
||||
.. js:attribute:: offset
|
||||
|
||||
The offset with which the original :js:func:`fetch` call was
|
||||
performed
|
||||
|
||||
.. js:attribute:: sort
|
||||
|
||||
The sorting criteria active on the
|
||||
:js:class:`openerp.base.DataSet` when :js:func:`fetch` was
|
||||
called
|
||||
|
||||
.. js:class:: DataSetOptions
|
||||
|
||||
.. js:attribute:: context
|
||||
|
||||
.. js:attribute:: domain
|
||||
|
||||
.. js:attribute:: sort
|
||||
|
||||
Python
|
||||
++++++
|
||||
|
||||
|
@ -499,3 +404,15 @@ Python
|
|||
|
||||
.. _promise object:
|
||||
http://api.jquery.com/deferred.promise/
|
||||
|
||||
.. _.appendTo():
|
||||
http://api.jquery.com/appendTo/
|
||||
|
||||
.. _.prependTo():
|
||||
http://api.jquery.com/prependTo/
|
||||
|
||||
.. _.insertAfter():
|
||||
http://api.jquery.com/insertAfter/
|
||||
|
||||
.. _.insertBefore():
|
||||
http://api.jquery.com/insertBefore/
|
||||
|
|
|
@ -374,11 +374,13 @@ Deletion can be overridden by replacing the
|
|||
calls :js:func:`~openerp.base.DataSet.unlink` in order to remove the records
|
||||
entirely.
|
||||
|
||||
.. note:: the list-wise deletion button (next to the record addition button)
|
||||
simply proxies to :js:func:`~openerp.base.ListView.do_delete` after
|
||||
obtaining all selected record ids, but it is possible to override it
|
||||
alone by replacing
|
||||
:js:func:`~openerp.base.ListView.do_delete_selected`.
|
||||
.. note::
|
||||
|
||||
the list-wise deletion button (next to the record addition button)
|
||||
simply proxies to :js:func:`~openerp.base.ListView.do_delete` after
|
||||
obtaining all selected record ids, but it is possible to override it
|
||||
alone by replacing
|
||||
:js:func:`~openerp.base.ListView.do_delete_selected`.
|
||||
|
||||
Internal API Doc
|
||||
----------------
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/sh
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
usage: $0 -a
|
||||
usage: $0 DIR OUTPUT_FILE
|
||||
|
||||
OPTIONS:
|
||||
-a recreate the .pot file for all addons
|
||||
-h print this message
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
do_all=
|
||||
|
||||
while getopts "a" opt
|
||||
do
|
||||
case "$opt" in
|
||||
a)
|
||||
do_all=true;;
|
||||
h)
|
||||
usage;;
|
||||
\?)
|
||||
usage;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ -n "$do_all" ]
|
||||
then
|
||||
echo "Extracting all the translations"
|
||||
executable=$0
|
||||
extract_module() {
|
||||
$executable addons/$1 addons/$1/po/$1.pot
|
||||
}
|
||||
extract_module base
|
||||
extract_module base_calendar
|
||||
extract_module base_dashboard
|
||||
extract_module base_default_home
|
||||
extract_module base_diagram
|
||||
extract_module base_gantt
|
||||
extract_module base_graph
|
||||
extract_module base_hello
|
||||
extract_module web_chat
|
||||
extract_module web_mobile
|
||||
elif [ -n "$2" ]
|
||||
then
|
||||
./npybabel.py extract -F babel.cfg -o $2 -k _t --no-default-keywords $1
|
||||
else
|
||||
usage
|
||||
fi
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'Babel==0.9.6','console_scripts','pybabel'
|
||||
__requires__ = 'Babel==0.9.6'
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
import re
|
||||
import json
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(
|
||||
load_entry_point('Babel==0.9.6', 'console_scripts', 'pybabel')()
|
||||
)
|
||||
|
||||
QWEB_EXPR = re.compile(r"""(?:\< *t\-tr *\>(.*?)\< *\/t\-tr *\>)|(?:\_t *\( *((?:"(?:[^"\\]|\\.)*")|(?:'(?:[^'\\]|\\.)*')) *\))""")
|
||||
XML_GROUP = 1
|
||||
JS_GROUP = 2
|
||||
|
||||
def extract_qweb(fileobj, keywords, comment_tags, options):
|
||||
"""Extract messages from XXX files.
|
||||
:param fileobj: the file-like object the messages should be extracted
|
||||
from
|
||||
:param keywords: a list of keywords (i.e. function names) that should
|
||||
be recognized as translation functions
|
||||
:param comment_tags: a list of translator tags to search for and
|
||||
include in the results
|
||||
:param options: a dictionary of additional options (optional)
|
||||
:return: an iterator over ``(lineno, funcname, message, comments)``
|
||||
tuples
|
||||
:rtype: ``iterator``
|
||||
"""
|
||||
content = fileobj.read()
|
||||
found = QWEB_EXPR.finditer(content)
|
||||
result = []
|
||||
index = 0
|
||||
line_nbr = 0
|
||||
for f in found:
|
||||
group = XML_GROUP if f.group(XML_GROUP) else JS_GROUP
|
||||
mes = f.group(group)
|
||||
if group == JS_GROUP:
|
||||
mes = json.loads(mes)
|
||||
while index < f.start():
|
||||
if content[index] == "\n":
|
||||
line_nbr += 1
|
||||
index += 1
|
||||
result.append((line_nbr, None, mes, ""))
|
||||
return result
|
|
@ -1,174 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# setup from TinERP
|
||||
# taken from straw http://www.nongnu.org/straw/index.html
|
||||
# taken from gnomolicious http://www.nongnu.org/gnomolicious/
|
||||
# adapted by Nicolas Évrard <nicoe@altern.org>
|
||||
#
|
||||
# doc/migrate is not included since about 6.1-dev
|
||||
# doc/tests is not included
|
||||
# python25-compat/*py should be in the openerp (and imported appropriately)
|
||||
|
||||
import sys
|
||||
import os
|
||||
from os.path import join, isfile
|
||||
import glob
|
||||
import re
|
||||
import sys
|
||||
from setuptools import setup
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
name = 'openerp-web-proto'
|
||||
version = '6.0.1'
|
||||
description = "Web Client of OpenERP, the Enterprise Management Software"
|
||||
long_description = "OpenERP Web is the web client of the OpenERP, a free enterprise management software"
|
||||
author = "OpenERP S.A."
|
||||
author_email = "info@openerp.com"
|
||||
support_email = 'support@openerp.com'
|
||||
url = "http://www.openerp.com/"
|
||||
download_url = ''
|
||||
license = "OEPL"
|
||||
|
||||
# Backports os.walk with followlinks from python 2.6.
|
||||
# Needed to add all addons files to data_files for Windows packaging.
|
||||
def walk_followlinks(top, topdown=True, onerror=None, followlinks=False):
|
||||
from os.path import join, isdir, islink
|
||||
from os import listdir, error
|
||||
|
||||
try:
|
||||
names = listdir(top)
|
||||
except error, err:
|
||||
if onerror is not None:
|
||||
onerror(err)
|
||||
return
|
||||
|
||||
dirs, nondirs = [], []
|
||||
for name in names:
|
||||
if isdir(join(top, name)):
|
||||
dirs.append(name)
|
||||
else:
|
||||
nondirs.append(name)
|
||||
|
||||
if topdown:
|
||||
yield top, dirs, nondirs
|
||||
for name in dirs:
|
||||
path = join(top, name)
|
||||
if followlinks or not islink(path):
|
||||
for x in walk_followlinks(path, topdown, onerror, followlinks):
|
||||
yield x
|
||||
if not topdown:
|
||||
yield top, dirs, nondirs
|
||||
|
||||
if sys.version_info < (2, 6):
|
||||
os.walk = walk_followlinks
|
||||
|
||||
py2exe_keywords = {}
|
||||
py2exe_data_files = []
|
||||
if os.name == 'nt':
|
||||
version_dash_incompatible = False
|
||||
if 'bdist_rpm' in sys.argv:
|
||||
version_dash_incompatible = True
|
||||
try:
|
||||
import py2exe
|
||||
py2exe_keywords['console'] = [
|
||||
{ "script": "openerp-server",
|
||||
"icon_resources": [(1, join("pixmaps","openerp-icon.ico"))],
|
||||
}]
|
||||
py2exe_keywords['options'] = {
|
||||
"py2exe": {
|
||||
"skip_archive": 1,
|
||||
"optimize": 2,
|
||||
"dist_dir": 'dist',
|
||||
"packages": [
|
||||
"lxml", "lxml.builder", "lxml._elementpath", "lxml.etree",
|
||||
"lxml.objectify", "decimal", "xml", "xml", "xml.dom", "xml.xpath",
|
||||
"encodings", "dateutil", "pychart", "PIL", "pyparsing",
|
||||
"pydot", "asyncore","asynchat", "reportlab", "vobject",
|
||||
"HTMLParser", "select", "mako", "poplib",
|
||||
"imaplib", "smtplib", "email", "yaml", "DAV",
|
||||
"uuid", "commands", "openerp",
|
||||
],
|
||||
"excludes" : ["Tkconstants","Tkinter","tcl"],
|
||||
}
|
||||
}
|
||||
# TODO is it still necessary now that we don't use the library.zip file?
|
||||
def data_files():
|
||||
'''For Windows, we consider all the addons as data files.
|
||||
It seems also that package_data below isn't honored by py2exe.'''
|
||||
files = []
|
||||
os.chdir('openerp')
|
||||
for (dp, dn, names) in os.walk('addons'):
|
||||
files.append((join('openerp',dp), map(lambda x: join('openerp', dp, x), names)))
|
||||
os.chdir('..')
|
||||
files.append(('openerp', [join('openerp', 'import_xml.rng'),]))
|
||||
from py2exe_utils import opts
|
||||
version_dash_incompatible = True
|
||||
except ImportError:
|
||||
opts = {}
|
||||
if version_dash_incompatible:
|
||||
version = version.split('-')[0]
|
||||
|
||||
# copy pytz/timzeone
|
||||
# TODO check if we have to also copy dateutil's timezone data.
|
||||
import pytz
|
||||
# Make sure the layout of pytz hasn't changed
|
||||
assert (pytz.__file__.endswith('__init__.pyc') or
|
||||
pytz.__file__.endswith('__init__.py')), pytz.__file__
|
||||
pytz_dir = os.path.dirname(pytz.__file__)
|
||||
FILE_PATTERNS = \
|
||||
r'.+\.(py|cfg|po|pot|mo|txt|rst|gif|png|jpg|ico|mako|html|js|css|htc|swf)$'
|
||||
def find_data_files(source, patterns=FILE_PATTERNS):
|
||||
file_matcher = re.compile(patterns, re.I)
|
||||
out = []
|
||||
for base, _, files in os.walk(source):
|
||||
cur_files = []
|
||||
for f in files:
|
||||
if file_matcher.match(f):
|
||||
cur_files.append(os.path.join(base, f))
|
||||
if cur_files:
|
||||
out.append(
|
||||
(base, cur_files))
|
||||
|
||||
saved_dir = os.getcwd()
|
||||
os.chdir(pytz_dir)
|
||||
for dp, dn, names in os.walk('zoneinfo'):
|
||||
files.append((join('pytz',dp), map(lambda x: join(pytz_dir, dp, x), names)))
|
||||
os.chdir(saved_dir)
|
||||
return out
|
||||
|
||||
return files
|
||||
py2exe_data_files = data_files()
|
||||
|
||||
execfile(join('openerp', 'release.py'))
|
||||
|
||||
setup(name = name,
|
||||
version = version,
|
||||
description = description,
|
||||
long_description = long_desc,
|
||||
url = url,
|
||||
author = author,
|
||||
author_email = author_email,
|
||||
classifiers = filter(None, classifiers.split("\n")),
|
||||
license = license,
|
||||
data_files = [
|
||||
(join('man', 'man1'), ['man/openerp-server.1']),
|
||||
(join('man', 'man5'), ['man/openerp_serverrc.5']),
|
||||
('doc', filter(isfile, glob.glob('doc/*'))),
|
||||
] + py2exe_data_files,
|
||||
scripts = ['openerp-server'],
|
||||
packages = find_packages(),
|
||||
include_package_data = True,
|
||||
package_data = {
|
||||
'': ['*.yml', '*.xml', '*.po', '*.pot', '*.csv'],
|
||||
},
|
||||
dependency_links = ['http://download.gna.org/pychart/'],
|
||||
install_requires = [
|
||||
# We require the same version as caldav for lxml.
|
||||
'lxml==2.1.5',
|
||||
'mako',
|
||||
'python-dateutil',
|
||||
'psycopg2',
|
||||
# TODO the pychart package we include in openerp corresponds to PyChart 1.37.
|
||||
# It seems there is a single difference, which is a spurious print in generate_docs.py.
|
||||
# It is probably safe to move to PyChart 1.39 (the latest one).
|
||||
# (Let setup.py choose the latest one, and we should check we can remove pychart from
|
||||
# our tree.)
|
||||
'pychart',
|
||||
'pydot',
|
||||
'pytz',
|
||||
'reportlab',
|
||||
'caldav',
|
||||
'pyyaml',
|
||||
'pywebdav',
|
||||
'feedparser',
|
||||
'simplejson >= 2.0',
|
||||
],
|
||||
extras_require = {
|
||||
'SSL' : ['pyopenssl'],
|
||||
},
|
||||
**py2exe_keywords
|
||||
setup(
|
||||
name=name,
|
||||
version=version,
|
||||
description=description,
|
||||
long_description=long_description,
|
||||
author=author,
|
||||
author_email=author_email,
|
||||
url=url,
|
||||
download_url=download_url,
|
||||
license=license,
|
||||
install_requires=[
|
||||
"CherryPy >= 3.1.2",
|
||||
"Babel >= 0.9.6",
|
||||
"simplejson >= 2.0.9",
|
||||
"python-dateutil >= 1.4.1",
|
||||
"pytz",
|
||||
],
|
||||
tests_require=[
|
||||
'unittest2',
|
||||
'mock',
|
||||
],
|
||||
test_suite = 'unittest2.collector',
|
||||
zip_safe=False,
|
||||
packages=[
|
||||
'addons',
|
||||
'addons.base',
|
||||
'addons.base.controllers',
|
||||
'addons.base_calendar',
|
||||
'addons.base_hello',
|
||||
'openerpweb',
|
||||
],
|
||||
classifiers=[
|
||||
'Development Status :: 6 - Production/Stable',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Environment :: Web Environment',
|
||||
'Topic :: Office/Business :: Financial',
|
||||
],
|
||||
scripts=['scripts/openerp-web'],
|
||||
data_files=(find_data_files('addons')
|
||||
+ opts.pop('data_files', [])
|
||||
),
|
||||
**opts
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue