[merge]
bzr revid: nicolas.vanhoren@openerp.com-20110915093144-0ix1tdc8mcmx6l9p
This commit is contained in:
@@ -32,10 +32,10 @@
|
||||
"static/src/js/views.js",
|
||||
"static/src/js/data.js",
|
||||
"static/src/js/data_export.js",
|
||||
"static/src/js/form.js",
|
||||
"static/src/js/list.js",
|
||||
"static/src/js/list-editable.js",
|
||||
"static/src/js/search.js",
|
||||
"static/src/js/view_form.js",
|
||||
"static/src/js/view_list.js",
|
||||
"static/src/js/view_list_editable.js",
|
||||
"static/src/js/view_tree.js",
|
||||
],
|
||||
'css' : [
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
from main import *
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import datetime
|
||||
|
||||
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
|
||||
DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
|
||||
DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
|
||||
DEFAULT_SERVER_DATE_FORMAT,
|
||||
DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
def str_to_datetime(str):
|
||||
"""
|
||||
Converts a string to a datetime object using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
No timezone information is added, the datetime is a naive instance, but
|
||||
according to OpenERP 6.1 specification the timezone is always UTC.
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def str_to_date(str):
|
||||
"""
|
||||
Converts a string to a date object using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
|
||||
|
||||
def str_to_time(str):
|
||||
"""
|
||||
Converts a string to a time object using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not str:
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
|
||||
|
||||
def datetime_to_str(obj):
|
||||
"""
|
||||
Converts a datetime object to a string using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
|
||||
The datetime instance should not have an attached timezone and be in UTC.
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def date_to_str(obj):
|
||||
"""
|
||||
Converts a date object to a string using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
def time_to_str(obj):
|
||||
"""
|
||||
Converts a time object to a string using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
"""
|
||||
if not obj:
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
@@ -1,397 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) Stephane Wirtel
|
||||
# Copyright (C) 2011 Nicolas Vanhoren
|
||||
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
OpenERP Client Library
|
||||
"""
|
||||
|
||||
import xmlrpclib
|
||||
import logging
|
||||
import socket
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
pickle.__name__
|
||||
except:
|
||||
import pickle
|
||||
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
StringIO.__name__
|
||||
except:
|
||||
import StringIO
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
def _getChildLogger(logger, subname):
|
||||
return logging.getLogger(logger.name + "." + subname)
|
||||
|
||||
class Connector(object):
|
||||
"""
|
||||
The base abstract class representing a connection to an OpenERP Server.
|
||||
"""
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector')
|
||||
|
||||
def __init__(self, hostname, port):
|
||||
"""
|
||||
Initilize by specifying an hostname and a port.
|
||||
:param hostname: Host name of the server.
|
||||
:param port: Port for the connection to the server.
|
||||
"""
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
|
||||
class XmlRPCConnector(Connector):
|
||||
"""
|
||||
A type of connector that uses the XMLRPC protocol.
|
||||
"""
|
||||
PROTOCOL = 'xmlrpc'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.xmlrpc')
|
||||
|
||||
def __init__(self, hostname, port=8069):
|
||||
"""
|
||||
Initialize by specifying the hostname and the port.
|
||||
:param hostname: The hostname of the computer holding the instance of OpenERP.
|
||||
:param port: The port used by the OpenERP instance for XMLRPC (default to 8069).
|
||||
"""
|
||||
Connector.__init__(self, hostname, port)
|
||||
self.url = 'http://%s:%d/xmlrpc' % (self.hostname, self.port)
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
url = '%s/%s' % (self.url, service_name)
|
||||
service = xmlrpclib.ServerProxy(url)
|
||||
return getattr(service, method)(*args)
|
||||
|
||||
class NetRPC_Exception(Exception):
|
||||
"""
|
||||
Exception for NetRPC errors.
|
||||
"""
|
||||
def __init__(self, faultCode, faultString):
|
||||
self.faultCode = faultCode
|
||||
self.faultString = faultString
|
||||
self.args = (faultCode, faultString)
|
||||
|
||||
class NetRPC:
|
||||
"""
|
||||
Low level class for NetRPC protocol.
|
||||
"""
|
||||
def __init__(self, sock=None):
|
||||
if sock is None:
|
||||
self.sock = socket.socket(
|
||||
socket.AF_INET, socket.SOCK_STREAM)
|
||||
else:
|
||||
self.sock = sock
|
||||
self.sock.settimeout(120)
|
||||
def connect(self, host, port=False):
|
||||
if not port:
|
||||
buf = host.split('//')[1]
|
||||
host, port = buf.split(':')
|
||||
self.sock.connect((host, int(port)))
|
||||
|
||||
def disconnect(self):
|
||||
self.sock.shutdown(socket.SHUT_RDWR)
|
||||
self.sock.close()
|
||||
|
||||
def mysend(self, msg, exception=False, traceback=None):
|
||||
msg = pickle.dumps([msg,traceback])
|
||||
size = len(msg)
|
||||
self.sock.send('%8d' % size)
|
||||
self.sock.send(exception and "1" or "0")
|
||||
totalsent = 0
|
||||
while totalsent < size:
|
||||
sent = self.sock.send(msg[totalsent:])
|
||||
if sent == 0:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
totalsent = totalsent + sent
|
||||
|
||||
def myreceive(self):
|
||||
buf=''
|
||||
while len(buf) < 8:
|
||||
chunk = self.sock.recv(8 - len(buf))
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf += chunk
|
||||
size = int(buf)
|
||||
buf = self.sock.recv(1)
|
||||
if buf != "0":
|
||||
exception = buf
|
||||
else:
|
||||
exception = False
|
||||
msg = ''
|
||||
while len(msg) < size:
|
||||
chunk = self.sock.recv(size-len(msg))
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
msg = msg + chunk
|
||||
msgio = StringIO.StringIO(msg)
|
||||
unpickler = pickle.Unpickler(msgio)
|
||||
unpickler.find_global = None
|
||||
res = unpickler.load()
|
||||
|
||||
if isinstance(res[0],Exception):
|
||||
if exception:
|
||||
raise NetRPC_Exception(str(res[0]), str(res[1]))
|
||||
raise res[0]
|
||||
else:
|
||||
return res[0]
|
||||
|
||||
class NetRPCConnector(Connector):
|
||||
"""
|
||||
A type of connector that uses the NetRPC protocol.
|
||||
"""
|
||||
|
||||
PROTOCOL = 'netrpc'
|
||||
|
||||
__logger = _getChildLogger(_logger, 'connector.netrpc')
|
||||
|
||||
def __init__(self, hostname, port=8070):
|
||||
"""
|
||||
Initialize by specifying the hostname and the port.
|
||||
:param hostname: The hostname of the computer holding the instance of OpenERP.
|
||||
:param port: The port used by the OpenERP instance for NetRPC (default to 8070).
|
||||
"""
|
||||
Connector.__init__(self, hostname, port)
|
||||
|
||||
def send(self, service_name, method, *args):
|
||||
socket = NetRPC()
|
||||
socket.connect(self.hostname, self.port)
|
||||
socket.mysend((service_name, method, )+args)
|
||||
result = socket.myreceive()
|
||||
socket.disconnect()
|
||||
return result
|
||||
|
||||
class Service:
|
||||
"""
|
||||
A class to execute RPC calls on a specific service of the remote server.
|
||||
"""
|
||||
def __init__(self, connector, service_name):
|
||||
"""
|
||||
:param connector: A valid Connector instance.
|
||||
:param service_name: The name of the service on the remote server.
|
||||
"""
|
||||
self.connector = connector
|
||||
self.service_name = service_name
|
||||
self.__logger = _getChildLogger(_getChildLogger(_logger, 'service'),service_name)
|
||||
|
||||
def __getattr__(self, method):
|
||||
"""
|
||||
:param method: The name of the method to execute on the service.
|
||||
"""
|
||||
self.__logger.debug('method: %r', method)
|
||||
def proxy(*args):
|
||||
"""
|
||||
:param args: A list of values for the method
|
||||
"""
|
||||
self.__logger.debug('args: %r', args)
|
||||
result = self.connector.send(self.service_name, method, *args)
|
||||
self.__logger.debug('result: %r' % result)
|
||||
return result
|
||||
return proxy
|
||||
|
||||
class Connection(object):
|
||||
"""
|
||||
A class to represent a connection with authentification to an OpenERP Server.
|
||||
It also provides utility methods to interact with the server more easily.
|
||||
"""
|
||||
__logger = _getChildLogger(_logger, 'connection')
|
||||
|
||||
def __init__(self, connector,
|
||||
database=None,
|
||||
login=None,
|
||||
password=None,
|
||||
user_id=None):
|
||||
"""
|
||||
Initialize with login information. The login information is facultative to allow specifying
|
||||
it after the initialization of this object.
|
||||
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
self.connector = connector
|
||||
|
||||
self.set_login_info(database, login, password, user_id)
|
||||
|
||||
def set_login_info(self, database, login, password, user_id=None):
|
||||
"""
|
||||
Set login information after the initialisation of this object.
|
||||
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
self.database, self.login, self.password = database, login, password
|
||||
|
||||
self.user_id = user_id
|
||||
|
||||
def check_login(self, force=True):
|
||||
"""
|
||||
Checks that the login information is valid. Throws an AuthentificationError if the
|
||||
authentification fails.
|
||||
|
||||
:param force: Force to re-check even if this Connection was already validated previously.
|
||||
Default to True.
|
||||
"""
|
||||
if self.user_id and not force:
|
||||
return
|
||||
|
||||
self.user_id = self.get_service("common").login(self.database, self.login, self.password)
|
||||
if not self.user_id:
|
||||
raise AuthentificationError("Authentification failure")
|
||||
self.__logger.debug("Authentified with user id %s" % self.user_id)
|
||||
|
||||
"""
|
||||
Returns a Model instance to allow easy remote manipulation of an OpenERP model.
|
||||
|
||||
:param model_name: The name of the model.
|
||||
"""
|
||||
def get_model(self, model_name):
|
||||
return Model(self, model_name)
|
||||
|
||||
"""
|
||||
Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
|
||||
Please note this Connection instance does not need to have valid authenfication information since authentification
|
||||
is only necessary for the "object" service that handles models.
|
||||
|
||||
:param service_name: The name of the service.
|
||||
"""
|
||||
def get_service(self, service_name):
|
||||
return Service(self.connector, service_name)
|
||||
|
||||
class AuthentificationError(Exception):
|
||||
"""
|
||||
An error thrown when an authentification to an OpenERP server failed.
|
||||
"""
|
||||
pass
|
||||
|
||||
class Model(object):
|
||||
"""
|
||||
Useful class to dialog with one of the models provided by an OpenERP server.
|
||||
An instance of this class depends on a Connection instance with valid authenfication information.
|
||||
"""
|
||||
|
||||
def __init__(self, connection, model_name):
|
||||
"""
|
||||
:param connection: A valid Connection instance with correct authentification information.
|
||||
:param model_name: The name of the model.
|
||||
"""
|
||||
self.connection = connection
|
||||
self.model_name = model_name
|
||||
self.__logger = _getChildLogger(_getChildLogger(_logger, 'object'), model_name)
|
||||
|
||||
def __getattr__(self, method):
|
||||
"""
|
||||
Provides proxy methods that will forward calls to the model on the remote OpenERP server.
|
||||
|
||||
:param method: The method for the linked model (search, read, write, unlink, create, ...)
|
||||
"""
|
||||
def proxy(*args):
|
||||
"""
|
||||
:param args: A list of values for the method
|
||||
"""
|
||||
self.connection.check_login(False)
|
||||
self.__logger.debug(args)
|
||||
result = self.connection.get_service('object').execute(
|
||||
self.connection.database,
|
||||
self.connection.user_id,
|
||||
self.connection.password,
|
||||
self.model_name,
|
||||
method,
|
||||
*args)
|
||||
if method == "read":
|
||||
if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
|
||||
index = {}
|
||||
for i in xrange(len(result)):
|
||||
index[result[i]["id"]] = result[i]
|
||||
result = [index[x] for x in args[0]]
|
||||
self.__logger.debug('result: %r' % result)
|
||||
return result
|
||||
return proxy
|
||||
|
||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
|
||||
"""
|
||||
A shortcut method to combine a search() and a read().
|
||||
|
||||
:param domain: The domain for the search.
|
||||
:param fields: The fields to extract (can be None or [] to extract all fields).
|
||||
:param offset: The offset for the rows to read.
|
||||
:param limit: The maximum number of rows to read.
|
||||
:param order: The order to class the rows.
|
||||
:param context: The context.
|
||||
:return: A list of dictionaries containing all the specified fields.
|
||||
"""
|
||||
record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
|
||||
records = self.read(record_ids, fields or [], context or {})
|
||||
return records
|
||||
|
||||
def get_connector(hostname, protocol="xmlrpc", port="auto"):
|
||||
"""
|
||||
A shortcut method to easily create a connector to a remote server using XMLRPC or NetRPC.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "netrpc".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
"""
|
||||
if port == 'auto':
|
||||
port = 8069 if protocol=="xmlrpc" else 8070
|
||||
if protocol == "xmlrpc":
|
||||
return XmlRPCConnector(hostname, port)
|
||||
elif protocol == "netrpc":
|
||||
return NetRPCConnector(hostname, port)
|
||||
else:
|
||||
raise ValueError("You must choose xmlrpc or netrpc")
|
||||
|
||||
def get_connection(hostname, protocol="xmlrpc", port='auto', database=None,
|
||||
login=None, password=None, user_id=None):
|
||||
"""
|
||||
A shortcut method to easily create a connection to a remote OpenERP server.
|
||||
|
||||
:param hostname: The hostname to the remote server.
|
||||
:param protocol: The name of the protocol, must be "xmlrpc" or "netrpc".
|
||||
:param port: The number of the port. Defaults to auto.
|
||||
:param connector: A valid Connector instance to send messages to the remote server.
|
||||
:param database: The name of the database to work on.
|
||||
:param login: The login of the user.
|
||||
:param password: The password of the user.
|
||||
:param user_id: The user id is a number identifying the user. This is only useful if you
|
||||
already know it, in most cases you don't need to specify it.
|
||||
"""
|
||||
return Connection(get_connector(hostname, protocol, port), database, login, password, user_id)
|
||||
|
||||
@@ -842,8 +842,8 @@ label.error {
|
||||
.openerp label.oe_label_help {
|
||||
cursor: help;
|
||||
}
|
||||
.openerp label.oe_label,
|
||||
.openerp label.oe_label_help {
|
||||
|
||||
.openerp .oe_form_field label.oe_label, .openerp .oe_form_field label.oe_label_help {
|
||||
text-align: right;
|
||||
margin: 3px 0 0 10px;
|
||||
}
|
||||
|
||||
@@ -463,30 +463,6 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se
|
||||
}));
|
||||
}
|
||||
});
|
||||
openerp.web.search.FilterGroup = openerp.web.search.Widget.extend(/** @lends openerp.web.search.FilterGroup# */{
|
||||
template: 'SearchView.filters',
|
||||
/**
|
||||
* Inclusive group of filters, creates a continuous "button" with clickable
|
||||
* sections (the normal display for filters is to be a self-contained button)
|
||||
*
|
||||
* @constructs openerp.web.search.FilterGroup
|
||||
* @extends openerp.web.search.Widget
|
||||
*
|
||||
* @param {Array<openerp.web.search.Filter>} filters elements of the group
|
||||
* @param {openerp.web.SearchView} view view in which the filters are contained
|
||||
*/
|
||||
init: function (filters, view) {
|
||||
this._super(view);
|
||||
this.filters = filters;
|
||||
this.length = filters.length;
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
_.each(this.filters, function (filter) {
|
||||
filter.start();
|
||||
});
|
||||
}
|
||||
});
|
||||
openerp.web.search.add_expand_listener = function($root) {
|
||||
$root.find('a.searchview_group_string').click(function (e) {
|
||||
$root.toggleClass('folded expanded');
|
||||
@@ -533,6 +509,49 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp.
|
||||
"get_domain not implemented for widget " + this.attrs.type);
|
||||
}
|
||||
});
|
||||
openerp.web.search.FilterGroup = openerp.web.search.Input.extend(/** @lends openerp.web.search.FilterGroup# */{
|
||||
template: 'SearchView.filters',
|
||||
/**
|
||||
* Inclusive group of filters, creates a continuous "button" with clickable
|
||||
* sections (the normal display for filters is to be a self-contained button)
|
||||
*
|
||||
* @constructs openerp.web.search.FilterGroup
|
||||
* @extends openerp.web.search.Input
|
||||
*
|
||||
* @param {Array<openerp.web.search.Filter>} filters elements of the group
|
||||
* @param {openerp.web.SearchView} view view in which the filters are contained
|
||||
*/
|
||||
init: function (filters, view) {
|
||||
this._super(view);
|
||||
this.filters = filters;
|
||||
this.length = filters.length;
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
_.each(this.filters, function (filter) {
|
||||
filter.start();
|
||||
});
|
||||
},
|
||||
get_context: function () { },
|
||||
/**
|
||||
* Handles domains-fetching for all the filters within it: groups them.
|
||||
*/
|
||||
get_domain: function () {
|
||||
var domains = _(this.filters).chain()
|
||||
.filter(function (filter) { return filter.is_enabled(); })
|
||||
.map(function (filter) { return filter.attrs.domain; })
|
||||
.value();
|
||||
|
||||
if (!domains.length) { return; }
|
||||
if (domains.length === 1) { return domains[0]; }
|
||||
for (var i=domains.length; --i;) {
|
||||
domains.unshift(['|']);
|
||||
}
|
||||
return _.extend(new openerp.web.CompoundDomain(), {
|
||||
__domains: domains
|
||||
});
|
||||
}
|
||||
});
|
||||
openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.web.search.Filter# */{
|
||||
template: 'SearchView.filter',
|
||||
/**
|
||||
@@ -586,12 +605,11 @@ openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.w
|
||||
}
|
||||
return this.attrs.context;
|
||||
},
|
||||
get_domain: function () {
|
||||
if (!this.is_enabled()) {
|
||||
return;
|
||||
}
|
||||
return this.attrs.domain;
|
||||
}
|
||||
/**
|
||||
* Does not return anything: filter domain is handled at the FilterGroup
|
||||
* level
|
||||
*/
|
||||
get_domain: function () { }
|
||||
});
|
||||
openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.web.search.Field# */ {
|
||||
template: 'SearchView.field',
|
||||
|
||||
@@ -35,7 +35,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
this.datarecord = {};
|
||||
this.ready = false;
|
||||
this.show_invalid = true;
|
||||
this.dirty = false;
|
||||
this.dirty_for_user = false;
|
||||
this.default_focus_field = null;
|
||||
this.default_focus_button = null;
|
||||
this.registry = openerp.web.form.widgets;
|
||||
@@ -93,6 +93,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
this.$form_header.find('button.oe_form_button_save_edit').click(this.do_save_edit);
|
||||
this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel);
|
||||
this.$form_header.find('button.oe_form_button_new').click(this.on_button_new);
|
||||
this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate);
|
||||
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
|
||||
@@ -139,7 +140,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
this.$form_header.find('.oe_form_on_update').show();
|
||||
this.$form_header.find('button.oe_form_button_new').show();
|
||||
}
|
||||
this.dirty = false;
|
||||
this.dirty_for_user = false;
|
||||
this.datarecord = record;
|
||||
for (var f in this.fields) {
|
||||
var field = this.fields[f];
|
||||
@@ -149,7 +150,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
}
|
||||
if (!record.id) {
|
||||
// New record: Second pass in order to trigger the onchanges
|
||||
this.dirty = true;
|
||||
this.show_invalid = false;
|
||||
for (var f in record) {
|
||||
var field = this.fields[f];
|
||||
@@ -178,21 +178,23 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
}
|
||||
},
|
||||
on_pager_action: function(action) {
|
||||
switch (action) {
|
||||
case 'first':
|
||||
this.dataset.index = 0;
|
||||
break;
|
||||
case 'previous':
|
||||
this.dataset.previous();
|
||||
break;
|
||||
case 'next':
|
||||
this.dataset.next();
|
||||
break;
|
||||
case 'last':
|
||||
this.dataset.index = this.dataset.ids.length - 1;
|
||||
break;
|
||||
if (this.can_be_discarded()) {
|
||||
switch (action) {
|
||||
case 'first':
|
||||
this.dataset.index = 0;
|
||||
break;
|
||||
case 'previous':
|
||||
this.dataset.previous();
|
||||
break;
|
||||
case 'next':
|
||||
this.dataset.next();
|
||||
break;
|
||||
case 'last':
|
||||
this.dataset.index = this.dataset.ids.length - 1;
|
||||
break;
|
||||
}
|
||||
this.reload();
|
||||
}
|
||||
this.reload();
|
||||
},
|
||||
do_update_pager: function(hide_index) {
|
||||
var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager');
|
||||
@@ -274,7 +276,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
processed.push(field.name);
|
||||
if (field.get_value() != value) {
|
||||
field.set_value(value);
|
||||
field.dirty = true;
|
||||
field.dirty = this.dirty_for_user = true;
|
||||
if (_.indexOf(processed, field.name) < 0) {
|
||||
this.do_onchange(field, processed);
|
||||
}
|
||||
@@ -302,13 +304,31 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
|
||||
var self = this;
|
||||
var def = $.Deferred();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.dataset.default_get(
|
||||
_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() {
|
||||
if (self.can_be_discarded()) {
|
||||
self.dataset.default_get(_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() {
|
||||
def.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
return def.promise();
|
||||
},
|
||||
on_button_duplicate: function() {
|
||||
var self = this;
|
||||
var def = $.Deferred();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
if (self.can_be_discarded()) {
|
||||
self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
|
||||
return self.on_created({ result : new_id });
|
||||
}).then(function() {
|
||||
def.resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
return def.promise();
|
||||
},
|
||||
can_be_discarded: function() {
|
||||
return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
|
||||
},
|
||||
/**
|
||||
* Triggers saving the form's record. Chooses between creating a new
|
||||
* record or saving an existing one depending on whether the record
|
||||
@@ -814,7 +834,7 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
|
||||
},
|
||||
on_click: function(saved) {
|
||||
var self = this;
|
||||
if (!this.node.attrs.special && this.view.dirty && saved !== true) {
|
||||
if ((!this.node.attrs.special && this.view.dirty_for_user && saved !== true) || !this.view.recordcount.id) {
|
||||
this.view.do_save(function() {
|
||||
self.on_click(true);
|
||||
});
|
||||
@@ -962,7 +982,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
|
||||
}
|
||||
},
|
||||
on_ui_change: function() {
|
||||
this.dirty = this.view.dirty = true;
|
||||
this.dirty = this.view.dirty_for_user = true;
|
||||
this.validate();
|
||||
if (this.is_valid()) {
|
||||
this.set_value_from_ui();
|
||||
@@ -2,17 +2,21 @@
|
||||
* OpenERP web library
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.web.views = function(openerp) {
|
||||
openerp.web.views = function(db) {
|
||||
|
||||
var _t = openerp.web._t;
|
||||
var QWeb = openerp.web.qweb;
|
||||
var _t = db.web._t;
|
||||
|
||||
/**
|
||||
* Registry for all the client actions key: tag value: widget
|
||||
*/
|
||||
openerp.web.client_actions = new openerp.web.Registry();
|
||||
db.web.client_actions = new db.web.Registry();
|
||||
|
||||
openerp.web.ActionManager = openerp.web.Widget.extend({
|
||||
/**
|
||||
* Registry for all the main views
|
||||
*/
|
||||
db.web.views = new db.web.Registry();
|
||||
|
||||
db.web.ActionManager = db.web.Widget.extend({
|
||||
identifier_prefix: "actionmanager",
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
@@ -87,20 +91,20 @@ openerp.web.ActionManager = openerp.web.Widget.extend({
|
||||
ir_actions_act_window: function (action, on_close) {
|
||||
if (action.target === 'new') {
|
||||
if (this.dialog == null) {
|
||||
this.dialog = new openerp.web.Dialog(this, { title: action.name, width: '80%' });
|
||||
this.dialog = new db.web.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();
|
||||
}
|
||||
this.dialog_viewmanager = new openerp.web.ViewManagerAction(this, action);
|
||||
this.dialog_viewmanager = new db.web.ViewManagerAction(this, action);
|
||||
this.dialog_viewmanager.appendTo(this.dialog.$element);
|
||||
this.dialog.open();
|
||||
} else {
|
||||
this.dialog_stop();
|
||||
this.content_stop();
|
||||
this.inner_viewmanager = new openerp.web.ViewManagerAction(this, action);
|
||||
this.inner_viewmanager = new db.web.ViewManagerAction(this, action);
|
||||
this.inner_viewmanager.appendTo(this.$element);
|
||||
this.url_update(action);
|
||||
}
|
||||
@@ -125,7 +129,7 @@ openerp.web.ActionManager = openerp.web.Widget.extend({
|
||||
},
|
||||
ir_actions_client: function (action) {
|
||||
this.content_stop();
|
||||
var ClientWidget = openerp.web.client_actions.get_object(action.tag);
|
||||
var ClientWidget = db.web.client_actions.get_object(action.tag);
|
||||
(this.client_widget = new ClientWidget(this, action.params)).appendTo(this);
|
||||
},
|
||||
ir_actions_report_xml: function(action) {
|
||||
@@ -138,12 +142,12 @@ openerp.web.ActionManager = openerp.web.Widget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.ViewManager# */{
|
||||
db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
|
||||
identifier_prefix: "viewmanager",
|
||||
template: "ViewManager",
|
||||
/**
|
||||
* @constructs openerp.web.ViewManager
|
||||
* @extends openerp.web.Widget
|
||||
* @constructs db.web.ViewManager
|
||||
* @extends db.web.Widget
|
||||
*
|
||||
* @param parent
|
||||
* @param dataset
|
||||
@@ -158,10 +162,10 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View
|
||||
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.web.views;
|
||||
this.registry = db.web.views;
|
||||
},
|
||||
render: function() {
|
||||
return QWeb.render(this.template, {
|
||||
return db.web.qweb.render(this.template, {
|
||||
self: this,
|
||||
prefix: this.element_id,
|
||||
views: this.views_src});
|
||||
@@ -280,7 +284,7 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View
|
||||
if (this.searchview) {
|
||||
this.searchview.stop();
|
||||
}
|
||||
this.searchview = new openerp.web.SearchView(
|
||||
this.searchview = new db.web.SearchView(
|
||||
this, this.element_id + "_search", this.dataset,
|
||||
view_id, search_defaults);
|
||||
|
||||
@@ -307,13 +311,13 @@ openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.View
|
||||
on_action_executed: function () {}
|
||||
});
|
||||
|
||||
openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{
|
||||
db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{
|
||||
template:"ViewManagerAction",
|
||||
/**
|
||||
* @constructs openerp.web.ViewManagerAction
|
||||
* @extends openerp.web.ViewManager
|
||||
* @constructs db.web.ViewManagerAction
|
||||
* @extends db.web.ViewManager
|
||||
*
|
||||
* @param {openerp.web.ActionManager} parent parent object/widget
|
||||
* @param {db.web.ActionManager} parent parent object/widget
|
||||
* @param {Object} action descriptor for the action this viewmanager needs to manage its views.
|
||||
*/
|
||||
init: function(parent, action) {
|
||||
@@ -322,7 +326,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
|
||||
// ``_super()``) rpc requests will blow up.
|
||||
this.session = parent.session;
|
||||
this.action = action;
|
||||
var dataset = new openerp.web.DataSetSearch(this, action.res_model, action.context, action.domain);
|
||||
var dataset = new db.web.DataSetSearch(this, action.res_model, action.context, action.domain);
|
||||
if (action.res_id) {
|
||||
dataset.ids.push(action.res_id);
|
||||
dataset.index = 0;
|
||||
@@ -376,12 +380,12 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
|
||||
|
||||
this.$element.find('.oe_get_xml_view').click(function () {
|
||||
// TODO: add search view?
|
||||
$('<pre>').text(openerp.web.json_node_to_xml(
|
||||
$('<pre>').text(db.web.json_node_to_xml(
|
||||
self.views[self.active_view].controller.fields_view.arch, true))
|
||||
.dialog({ width: '95%'});
|
||||
});
|
||||
if (this.action.help && !this.flags.low_profile) {
|
||||
var Users = new openerp.web.DataSet(self, 'res.users'),
|
||||
var Users = new db.web.DataSet(self, 'res.users'),
|
||||
header = this.$element.find('.oe-view-manager-header');
|
||||
header.delegate('blockquote button', 'click', function() {
|
||||
var $this = $(this);
|
||||
@@ -421,7 +425,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
|
||||
var grandparent = this.widget_parent && this.widget_parent.widget_parent;
|
||||
// display shortcuts if on the first view for the action
|
||||
var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle');
|
||||
if (!(grandparent instanceof openerp.web.WebClient) ||
|
||||
if (!(grandparent instanceof db.web.WebClient) ||
|
||||
!(view.view_type === this.views_src[0].view_type
|
||||
&& view.view_id === this.views_src[0].view_id)) {
|
||||
$shortcut_toggle.hide();
|
||||
@@ -458,7 +462,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
|
||||
* Intercept do_action resolution from children views
|
||||
*/
|
||||
on_action_executed: function () {
|
||||
new openerp.web.DataSet(this, 'res.log')
|
||||
new db.web.DataSet(this, 'res.log')
|
||||
.call('get', [], this.do_display_log);
|
||||
},
|
||||
/**
|
||||
@@ -485,7 +489,7 @@ openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepner
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web.Sidebar = openerp.web.Widget.extend({
|
||||
db.web.Sidebar = db.web.Widget.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.items = {};
|
||||
@@ -494,7 +498,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
|
||||
start: function() {
|
||||
this._super(this);
|
||||
var self = this;
|
||||
this.$element.html(QWeb.render('Sidebar'));
|
||||
this.$element.html(db.web.qweb.render('Sidebar'));
|
||||
this.$element.find(".toggle-sidebar").click(function(e) {
|
||||
self.do_toggle();
|
||||
});
|
||||
@@ -536,7 +540,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
|
||||
this.items[items[i].element_id] = items[i];
|
||||
}
|
||||
}
|
||||
var $section = $(QWeb.render("Sidebar.section", {
|
||||
var $section = $(db.web.qweb.render("Sidebar.section", {
|
||||
section_id: section_id,
|
||||
name: name,
|
||||
classname: 'oe_sidebar_' + code,
|
||||
@@ -592,7 +596,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web.TranslateDialog = openerp.web.Dialog.extend({
|
||||
db.web.TranslateDialog = db.web.Dialog.extend({
|
||||
dialog_title: _t("Translations"),
|
||||
init: function(view) {
|
||||
// TODO fme: should add the language to fields_view_get because between the fields view get
|
||||
@@ -612,14 +616,14 @@ openerp.web.TranslateDialog = openerp.web.Dialog.extend({
|
||||
this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name });
|
||||
this.languages = null;
|
||||
this.languages_loaded = $.Deferred();
|
||||
(new openerp.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(),
|
||||
(new db.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(),
|
||||
[['translatable', '=', '1']])).read_slice(['code', 'name'], { sort: 'id' }, this.on_languages_loaded);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._super();
|
||||
$.when(this.languages_loaded).then(function() {
|
||||
self.$element.html(QWeb.render('TranslateDialog', { widget: self }));
|
||||
self.$element.html(db.web.qweb.render('TranslateDialog', { widget: self }));
|
||||
self.$element.tabs();
|
||||
if (!(self.view.translatable_fields && self.view.translatable_fields.length)) {
|
||||
self.hide_tabs('fields');
|
||||
@@ -724,11 +728,7 @@ openerp.web.TranslateDialog = openerp.web.Dialog.extend({
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.web.Widget
|
||||
*/
|
||||
openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
|
||||
set_default_options: function(options) {
|
||||
this.options = options || {};
|
||||
_.defaults(this.options, {
|
||||
@@ -741,7 +741,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
},
|
||||
open_translate_dialog: function(field) {
|
||||
if (!this.translate_dialog) {
|
||||
this.translate_dialog = new openerp.web.TranslateDialog(this).start();
|
||||
this.translate_dialog = new db.web.TranslateDialog(this).start();
|
||||
}
|
||||
this.translate_dialog.open(field);
|
||||
},
|
||||
@@ -753,7 +753,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
* @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``)
|
||||
* @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
|
||||
* @param {Object} [action_data.context=null] additional action context, to add to the current context
|
||||
* @param {openerp.web.DataSet} dataset a dataset object used to communicate with the server
|
||||
* @param {db.web.DataSet} dataset a dataset object used to communicate with the server
|
||||
* @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)
|
||||
*/
|
||||
@@ -772,14 +772,14 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
active_ids: [record_id || false],
|
||||
active_model: dataset.model
|
||||
});
|
||||
action.context = new openerp.web.CompoundContext(dataset.get_context(), action.context);
|
||||
action.context = new db.web.CompoundContext(dataset.get_context(), action.context);
|
||||
self.do_action(action, result_handler);
|
||||
} else {
|
||||
result_handler();
|
||||
}
|
||||
};
|
||||
|
||||
var context = new openerp.web.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
var context = new db.web.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
|
||||
if (action_data.special) {
|
||||
handler({result: {"type":"ir.actions.act_window_close"}});
|
||||
@@ -794,7 +794,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
/**
|
||||
* 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.web.View must use the provided view instead of any other one.
|
||||
* of db.web.View must use the provided view instead of any other one.
|
||||
*
|
||||
* @param embedded_view A view.
|
||||
*/
|
||||
@@ -841,7 +841,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
},
|
||||
on_sidebar_manage_view: function() {
|
||||
if (this.fields_view && this.fields_view.arch) {
|
||||
$('<xmp>' + openerp.web.json_node_to_xml(this.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
|
||||
$('<xmp>' + db.web.json_node_to_xml(this.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
|
||||
} else {
|
||||
this.notification.warn("Manage Views", "Could not find current view declaration");
|
||||
}
|
||||
@@ -855,7 +855,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
on_sidebar_import: function() {
|
||||
},
|
||||
on_sidebar_export: function() {
|
||||
var export_view = new openerp.web.DataExport(this, this.dataset);
|
||||
var export_view = new db.web.DataExport(this, this.dataset);
|
||||
export_view.start();
|
||||
},
|
||||
on_sidebar_translate: function() {
|
||||
@@ -865,12 +865,7 @@ openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Registry for all the main views
|
||||
*/
|
||||
openerp.web.views = new openerp.web.Registry();
|
||||
|
||||
openerp.web.json_node_to_xml = function(node, single_quote, indent) {
|
||||
db.web.json_node_to_xml = function(node, single_quote, indent) {
|
||||
// For debugging purpose, this function will convert a json node back to xml
|
||||
// Maybe usefull for xml view editor
|
||||
|
||||
@@ -899,7 +894,7 @@ openerp.web.json_node_to_xml = function(node, single_quote, indent) {
|
||||
r += '>\n';
|
||||
var childs = [];
|
||||
for (var i = 0, ii = node.children.length; i < ii; i++) {
|
||||
childs.push(openerp.web.json_node_to_xml(node.children[i], single_quote, indent + 1));
|
||||
childs.push(db.web.json_node_to_xml(node.children[i], single_quote, indent + 1));
|
||||
}
|
||||
r += childs.join('\n');
|
||||
r += '\n' + sindent + '</' + node.tag + '>';
|
||||
|
||||
@@ -661,6 +661,7 @@
|
||||
</button>
|
||||
<!--<button type="button" class="oe_form_button_cancel">Cancel</button>-->
|
||||
<button type="button" class="oe_form_button_new">New</button>
|
||||
<button type="button" class="oe_form_button_duplicate oe_form_on_update">Duplicate</button>
|
||||
</div>
|
||||
<div class="oe_form_pager" t-if="view.options.pager !== false">
|
||||
<button type="button" data-pager-action="first">First</button>
|
||||
|
||||
Reference in New Issue
Block a user