import md5
import openerp.addons.hw_proxy.controllers.main as hw_proxy
import subprocess
+import traceback
from threading import Thread, Lock
from Queue import Queue, Empty
if timestamp >= time.time() - 1 * 60 * 60:
self.print_receipt_body(printer,data)
printer.cut()
+ elif task == 'xml_receipt':
+ if timestamp >= time.time() - 1 * 60 * 60:
+ printer.receipt(data)
elif task == 'cashbox':
if timestamp >= time.time() - 12:
self.open_cashbox(printer)
except Exception as e:
self.set_status('error', str(e))
- _logger.error(e);
+ errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n'
+ _logger.error(errmsg);
def push_task(self,task, data = None):
self.lockedstart()
hw_proxy.drivers['escpos'] = driver
-driver.push_task('printstatus')
-
class EscposProxy(hw_proxy.Proxy):
@http.route('/hw_proxy/open_cashbox', type='json', auth='none', cors='*')
def print_receipt(self, receipt):
_logger.info('ESC/POS: PRINT RECEIPT')
driver.push_task('receipt',receipt)
+
+ @http.route('/hw_proxy/print_xml_receipt', type='json', auth='none', cors='*')
+ def print_receipt(self, receipt):
+ _logger.info('ESC/POS: PRINT XML RECEIPT')
+ driver.push_task('xml_receipt',receipt)
TXT_NORMAL = '\x1b\x21\x00' # Normal text
TXT_2HEIGHT = '\x1b\x21\x10' # Double height text
TXT_2WIDTH = '\x1b\x21\x20' # Double width text
+TXT_DOUBLE = '\x1b\x21\x30' # Double height & Width
TXT_UNDERL_OFF = '\x1b\x2d\x00' # Underline font OFF
TXT_UNDERL_ON = '\x1b\x2d\x01' # Underline font 1-dot ON
TXT_UNDERL2_ON = '\x1b\x2d\x02' # Underline font 2-dot ON
-#!/usr/bin/python
+# -*- coding: utf-8 -*-
'''
@author: Manuel F Martinez <manpaz@bashlinux.com>
@organization: Bashlinux
import base64
import math
import md5
+import re
+import traceback
+import xml.etree.ElementTree as ET
+import xml.dom.minidom as minidom
from PIL import Image
from constants import *
from exceptions import *
+def utfstr(stuff):
+ """ converts stuff to string and does without failing if stuff is a utf8 string """
+ if isinstance(stuff,basestring):
+ return stuff
+ else:
+ return str(stuff)
+
+class StyleStack:
+ """
+ The stylestack is used by the xml receipt serializer to compute the active styles along the xml
+ document. Styles are just xml attributes, there is no css mechanism. But the style applied by
+ the attributes are inherited by deeper nodes.
+ """
+ def __init__(self):
+ self.stack = []
+ self.defaults = { # default style values
+ 'align': 'left',
+ 'underline': 'off',
+ 'bold': 'off',
+ 'size': 'normal',
+ 'font' : 'a',
+ 'width': 48,
+ 'indent': 0,
+ 'tabwidth': 2,
+ 'bullet': ' - ',
+ 'line-ratio':0.5,
+
+ 'value-decimals': 2,
+ 'value-symbol': '',
+ 'value-symbol-position': 'after',
+ 'value-autoint': 'off',
+ 'value-decimals-separator': '.',
+ 'value-thousands-separator': ',',
+ 'value-width': 0,
+
+ }
+
+ self.types = { # attribute types, default is string and can be ommitted
+ 'width': 'int',
+ 'indent': 'int',
+ 'tabwidth': 'int',
+ 'line-ratio': 'float',
+ 'value-decimals': 'int',
+ 'value-width': 'int',
+ }
+
+ self.cmds = {
+ # translation from styles to escpos commands
+ # some style do not correspond to escpos command are used by
+ # the serializer instead
+ 'align': {
+ 'left': TXT_ALIGN_LT,
+ 'right': TXT_ALIGN_RT,
+ 'center': TXT_ALIGN_CT,
+ },
+ 'underline': {
+ 'off': TXT_UNDERL_OFF,
+ 'on': TXT_UNDERL_ON,
+ 'double': TXT_UNDERL2_ON,
+ },
+ 'bold': {
+ 'off': TXT_BOLD_OFF,
+ 'on': TXT_BOLD_ON,
+ },
+ 'font': {
+ 'a': TXT_FONT_A,
+ 'b': TXT_FONT_B,
+ },
+ 'size': {
+ 'normal': TXT_NORMAL,
+ 'double-height': TXT_2HEIGHT,
+ 'double-width': TXT_2WIDTH,
+ 'double': TXT_DOUBLE,
+ }
+ }
+
+ self.push(self.defaults)
+
+ def get(self,style):
+ """ what's the value of a style at the current stack level"""
+ level = len(self.stack) -1
+ while level >= 0:
+ if style in self.stack[level]:
+ return self.stack[level][style]
+ else:
+ level = level - 1
+ return None
+
+ def enforce_type(self, attr, val):
+ """converts a value to the attribute's type"""
+ if not attr in self.types:
+ return utfstr(val)
+ elif self.types[attr] == 'int':
+ return int(float(val))
+ elif self.types[attr] == 'float':
+ return float(val)
+ else:
+ return utfstr(val)
+
+ def push(self, style={}):
+ """push a new level on the stack with a style dictionnary containing style:value pairs"""
+ _style = {}
+ for attr in style:
+ if attr in self.cmds and not style[attr] in self.cmds[attr]:
+ print 'WARNING: ESC/POS PRINTING: ignoring invalid value: '+utfstr(style[attr])+' for style: '+utfstr(attr)
+ else:
+ _style[attr] = self.enforce_type(attr, style[attr])
+ self.stack.append(_style)
+
+ def set(self, style={}):
+ """overrides style values at the current stack level"""
+ _style = {}
+ for attr in style:
+ if attr in self.cmds and not style[attr] in self.cmds[attr]:
+ print 'WARNING: ESC/POS PRINTING: ignoring invalid value: '+utfstr(style[attr])+' for style: '+utfstr(attr)
+ else:
+ self.stack[-1][attr] = self.enforce_type(attr, style[attr])
+
+ def pop(self):
+ """ pop a style stack level """
+ if len(self.stack) > 1 :
+ self.stack = self.stack[:-1]
+
+ def to_escpos(self):
+ """ converts the current style to an escpos command string """
+ cmd = ''
+ for style in self.cmds:
+ cmd += self.cmds[style][self.get(style)]
+ return cmd
+
+class XmlSerializer:
+ """
+ Converts the xml inline / block tree structure to a string,
+ keeping track of newlines and spacings.
+ The string is outputted asap to the provided escpos driver.
+ """
+ def __init__(self,escpos):
+ self.escpos = escpos
+ self.stack = ['block']
+ self.dirty = False
+
+ def start_inline(self,stylestack=None):
+ """ starts an inline entity with an optional style definition """
+ print 'start_inline'
+ self.stack.append('inline')
+ if self.dirty:
+ self.escpos._raw(' ')
+ if stylestack:
+ self.style(stylestack)
+
+ def start_block(self,stylestack=None):
+ """ starts a block entity with an optional style definition """
+ print 'start_block'
+ if self.dirty:
+ print 'cleanup before block'
+ self.escpos._raw('\n')
+ self.dirty = False
+ self.stack.append('block')
+ if stylestack:
+ self.style(stylestack)
+
+ def end_entity(self):
+ """ ends the entity definition. (but does not cancel the active style!) """
+ print 'end_entity'
+ if self.stack[-1] == 'block' and self.dirty:
+ print 'cleanup after block'
+ self.escpos._raw('\n')
+ self.dirty = False
+ if len(self.stack) > 1:
+ self.stack = self.stack[:-1]
+
+ def pre(self,text):
+ """ puts a string of text in the entity keeping the whitespace intact """
+ if text:
+ self.escpos.text(text)
+ self.dirty = True
+
+ def text(self,text):
+ """ puts text in the entity. Whitespace and newlines are stripped to single spaces. """
+ if text:
+ text = utfstr(text)
+ text = text.strip()
+ text = re.sub('\s+',' ',text)
+ if text:
+ print 'printing text:'+text
+ self.dirty = True
+ self.escpos.text(text)
+
+ def linebreak(self):
+ """ inserts a linebreak in the entity """
+ self.dirty = False
+ self.escpos._raw('\n')
+
+ def style(self,stylestack):
+ """ apply a style to the entity (only applies to content added after the definition) """
+ self.raw(stylestack.to_escpos())
+
+ def raw(self,raw):
+ """ puts raw text or escpos command in the entity without affecting the state of the serializer """
+ self.escpos._raw(raw)
+
+class XmlLineSerializer:
+ """
+ This is used to convert a xml tree into a single line, with a left and a right part.
+ The content is not output to escpos directly, and is intended to be fedback to the
+ XmlSerializer as the content of a block entity.
+ """
+ def __init__(self, indent=0, tabwidth=2, width=48, ratio=0.5):
+ self.tabwidth = tabwidth
+ self.indent = indent
+ self.width = max(0, width - int(tabwidth*indent))
+ self.lwidth = int(self.width*ratio)
+ self.rwidth = max(0, self.width - self.lwidth)
+ self.clwidth = 0
+ self.crwidth = 0
+ self.lbuffer = ''
+ self.rbuffer = ''
+ self.left = True
+
+ def _txt(self,txt):
+ print '_txt: ',txt
+ if self.left:
+ if self.clwidth < self.lwidth:
+ txt = txt[:max(0, self.lwidth - self.clwidth)]
+ self.lbuffer += txt
+ self.clwidth += len(txt)
+ else:
+ if self.crwidth < self.rwidth:
+ txt = txt[:max(0, self.rwidth - self.crwidth)]
+ self.rbuffer += txt
+ self.crwidth += len(txt)
+
+ def start_inline(self,stylestack=None):
+ print 'LINE:start_entity'
+ if (self.left and self.clwidth) or (not self.left and self.crwidth):
+ self._txt(' ')
+
+ def start_block(self,stylestack=None):
+ self.start_inline(stylestack)
+
+ def end_entity(self):
+ pass
+
+ def pre(self,text):
+ if text:
+ self._txt(text)
+ def text(self,text):
+ if text:
+ text = utfstr(text)
+ text = text.strip()
+ text = re.sub('\s+',' ',text)
+ if text:
+ print 'LINE:printing text:'+text
+ self._txt(text)
+
+ def linebreak(self):
+ pass
+ def style(self,stylestack):
+ pass
+ def raw(self,raw):
+ pass
+
+ def start_right(self):
+ self.left = False
+
+ def get_line(self):
+ print 'LBUFFER: '+self.lbuffer
+ print self.clwidth
+ print 'RBUFFER: '+self.rbuffer
+ print self.crwidth
+
+ return ' ' * self.indent * self.tabwidth + self.lbuffer + ' ' * (self.width - self.clwidth - self.crwidth) + self.rbuffer
+
+
class Escpos:
""" ESC/POS Printer object """
device = None
encoding = None
img_cache = {}
-
def _check_image_size(self, size):
""" Check and fix the size of the image to 32 bits """
if size % 32 == 0:
else:
return (image_border / 2, (image_border / 2) + 1)
-
def _print_image(self, line, size):
""" Print formatted image """
i = 0
return raw
-
def _convert_image(self, im):
""" Parse image and prepare it to a printable format """
pixels = []
# Convert the RGB image in printable image
self._convert_image(im)
-
- def barcode(self, code, bc, width, height, pos, font):
+ def barcode(self, code, bc, width=255, height=2, pos='below', font='a'):
""" Print Barcode """
# Align Bar Code()
self._raw(TXT_ALIGN_CT)
else:
raise exception.BarcodeCodeError()
+ def receipt(self,xml):
+ """
+ Prints an xml based receipt definition
+ """
+
+ def strclean(string):
+ if not string:
+ string = ''
+ string = string.strip()
+ string = re.sub('\s+',' ',string)
+ return string
+
+ def format_value(value, decimals=3, width=0, decimals_separator='.', thousands_separator=',', autoint=False, symbol='', position='after'):
+ decimals = max(0,int(decimals))
+ width = max(0,int(width))
+ value = float(value)
+
+ if autoint and math.floor(value) == value:
+ decimals = 0
+ if width == 0:
+ width = ''
+
+ if thousands_separator:
+ formatstr = "{:"+str(width)+",."+str(decimals)+"f}"
+ else:
+ formatstr = "{:"+str(width)+"."+str(decimals)+"f}"
+
+
+ print formatstr
+ print value
+ ret = formatstr.format(value)
+ print ret
+ ret = ret.replace(',','COMMA')
+ ret = ret.replace('.','DOT')
+ ret = ret.replace('COMMA',thousands_separator)
+ ret = ret.replace('DOT',decimals_separator)
+ print 'RET '+ret
+
+ if symbol:
+ if position == 'after':
+ ret = ret + symbol
+ else:
+ ret = symbol + ret
+ return ret
+
+ def print_elem(stylestack, serializer, elem, indent=0):
+
+ elem_styles = {
+ 'h1': {'bold': 'on', 'size':'double'},
+ 'h2': {'size':'double'},
+ 'h3': {'bold': 'on', 'size':'double-height'},
+ 'h4': {'size': 'double-height'},
+ 'h5': {'bold': 'on'},
+ 'em': {'font': 'b'},
+ 'b': {'bold': 'on'},
+ }
+
+ stylestack.push()
+ if elem.tag in elem_styles:
+ stylestack.set(elem_styles[elem.tag])
+ stylestack.set(elem.attrib)
+
+ if elem.tag in ('p','div','section','article','receipt','header','footer','li','h1','h2','h3','h4','h5'):
+ serializer.start_block(stylestack)
+ serializer.text(elem.text)
+ for child in elem:
+ print_elem(stylestack,serializer,child)
+ serializer.start_inline(stylestack)
+ serializer.text(child.tail)
+ serializer.end_entity()
+ serializer.end_entity()
+
+ elif elem.tag in ('span','em','b','left','right'):
+ serializer.start_inline(stylestack)
+ serializer.text(elem.text)
+ for child in elem:
+ print_elem(stylestack,serializer,child)
+ serializer.start_inline(stylestack)
+ serializer.text(child.tail)
+ serializer.end_entity()
+ serializer.end_entity()
+
+ elif elem.tag == 'value':
+ serializer.start_inline(stylestack)
+ serializer.pre(format_value(
+ elem.text,
+ decimals=stylestack.get('value-decimals'),
+ width=stylestack.get('value-width'),
+ decimals_separator=stylestack.get('value-decimals-separator'),
+ thousands_separator=stylestack.get('value-thousands-separator'),
+ autoint=(stylestack.get('autoint') == 'on'),
+ symbol=stylestack.get('value-symbol'),
+ position=stylestack.get('value-symbol-position')
+ ))
+ serializer.end_entity()
+
+ elif elem.tag == 'line':
+ width = stylestack.get('width')
+ if stylestack.get('size') in ('double', 'double-width'):
+ width = width / 2
+
+ lineserializer = XmlLineSerializer(stylestack.get('indent')+indent,stylestack.get('tabwidth'),width,stylestack.get('line-ratio'))
+ serializer.start_block(stylestack)
+ for child in elem:
+ if child.tag == 'left':
+ print_elem(stylestack,lineserializer,child,indent=indent)
+ elif child.tag == 'right':
+ lineserializer.start_right()
+ print_elem(stylestack,lineserializer,child,indent=indent)
+ serializer.pre(lineserializer.get_line())
+ serializer.end_entity()
+
+ elif elem.tag == 'ul':
+ serializer.start_block(stylestack)
+ bullet = stylestack.get('bullet')
+ for child in elem:
+ if child.tag == 'li':
+ serializer.style(stylestack)
+ serializer.raw(' ' * indent * stylestack.get('tabwidth') + bullet)
+ print_elem(stylestack,serializer,child,indent=indent+1)
+ serializer.end_entity()
+
+ elif elem.tag == 'ol':
+ cwidth = len(str(len(elem))) + 2
+ i = 1
+ serializer.start_block(stylestack)
+ for child in elem:
+ if child.tag == 'li':
+ serializer.style(stylestack)
+ serializer.raw(' ' * indent * stylestack.get('tabwidth') + ' ' + (str(i)+')').ljust(cwidth))
+ i = i + 1
+ print_elem(stylestack,serializer,child,indent=indent+1)
+ serializer.end_entity()
+
+ elif elem.tag == 'pre':
+ serializer.start_block(stylestack)
+ serializer.pre(elem.text)
+ serializer.end_entity()
+
+ elif elem.tag == 'hr':
+ width = stylestack.get('width')
+ if stylestack.get('size') in ('double', 'double-width'):
+ width = width / 2
+ serializer.start_block(stylestack)
+ serializer.text('-'*width)
+ serializer.end_entity()
+
+ elif elem.tag == 'br':
+ serializer.linebreak()
+
+ elif elem.tag == 'img':
+ if src in elem.attrib and 'data:' in elem.attrib['src']:
+ self.print_base64_image(elem.attrib['src'])
+
+ elif elem.tag == 'barcode' and 'encoding' in elem.attrib:
+ serializer.start_block(stylestack)
+ self.barcode(strclean(elem.text),elem.attrib['encoding'])
+ serializer.end_entity()
+
+ elif elem.tag == 'cut':
+ self.cut()
+ elif elem.tag == 'partialcut':
+ self.cut(mode='part')
+ elif elem.tag == 'cashdraw':
+ self.cashdraw(2)
+ self.cashdraw(5)
+
+ stylestack.pop()
+
+ try:
+ stylestack = StyleStack()
+ serializer = XmlSerializer(self)
+ root = ET.fromstring(xml)
+
+ self._raw(stylestack.to_escpos())
+
+ print_elem(stylestack,serializer,root)
+
+ if 'open-cashdrawer' in root.attrib and root.attrib['open-cashdrawer'] == 'true':
+ self.cashdraw(2)
+ self.cashdraw(5)
+ if not 'cut' in root.attrib or root.attrib['cut'] == 'true' :
+ self.cut()
+
+ except Exception as e:
+ errmsg = str(e)+'\n'+'-'*48+'\n'+traceback.format_exc() + '-'*48+'\n'
+ self.text(errmsg)
+ self.cut()
+
+ raise e
+
def text(self,txt):
""" Print Utf8 encoded alpha-numeric text """
if not txt:
http = openerp.http
import controllers
+import cli
wsgi_postload = http.wsgi_postload
"static/test/data.js",
"static/test/list-utils.js",
"static/test/formats.js",
+ "static/test/jsonrpc.js",
"static/test/rpc-misordered.js",
"static/test/evals.js",
"static/test/search.js",
--- /dev/null
+import test_js
--- /dev/null
+import logging
+import optparse
+import sys
+
+import unittest2
+
+import openerp
+import openerp.addons.web.tests
+
+_logger = logging.getLogger(__name__)
+
+class TestJs(openerp.cli.Command):
+ def run(self, args):
+ self.parser = parser = optparse.OptionParser()
+ parser.add_option("-d", "--database", dest="db_name", default=False, help="specify the database name")
+ parser.add_option("--xmlrpc-port", dest="xmlrpc_port", default=8069, help="specify the TCP port for the XML-RPC protocol", type="int")
+ # proably need to add both --superadmin-password and --database-admin-password
+ self.parser.parse_args(args)
+
+ # test ony uses db_name xmlrpc_port admin_passwd, so use the server one for the actual parsing
+
+ config = openerp.tools.config
+ config.parse_config(args)
+ # needed until runbot is fixed
+ config['db_password'] = config['admin_passwd']
+
+ # run js tests
+ openerp.netsvc.init_alternative_logger()
+ suite = unittest2.TestSuite()
+ suite.addTests(unittest2.TestLoader().loadTestsFromModule(openerp.addons.web.tests.test_js))
+ r = unittest2.TextTestRunner(verbosity=2).run(suite)
+ if r.errors or r.failures:
+ sys.exit(1)
+
+# vim:et:ts=4:sw=4:
import os
import re
import simplejson
-import sys
import time
import urllib2
import zlib
from openerp.tools.translate import _
from openerp import http
-from openerp.http import request, serialize_exception as _serialize_exception
+from openerp.http import request, serialize_exception as _serialize_exception, LazyResponse
_logger = logging.getLogger(__name__)
-if hasattr(sys, 'frozen'):
- # When running on compiled windows binary, we don't have access to package loader.
- path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'views'))
- loader = jinja2.FileSystemLoader(path)
-else:
- loader = jinja2.PackageLoader('openerp.addons.web', "views")
-
-env = jinja2.Environment(loader=loader, autoescape=True)
+env = jinja2.Environment(
+ loader=jinja2.PackageLoader('openerp.addons.web', "views"),
+ autoescape=True
+)
env.filters["json"] = simplejson.dumps
#----------------------------------------------------------
"""
return http.redirect_with_hash(*args, **kw)
-def abort_and_redirect(url):
- r = request.httprequest
- response = werkzeug.utils.redirect(url, 302)
- response = r.app.get_response(r, response, explicit_session=False)
- werkzeug.exceptions.abort(response)
-
def ensure_db(redirect='/web/database/selector'):
# This helper should be used in web client auth="none" routes
# if those routes needs a db to work with.
# may depend on data injected by the database route dispatcher.
# Thus, we redirect the user to the same page but with the session cookie set.
# This will force using the database route dispatcher...
+ r = request.httprequest
+ response = werkzeug.utils.redirect(r.url, 302)
request.session.db = db
- abort_and_redirect(request.httprequest.url)
+ response = r.app.get_response(r, response, explicit_session=False)
+ werkzeug.exceptions.abort(response)
+ return
# if db not provided, use the session one
if not db:
# always switch the session to the computed db
if db != request.session.db:
request.session.logout()
- abort_and_redirect(request.httprequest.url)
request.session.db = db
r.append((None, pattern))
else:
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
- # Hack for IE, who limit 288Ko, 4095 rules, 31 sheets
- # http://support.microsoft.com/kb/262161/en
- if pattern == "static/lib/bootstrap/css/bootstrap.css":
- if include_remotes:
- r.insert(0, (None, fs2web(path[len(addons_path):])))
- else:
- r.append((path, fs2web(path[len(addons_path):])))
+ r.append((path, fs2web(path[len(addons_path):])))
return r
def manifest_list(extension, mods=None, db=None, debug=False):
redirect.autocorrect_location_header = False
return redirect
-def login_redirect():
- url = '/web/login?'
- if request.debug:
- url += 'debug&'
- return """<html><head><script>
- window.location = '%sredirect=' + encodeURIComponent(window.location);
- </script></head></html>
- """ % (url,)
-
def load_actions_from_ir_values(key, key2, models, meta):
Values = request.session.model('ir.values')
actions = Values.get(key, key2, models, meta, request.context)
</html>
"""
-def render_bootstrap_template(template, values=None, debug=False, db=None, **kw):
- if not db:
- db = request.db
- if request.debug:
+def render_bootstrap_template(db, template, values=None, debug=False, lazy=False, **kw):
+ if request and request.debug:
debug = True
if values is None:
values = {}
+ values.update(kw)
values['debug'] = debug
values['current_db'] = db
try:
values['modules'] = module_boot(db=db)
values['modules'] = simplejson.dumps(values['modules'])
- return request.render(template, values, **kw)
+ def callback(template, values):
+ registry = openerp.modules.registry.RegistryManager.get(db)
+ with registry.cursor() as cr:
+ view_obj = registry["ir.ui.view"]
+ return view_obj.render(cr, openerp.SUPERUSER_ID, template, values)
+ if lazy:
+ return LazyResponse(callback, template=template, values=values)
+ else:
+ return callback(template, values)
class Home(http.Controller):
@http.route('/', type='http', auth="none")
def index(self, s_action=None, db=None, **kw):
- return http.local_redirect('/web', query=request.params, keep_hash=True)
+ return http.local_redirect('/web', query=request.params)
@http.route('/web', type='http', auth="none")
def web_client(self, s_action=None, **kw):
ensure_db()
if request.session.uid:
- headers = {
- 'Cache-Control': 'no-cache',
- 'Content-Type': 'text/html; charset=utf-8',
- }
- return render_bootstrap_template("web.webclient_bootstrap", headers=headers)
+ html = render_bootstrap_template(request.session.db, "web.webclient_bootstrap")
+ return request.make_response(html, {'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8'})
else:
- return login_redirect()
+ return http.local_redirect('/web/login', query=request.params)
@http.route('/web/login', type='http', auth="none")
def web_login(self, redirect=None, **kw):
ensure_db()
- if not request.uid:
- request.uid = openerp.SUPERUSER_ID
-
values = request.params.copy()
if not redirect:
redirect = '/web?' + request.httprequest.query_string
if uid is not False:
return http.redirect_with_hash(redirect)
values['error'] = "Wrong login/password"
- return render_bootstrap_template('web.login', values)
+ return render_bootstrap_template(request.session.db, 'web.login', values, lazy=True)
@http.route('/login', type='http', auth="none")
def login(self, db, login, key, redirect="/web", **kw):
return simplejson.dumps([[],[{'error': openerp.tools.ustr(e), 'title': _('Backup Database')}]])
@http.route('/web/database/restore', type='http', auth="none")
- def restore(self, db_file, restore_pwd, new_db, mode):
+ def restore(self, db_file, restore_pwd, new_db):
try:
- copy = mode == 'copy'
data = base64.b64encode(db_file.read())
- request.session.proxy("db").restore(restore_pwd, new_db, data, copy)
+ request.session.proxy("db").restore(restore_pwd, new_db, data)
return ''
except openerp.exceptions.AccessDenied, e:
raise Exception("AccessDenied")
:return: A key identifying the saved action.
:rtype: integer
"""
- return request.httpsession.save_action(the_action)
+ saved_actions = request.httpsession.get('saved_actions')
+ if not saved_actions:
+ saved_actions = {"next":1, "actions":{}}
+ request.httpsession['saved_actions'] = saved_actions
+ # we don't allow more than 10 stored actions
+ if len(saved_actions["actions"]) >= 10:
+ del saved_actions["actions"][min(saved_actions["actions"])]
+ key = saved_actions["next"]
+ saved_actions["actions"][key] = the_action
+ saved_actions["next"] = key + 1
+ request.httpsession['saved_actions'] = saved_actions
+ return key
@http.route('/web/session/get_session_action', type='json', auth="user")
def get_session_action(self, key):
:return: The saved action or None.
:rtype: anything
"""
- return request.httpsession.get_action(key)
+ saved_actions = request.httpsession.get('saved_actions')
+ if not saved_actions:
+ return None
+ return saved_actions["actions"].get(key)
@http.route('/web/session/check', type='json', auth="user")
def check(self):
model, map(operator.itemgetter('name'), export_fields_list))
return [
- {'name': field['name'], 'label': fields_data[field['name']]}
- for field in export_fields_list
+ {'name': field_name, 'label': fields_data[field_name]}
+ for field_name in fields_data.keys()
]
def fields_info(self, model, export_fields):
<script src="/web/static/lib/qunit/qunit.js"></script>
<script type="text/javascript">
+ var oe_db_info = ${db_info | n};
// List of modules, each module is preceded by its dependencies
var oe_all_dependencies = ${dependencies | n};
QUnit.config.testTimeout = 5 * 60 * 1000;
for mod, tests in itertools.izip(sorted_mods, tests)
]
+ # if all three db_info parameters are present, send them to the page
+ db_info = dict((k, v) for k, v in kwargs.iteritems()
+ if k in ['source', 'supadmin', 'password'])
+ if len(db_info) != 3:
+ db_info = None
+
return TESTING.render(files=files, dependencies=json.dumps(
[name for name in sorted_mods
if module.get_module_resource(name, 'static')
- if manifests[name]['js']]))
+ if manifests[name]['js']]), db_info=json.dumps(db_info))
def load_manifest(self, name):
manifest = module.load_information_from_description_file(name)
# replace OS path separators (from join & normpath) by URI ones
yield path[len(root):].replace(os.path.sep, '/')
+ @http.route('/web/tests/set_session_value', type='json', auth="none")
+ def set_session_value(self, value):
+ request.session.some_test_value = value
+
+ @http.route('/web/tests/get_session_value', type='json', auth="none")
+ def get_session_value(self):
+ return request.session.some_test_value
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:01+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
"PO-Revision-Date: 2014-01-30 17:05+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
"Language-Team: Bosnian <bs@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: web
#: code:addons/web/static/src/xml/base.xml:467
#, python-format
msgid "Powered by"
-msgstr "Založeno na"
+msgstr ""
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"Language: es\n"
#. module: web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-17 05:44+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:558
#, python-format
msgid "Toggle Form Layout Outline"
-msgstr "Vaihda lomakkeen asettelua"
+msgstr "Näytä Sijoittelu"
#. module: web
#. openerp-web
#: code:addons/web/static/src/js/view_list_editable.js:793
#, python-format
msgid "The form's data can not be discarded"
-msgstr "Lomakkeen tietoja ei voi hylätä"
+msgstr "Asiakirjan dataa ei voida hylätä"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:147
#, python-format
msgid "Default language:"
-msgstr "デフォルト言語:"
+msgstr "デフォルトの言語:"
#. module: web
#. openerp-web
#: code:addons/web/static/src/js/view_form.js:1071
#, python-format
msgid "Set Default"
-msgstr "デフォルト値設定"
+msgstr "デフォルトに設定"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:873
#, python-format
msgid "Condition:"
-msgstr "条件:"
+msgstr "状態:"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:899
#, python-format
msgid "All users"
-msgstr "全ユーザ"
+msgstr "全てのユーザ"
#. module: web
#. openerp-web
#: code:addons/web/static/src/js/view_form.js:1078
#, python-format
msgid "Save default"
-msgstr "デフォルト値保存"
+msgstr "デフォルトに保存"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:567
#, python-format
msgid "Manage Views"
-msgstr "ビュー管理"
+msgstr "ビューの管理"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:561
#, python-format
msgid "JS Tests"
-msgstr "JSテスト"
+msgstr ""
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:856
#, python-format
msgid "Default:"
-msgstr "デフォルト値:"
+msgstr "デフォルト:"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:559
#, python-format
msgid "Set Defaults"
-msgstr "デフォルト値設定"
+msgstr ""
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:892
#, python-format
msgid "Only you"
-msgstr "自分のみ"
+msgstr "あなただけ"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:01+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
#: code:addons/web/static/src/xml/base.xml:147
#, python-format
msgid "Default language:"
-msgstr "ภาษาหลัก"
+msgstr "ภาษาหลัก:"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web
#. openerp-web
.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}\r
.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}\r
.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}\r
-.cleditorPopup {border:solid 1px #999; background-color:white; color:#333333; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}\r
+.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}\r
.cleditorList div {padding:2px 4px 2px 4px}\r
.cleditorList p,\r
.cleditorList h1,\r
-/*!\r
- CLEditor WYSIWYG HTML Editor v1.4.4\r
- http://premiumsoftware.net/CLEditor\r
+/**\r
+ @preserve CLEditor WYSIWYG HTML Editor v1.3.0\r
+ http://premiumsoftware.net/cleditor\r
requires jQuery v1.4.2 or later\r
\r
Copyright 2010, Chris Landowski, Premium Software, LLC\r
Dual licensed under the MIT or GPL Version 2 licenses.\r
*/\r
\r
-(function ($) {\r
+// ==ClosureCompiler==\r
+// @compilation_level SIMPLE_OPTIMIZATIONS\r
+// @output_file_name jquery.cleditor.min.js\r
+// ==/ClosureCompiler==\r
+\r
+(function($) {\r
\r
//==============\r
// jQuery Plugin\r
\r
// Define the defaults used for all new cleditor instances\r
defaultOptions: {\r
- width: 'auto', // width not including margins, borders or padding\r
+ width: 500, // width not including margins, borders or padding\r
height: 250, // height not including margins, borders or padding\r
controls: // controls to add to the toolbar\r
"bold italic underline strikethrough subscript superscript | font size " +\r
[["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],\r
["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"],\r
["Header 6","<h6>"]],\r
- useCSS: true, // use CSS to style HTML when possible (not supported in ie)\r
+ useCSS: false, // use CSS to style HTML when possible (not supported in ie)\r
docType: // Document type contained within the editor\r
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',\r
docCSSFile: // CSS file used to style the document contained within the editor\r
\r
// Define all usable toolbar buttons - the init string property is \r
// expanded during initialization back into the buttons object and \r
- // separate object properties are created for each button.\r
+ // seperate object properties are created for each button.\r
// e.g. buttons.size.title = "Font Size"\r
buttons: {\r
// name,title,command,popupName (""=use name)\r
\r
// Loop through all matching textareas and create the editors\r
this.each(function(idx, elem) {\r
- if (elem.tagName.toUpperCase() === "TEXTAREA") {\r
+ if (elem.tagName == "TEXTAREA") {\r
var data = $.data(elem, CLEDITOR);\r
if (!data) data = new cleditor(elem, options);\r
$result = $result.add(data);\r
\r
// Misc constants\r
BACKGROUND_COLOR = "backgroundColor",\r
- BLURRED = "blurred",\r
BUTTON = "button",\r
BUTTON_NAME = "buttonName",\r
CHANGE = "change",\r
CLICK = "click",\r
DISABLED = "disabled",\r
DIV_TAG = "<div>",\r
- FOCUSED = "focused",\r
TRANSPARENT = "transparent",\r
UNSELECTABLE = "unselectable",\r
\r
PROMPT_CLASS = "cleditorPrompt", // prompt popup divs inside body\r
MSG_CLASS = "cleditorMsg", // message popup div inside body\r
\r
- // Browser detection\r
- ua = navigator.userAgent.toLowerCase(),\r
- ie = /msie/.test(ua),\r
- ie6 = /msie\s6/.test(ua),\r
- iege11 = /(trident)(?:.*rv:([\w.]+))?/.test(ua),\r
- webkit = /webkit/.test(ua),\r
+ // Test for ie\r
+ ie = $.browser.msie,\r
+ ie6 = /msie\s6/i.test(navigator.userAgent),\r
\r
// Test for iPhone/iTouch/iPad\r
- iOS = /iphone|ipad|ipod/i.test(ua),\r
+ iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),\r
\r
// Popups are created once as needed and shared by all editor instances\r
popups = {},\r
var $group = $(DIV_TAG)\r
.addClass(GROUP_CLASS)\r
.appendTo($toolbar);\r
-\r
- // Initialize the group width\r
- var groupWidth = 0;\r
\r
// Add the buttons to the toolbar\r
$.each(options.controls.split(" "), function(idx, buttonName) {\r
if (buttonName === "") return true;\r
\r
// Divider\r
- if (buttonName === "|") {\r
+ if (buttonName == "|") {\r
\r
// Add a new divider to the group\r
var $div = $(DIV_TAG)\r
.addClass(DIVIDER_CLASS)\r
.appendTo($group);\r
\r
- // Update the group width\r
- $group.width(groupWidth + 1);\r
- groupWidth = 0;\r
-\r
// Create a new group\r
$group = $(DIV_TAG)\r
.addClass(GROUP_CLASS)\r
.appendTo($group)\r
.hover(hoverEnter, hoverLeave);\r
\r
- // Update the group width\r
- groupWidth += 24;\r
- $group.width(groupWidth + 1);\r
-\r
// Prepare the button image\r
var map = {};\r
if (button.css) map = button.css;\r
\r
// Bind the window resize event when the width or height is auto or %\r
if (/auto|%/.test("" + options.width + options.height))\r
- $(window).bind('resize.cleditor', function () {\r
+ $(window).resize(function() {\r
//Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears\r
var contentWindow = editor.$frame[0].contentWindow;\r
if(!$.browser.mozilla && contentWindow){\r
refresh(editor);\r
}\r
});\r
+\r
// Create the iframe and resize the controls\r
refresh(editor);\r
\r
return editor;\r
};\r
});\r
- \r
- // blurred - shortcut for .bind("blurred", handler) or .trigger("blurred")\r
- fn.blurred = function(handler) {\r
- var $this = $(this);\r
- return handler ? $this.bind(BLURRED, handler) : $this.trigger(BLURRED);\r
- };\r
\r
// change - shortcut for .bind("change", handler) or .trigger("change")\r
- fn.change = function change(handler) {\r
- console.log('change test');\r
+ fn.change = function(handler) {\r
var $this = $(this);\r
return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);\r
};\r
\r
- // focused - shortcut for .bind("focused", handler) or .trigger("focused")\r
- fn.focused = function(handler) {\r
- var $this = $(this);\r
- return handler ? $this.bind(FOCUSED, handler) : $this.trigger(FOCUSED);\r
- };\r
-\r
//===============\r
// Event Handlers\r
//===============\r
popup = popups[popupName];\r
\r
// Check if disabled\r
- if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED)\r
+ if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)\r
return;\r
\r
// Fire the buttonClick event\r
return false;\r
\r
// Toggle source\r
- if (buttonName === "source") {\r
+ if (buttonName == "source") {\r
\r
// Show the iframe\r
if (sourceMode(editor)) {\r
var $popup = $(popup);\r
\r
// URL\r
- if (popupName === "url") {\r
+ if (popupName == "url") {\r
\r
// Check for selection before showing the link url popup\r
- if (buttonName === "link" && selectedText(editor) === "") {\r
+ if (buttonName == "link" && selectedText(editor) === "") {\r
showMessage(editor, "A selection is required when inserting a link.", buttonDiv);\r
return false;\r
}\r
}\r
\r
// Paste as Text\r
- else if (popupName === "pastetext") {\r
+ else if (popupName == "pastetext") {\r
\r
// Wire up the submit button click event handler\r
$popup.children(":button")\r
return false; // stop propagination to document click\r
}\r
\r
- // propaginate to document click\r
+ // propaginate to documnt click\r
return;\r
\r
}\r
\r
// Print\r
- else if (buttonName === "print")\r
+ else if (buttonName == "print")\r
editor.$frame[0].contentWindow.print();\r
\r
// All other buttons\r
useCSS = editor.options.useCSS;\r
\r
// Get the command value\r
- if (buttonName === "font")\r
+ if (buttonName == "font")\r
// Opera returns the fontfamily wrapped in quotes\r
value = target.style.fontFamily.replace(/"/g, "");\r
- else if (buttonName === "size") {\r
- if (target.tagName.toUpperCase() === "DIV")\r
+ else if (buttonName == "size") {\r
+ if (target.tagName == "DIV")\r
target = target.children[0];\r
value = target.innerHTML;\r
}\r
- else if (buttonName === "style")\r
+ else if (buttonName == "style")\r
value = "<" + target.tagName + ">";\r
- else if (buttonName === "color")\r
+ else if (buttonName == "color")\r
value = hex(target.style.backgroundColor);\r
- else if (buttonName === "highlight") {\r
+ else if (buttonName == "highlight") {\r
value = hex(target.style.backgroundColor);\r
if (ie) command = 'backcolor';\r
else useCSS = true;\r
$popup.html(popupContent);\r
\r
// Color\r
- else if (popupName === "color") {\r
+ else if (popupName == "color") {\r
var colors = options.colors.split(" ");\r
if (colors.length < 10)\r
$popup.width("auto");\r
}\r
\r
// Font\r
- else if (popupName === "font")\r
+ else if (popupName == "font")\r
$.each(options.fonts.split(","), function(idx, font) {\r
$(DIV_TAG).appendTo($popup)\r
.css("fontFamily", font)\r
});\r
\r
// Size\r
- else if (popupName === "size")\r
+ else if (popupName == "size")\r
$.each(options.sizes.split(","), function(idx, size) {\r
$(DIV_TAG).appendTo($popup)\r
- .html('<font size="' + size + '">' + size + '</font>');\r
+ .html("<font size=" + size + ">" + size + "</font>");\r
});\r
\r
// Style\r
- else if (popupName === "style")\r
+ else if (popupName == "style")\r
$.each(options.styles, function(idx, style) {\r
$(DIV_TAG).appendTo($popup)\r
.html(style[1] + style[0] + style[1].replace("<", "</"));\r
});\r
\r
// URL\r
- else if (popupName === "url") {\r
- $popup.html('Enter URL:<br /><input type="text" value="http://" size="35" /><br /><input type="button" value="Submit" />');\r
+ else if (popupName == "url") {\r
+ $popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');\r
popupTypeClass = PROMPT_CLASS;\r
}\r
\r
// Paste as Text\r
- else if (popupName === "pastetext") {\r
- $popup.html('Paste your content here and click submit.<br /><textarea cols="40" rows="3"></textarea><br /><input type="button" value="Submit" />');\r
+ else if (popupName == "pastetext") {\r
+ $popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');\r
popupTypeClass = PROMPT_CLASS;\r
}\r
\r
}\r
\r
// Execute the command and check for error\r
- var success = true, message;\r
- if (ie && command.toLowerCase() === "inserthtml")\r
+ var success = true, description;\r
+ if (ie && command.toLowerCase() == "inserthtml")\r
getRange(editor).pasteHTML(value);\r
else {\r
try { success = editor.doc.execCommand(command, 0, value || null); }\r
- catch (err) { message = err.message; success = false; }\r
+ catch (err) { description = err.description; success = false; }\r
if (!success) {\r
if ("cutcopypaste".indexOf(command) > -1)\r
showMessage(editor, "For security reasons, your browser does not support the " +\r
button);\r
else\r
showMessage(editor,\r
- (message ? message : "Error executing the " + command + " command."),\r
+ (description ? description : "Error executing the " + command + " command."),\r
button);\r
}\r
}\r
\r
- // Enable the buttons and update the textarea\r
+ // Enable the buttons\r
refreshButtons(editor);\r
- updateTextArea(editor, true);\r
return success;\r
\r
}\r
return editor.$frame[0].contentWindow.getSelection();\r
}\r
\r
- // hex - returns the hex value for the passed in color string\r
+ // Returns the hex value for the passed in string.\r
+ // hex("rgb(255, 0, 0)"); // #FF0000\r
+ // hex("#FF0000"); // #FF0000\r
+ // hex("#F00"); // #FF0000\r
function hex(s) {\r
-\r
- // hex("rgb(255, 0, 0)") returns #FF0000\r
- var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s);\r
+ var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),\r
+ c = s.split("");\r
if (m) {\r
- s = (m[1] << 16 | m[2] << 8 | m[3]).toString(16);\r
+ s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);\r
while (s.length < 6)\r
s = "0" + s;\r
- return "#" + s;\r
}\r
-\r
- // hex("#F00") returns #FF0000\r
- var c = s.split("");\r
- if (s.length === 4)\r
- return "#" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];\r
-\r
- // hex("#FF0000") returns #FF0000\r
- return s;\r
-\r
+ return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);\r
}\r
\r
// hidePopups - hides all popups\r
\r
// imagesPath - returns the path to the images folder\r
function imagesPath() {\r
- var href = $("link[href*=cleditor]").attr("href");\r
- return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/";\r
+ var cssFile = "jquery.cleditor.css",\r
+ href = $("link[href$='" + cssFile +"']").attr("href");\r
+ return href.substr(0, href.length - cssFile.length) + "images/";\r
}\r
\r
// imageUrl - Returns the css url string for a filemane\r
editor.$frame.remove();\r
\r
// Create a new iframe\r
- var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;" />')\r
+ var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')\r
.hide()\r
.appendTo($main);\r
\r
\r
// Work around for bug in IE which causes the editor to lose\r
// focus when clicking below the end of the document.\r
- if (ie || iege11)\r
+ if (ie)\r
$doc.click(function() {focus(editor);});\r
\r
// Load the content\r
updateFrame(editor);\r
\r
// Bind the ie specific iframe event handlers\r
- if (ie || iege11) {\r
+ if (ie) {\r
\r
// Save the current user selection. This code is needed since IE will\r
// reset the selection just after the beforedeactivate event and just\r
$doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {\r
\r
// Flag the editor as inactive\r
- if (e.type === "beforedeactivate")\r
+ if (e.type == "beforedeactivate")\r
editor.inactive = true;\r
-\r
- // Get rid of the bogus selection and flag the editor as active\r
- else if (e.type === "beforeactivate") {\r
+ \r
+ // Get rid of the bogus selection and flag the editor as active\r
+ else if (e.type == "beforeactivate") {\r
if (!editor.inactive && editor.range && editor.range.length > 1)\r
editor.range.shift();\r
delete editor.inactive;\r
}\r
\r
- // Save the selection when the editor is active\r
+ // Save the selection when the editor is active\r
else if (!editor.inactive) {\r
- if (!editor.range)\r
+ if (!editor.range) \r
editor.range = [];\r
editor.range.unshift(getRange(editor));\r
\r
\r
});\r
\r
- // Restore the text range and trigger focused event when the iframe gains focus\r
+ // Restore the text range when the iframe gains focus\r
$frame.focus(function() {\r
restoreRange(editor);\r
- $(editor).triggerHandler(FOCUSED);\r
- });\r
-\r
- // Trigger blurred event when the iframe looses focus\r
- $frame.blur(function() {\r
- $(editor).triggerHandler(BLURRED);\r
});\r
\r
}\r
\r
- // Trigger focused and blurred events for all other browsers\r
- else {\r
- $(editor.$frame[0].contentWindow)\r
- .focus(function () { $(editor).triggerHandler(FOCUSED); })\r
- .blur(function () { $(editor).triggerHandler(BLURRED); });\r
- }\r
+ // Update the textarea when the iframe loses focus\r
+ ($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {\r
+ updateTextArea(editor, true);\r
+ });\r
\r
- // Enable the toolbar buttons and update the textarea as the user types or clicks\r
+ // Enable the toolbar buttons as the user types or clicks\r
$doc.click(hidePopups)\r
.bind("keyup mouseup", function() {\r
refreshButtons(editor);\r
- updateTextArea(editor, true);\r
});\r
\r
// Show the textarea for iPhone/iTouch/iPad or\r
$toolbar.height(hgt);\r
\r
// Resize the iframe\r
- hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height, 10)) - hgt;\r
+ hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;\r
$frame.width(wid).height(hgt);\r
\r
// Resize the textarea. IE6 textareas have a 1px top\r
function refreshButtons(editor) {\r
\r
// Webkit requires focus before queryCommandEnabled will return anything but false\r
- if (!iOS && webkit && !editor.focused) {\r
+ if (!iOS && $.browser.webkit && !editor.focused) {\r
editor.$frame[0].contentWindow.focus();\r
window.focus();\r
editor.focused = true;\r
if (enabled === undefined)\r
enabled = true;\r
}\r
- else if (((inSourceMode || iOS) && button.name !== "source") ||\r
- (ie && (command === "undo" || command === "redo")))\r
+ else if (((inSourceMode || iOS) && button.name != "source") ||\r
+ (ie && (command == "undo" || command == "redo")))\r
enabled = false;\r
- else if (command && command !== "print") {\r
- if (ie && command === "hilitecolor")\r
+ else if (command && command != "print") {\r
+ if (ie && command == "hilitecolor")\r
command = "backcolor";\r
// IE does not support inserthtml, so it's always enabled\r
- if (!ie || command !== "inserthtml") {\r
+ if (!ie || command != "inserthtml") {\r
try {enabled = queryObj.queryCommandEnabled(command);}\r
catch (err) {enabled = false;}\r
}\r
\r
// restoreRange - restores the current ie selection\r
function restoreRange(editor) {\r
- if (editor.range) {\r
- if (ie)\r
- editor.range[0].select();\r
- else if (iege11)\r
- getSelection(editor).addRange(editor.range[0]);\r
- }\r
+ if (ie && editor.range)\r
+ editor.range[0].select();\r
}\r
\r
// select - selects all the text in either the textarea or iframe\r
// of potentially heavy updateFrame callbacks.\r
if (updateFrameCallback) {\r
var sum = checksum(code);\r
- if (checkForChange && editor.areaChecksum === sum)\r
+ if (checkForChange && editor.areaChecksum == sum)\r
return;\r
editor.areaChecksum = sum;\r
}\r
editor.frameChecksum = checksum(html);\r
\r
// Update the iframe and trigger the change event\r
- if (html !== $body.html()) {\r
+ if (html != $body.html()) {\r
$body.html(html);\r
$(editor).triggerHandler(CHANGE);\r
}\r
// of potentially heavy updateTextArea callbacks.\r
if (updateTextAreaCallback) {\r
var sum = checksum(html);\r
- if (checkForChange && editor.frameChecksum === sum)\r
+ if (checkForChange && editor.frameChecksum == sum)\r
return;\r
editor.frameChecksum = sum;\r
}\r
editor.areaChecksum = checksum(code);\r
\r
// Update the textarea and trigger the change event\r
- if (code !== $area.val()) {\r
+ if (code != $area.val()) {\r
$area.val(code);\r
$(editor).triggerHandler(CHANGE);\r
}\r
--- /dev/null
+/*
+ CLEditor WYSIWYG HTML Editor v1.3.0
+ http://premiumsoftware.net/cleditor
+ requires jQuery v1.4.2 or later
+
+ Copyright 2010, Chris Landowski, Premium Software, LLC
+ Dual licensed under the MIT or GPL Version 2 licenses.
+*/
+(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
+"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
+"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
+g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
+16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
+g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
+return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
+-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
+c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
+a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
+[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
+e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
+false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
+d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"<");if(d.updateTextArea)a.frameChecksum=
+C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
+colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
+["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
+imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
+L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
+f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
+k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
+function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
+a):b.trigger(F)}})(jQuery);
\ No newline at end of file
}
.fa {
display: inline-block;
- font-family: FontAwesome !important;
+ font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-// Underscore.js 1.6.0
+// Underscore.js 1.5.2
// http://underscorejs.org
-// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function() {
}
// Current version.
- _.VERSION = '1.6.0';
+ _.VERSION = '1.5.2';
// Collection Functions
// --------------------
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return obj;
+ if (obj == null) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
}
- return obj;
};
// Return the results of applying the iterator to each element.
};
// Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, predicate, context) {
+ _.find = _.detect = function(obj, iterator, context) {
var result;
any(obj, function(value, index, list) {
- if (predicate.call(context, value, index, list)) {
+ if (iterator.call(context, value, index, list)) {
result = value;
return true;
}
// Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`.
- _.filter = _.select = function(obj, predicate, context) {
+ _.filter = _.select = function(obj, iterator, context) {
var results = [];
if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
each(obj, function(value, index, list) {
- if (predicate.call(context, value, index, list)) results.push(value);
+ if (iterator.call(context, value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
- _.reject = function(obj, predicate, context) {
+ _.reject = function(obj, iterator, context) {
return _.filter(obj, function(value, index, list) {
- return !predicate.call(context, value, index, list);
+ return !iterator.call(context, value, index, list);
}, context);
};
// Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
- _.every = _.all = function(obj, predicate, context) {
- predicate || (predicate = _.identity);
+ _.every = _.all = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
var result = true;
if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
each(obj, function(value, index, list) {
- if (!(result = result && predicate.call(context, value, index, list))) return breaker;
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
});
return !!result;
};
// Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`.
- var any = _.some = _.any = function(obj, predicate, context) {
- predicate || (predicate = _.identity);
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
var result = false;
if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
each(obj, function(value, index, list) {
- if (result || (result = predicate.call(context, value, index, list))) return breaker;
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
});
return !!result;
};
// Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) {
- return _.map(obj, _.property(key));
+ return _.map(obj, function(value){ return value[key]; });
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
- _.where = function(obj, attrs) {
- return _.filter(obj, _.matches(attrs));
+ _.where = function(obj, attrs, first) {
+ if (_.isEmpty(attrs)) return first ? void 0 : [];
+ return _[first ? 'find' : 'filter'](obj, function(value) {
+ for (var key in attrs) {
+ if (attrs[key] !== value[key]) return false;
+ }
+ return true;
+ });
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {
- return _.find(obj, _.matches(attrs));
+ return _.where(obj, attrs, true);
};
// Return the maximum element or (element-based computation).
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.max.apply(Math, obj);
}
- var result = -Infinity, lastComputed = -Infinity;
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity, value: -Infinity};
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
- if (computed > lastComputed) {
- result = value;
- lastComputed = computed;
- }
+ computed > result.computed && (result = {value : value, computed : computed});
});
- return result;
+ return result.value;
};
// Return the minimum element (or element-based computation).
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.min.apply(Math, obj);
}
- var result = Infinity, lastComputed = Infinity;
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity, value: Infinity};
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
- if (computed < lastComputed) {
- result = value;
- lastComputed = computed;
- }
+ computed < result.computed && (result = {value : value, computed : computed});
});
- return result;
+ return result.value;
};
- // Shuffle an array, using the modern version of the
+ // Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) {
var rand;
return shuffled;
};
- // Sample **n** random values from a collection.
- // If **n** is not specified, returns a single random element.
+ // Sample **n** random values from an array.
+ // If **n** is not specified, returns a single random element from the array.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
- if (n == null || guard) {
- if (obj.length !== +obj.length) obj = _.values(obj);
+ if (arguments.length < 2 || guard) {
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
// An internal function to generate lookup iterators.
var lookupIterator = function(value) {
- if (value == null) return _.identity;
- if (_.isFunction(value)) return value;
- return _.property(value);
+ return _.isFunction(value) ? value : function(obj){ return obj[value]; };
};
// Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, iterator, context) {
- iterator = lookupIterator(iterator);
+ _.sortBy = function(obj, value, context) {
+ var iterator = lookupIterator(value);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
- return function(obj, iterator, context) {
+ return function(obj, value, context) {
var result = {};
- iterator = lookupIterator(iterator);
+ var iterator = value == null ? _.identity : lookupIterator(value);
each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj);
behavior(result, key, value);
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) {
- _.has(result, key) ? result[key].push(value) : result[key] = [value];
+ (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
- iterator = lookupIterator(iterator);
+ iterator = iterator == null ? _.identity : lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0;
- if ((n == null) || guard) return array[0];
- if (n < 0) return [];
- return slice.call(array, 0, n);
+ return (n == null) || guard ? array[0] : slice.call(array, 0, n);
};
// Returns everything but the last entry of the array. Especially useful on
// values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) {
if (array == null) return void 0;
- if ((n == null) || guard) return array[array.length - 1];
- return slice.call(array, Math.max(array.length - n, 0));
+ if ((n == null) || guard) {
+ return array[array.length - 1];
+ } else {
+ return slice.call(array, Math.max(array.length - n, 0));
+ }
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
return _.difference(array, slice.call(arguments, 1));
};
- // Split an array into two arrays: one whose elements all satisfy the given
- // predicate, and one whose elements all do not satisfy the predicate.
- _.partition = function(array, predicate, context) {
- predicate = lookupIterator(predicate);
- var pass = [], fail = [];
- each(array, function(elem) {
- (predicate.call(context, elem) ? pass : fail).push(elem);
- });
- return [pass, fail];
- };
-
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) {
return _.every(rest, function(other) {
- return _.contains(other, item);
+ return _.indexOf(other, item) >= 0;
});
});
};
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = function() {
- var length = _.max(_.pluck(arguments, 'length').concat(0));
+ var length = _.max(_.pluck(arguments, "length").concat(0));
var results = new Array(length);
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i);
};
// Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context. _ acts
- // as a placeholder, allowing any combination of arguments to be pre-filled.
+ // arguments pre-filled, without changing its dynamic `this` context.
_.partial = function(func) {
- var boundArgs = slice.call(arguments, 1);
+ var args = slice.call(arguments, 1);
return function() {
- var position = 0;
- var args = boundArgs.slice();
- for (var i = 0, length = args.length; i < length; i++) {
- if (args[i] === _) args[i] = arguments[position++];
- }
- while (position < arguments.length) args.push(arguments[position++]);
- return func.apply(this, args);
+ return func.apply(this, args.concat(slice.call(arguments)));
};
};
- // Bind a number of an object's methods to that object. Remaining arguments
- // are the method names to be bound. Useful for ensuring that all callbacks
- // defined on an object belong to it.
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
_.bindAll = function(obj) {
var funcs = slice.call(arguments, 1);
- if (funcs.length === 0) throw new Error('bindAll must be passed function names');
+ if (funcs.length === 0) throw new Error("bindAll must be passed function names");
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
return obj;
};
var previous = 0;
options || (options = {});
var later = function() {
- previous = options.leading === false ? 0 : _.now();
+ previous = options.leading === false ? 0 : new Date;
timeout = null;
result = func.apply(context, args);
- context = args = null;
};
return function() {
- var now = _.now();
+ var now = new Date;
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
timeout = null;
previous = now;
result = func.apply(context, args);
- context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
-
- var later = function() {
- var last = _.now() - timestamp;
- if (last < wait) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- context = args = null;
- }
- }
- };
-
return function() {
context = this;
args = arguments;
- timestamp = _.now();
+ timestamp = new Date();
+ var later = function() {
+ var last = (new Date()) - timestamp;
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ }
+ };
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
- if (callNow) {
- result = func.apply(context, args);
- context = args = null;
- }
-
+ if (callNow) result = func.apply(context, args);
return result;
};
};
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
- return _.partial(wrapper, func);
+ return function() {
+ var args = [func];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
};
// Returns a function that is the composition of a list of functions, each
// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = function(obj) {
- if (!_.isObject(obj)) return [];
- if (nativeKeys) return nativeKeys(obj);
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys;
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))
- && ('constructor' in a && 'constructor' in b)) {
+ _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
return false;
}
// Add the first object to the stack of traversed objects.
return value;
};
- _.constant = function(value) {
- return function () {
- return value;
- };
- };
-
- _.property = function(key) {
- return function(obj) {
- return obj[key];
- };
- };
-
- // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
- _.matches = function(attrs) {
- return function(obj) {
- if (obj === attrs) return true; //avoid comparing an object to itself.
- for (var key in attrs) {
- if (attrs[key] !== obj[key])
- return false;
- }
- return true;
- }
- };
-
// Run a function **n** times.
_.times = function(n, iterator, context) {
var accum = Array(Math.max(0, n));
return min + Math.floor(Math.random() * (max - min + 1));
};
- // A (possibly faster) way to get the current timestamp as an integer.
- _.now = Date.now || function() { return new Date().getTime(); };
-
// List of HTML entities for escaping.
var entityMap = {
escape: {
});
- // AMD registration happens at the end for compatibility with AMD loaders
- // that may not enforce next-turn semantics on modules. Even though general
- // practice for AMD registration is to be anonymous, underscore registers
- // as a named module because, like jQuery, it is a base library that is
- // popular enough to be bundled in a third party lib, but not be part of
- // an AMD load request. Those cases could generate an error when an
- // anonymous define() is called outside of a loader request.
- if (typeof define === 'function' && define.amd) {
- define('underscore', [], function() {
- return _;
- });
- }
}).call(this);
-all: *.css
-%.css: %.sass
- sass -t expanded --compass --unix-newlines $< $@
-watch:
- sass -t expanded --compass --unix-newlines --watch .:.
+sass:
+ sass -t expanded --compass --unix-newlines --watch base.sass:base.css&
\ No newline at end of file
-@charset "utf-8";
+@charset "UTF-8";
@font-face {
font-family: "mnmliconsRegular";
src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot");
.openerp td {
vertical-align: top;
}
-.openerp .oe_title {
- width: 50%;
- float: left;
-}
-.openerp .oe_title:after {
- content: ".";
- display: block;
- height: 0;
- clear: both;
- visibility: hidden;
-}
-.openerp .oe_form_group {
- clear: both;
-}
.openerp .zebra tbody tr:nth-child(odd) td {
background-color: #f0f0fa;
background-color: #efeff8;
.openerp .oe_about .oe_bottom a {
color: #eeeeee;
}
-.openerp a.oe_form_uri:hover {
+.openerp .oe_form_uri {
+ color: #7c7bad;
+}
+.openerp .oe_form_uri:hover {
text-decoration: underline;
}
.openerp .oe_application {
border-radius: 0 3px 3px 0;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
+ height: 18px;
padding: 0 4px;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category {
}
.openerp .oe_form > :not(.oe_form_nosheet) header .oe_button {
margin: 3px 2px 1px;
+ float: left;
}
.openerp .oe_form > :not(.oe_form_nosheet) header .oe_button:first-child {
margin-left: 6px;
}
.openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span {
font-size: 80%;
- color: darkgreen;
+ color: darkGreen;
vertical-align: top;
position: relative;
top: -4px;
}
.openerp .oe_form .oe_form_embedded_html {
position: relative;
- width: 100%;
- margin: auto;
- overflow: auto;
+ width: 600px;
+ margin-left: 130px;
+ margin-top: 32px;
+ margin-bottom: 32px;
text-align: justify;
}
.openerp .oe_form .oe_form_field_html .oe_input_icon {
font-size: 95%;
line-height: 1.2em;
}
+.openerp .oe_debug_view_log label {
+ display: block;
+ width: 49%;
+ text-align: right;
+ float: left;
+ font-weight: bold;
+ color: #000099;
+}
+.openerp .oe_debug_view_log span {
+ display: block;
+ width: 49%;
+ float: right;
+ color: #333333;
+}
.openerp .navbar {
min-height: 32px;
margin-bottom: 0px;
border: none;
z-index: 1;
- position: static;
background-color: #414141;
background-color: #454343;
background-image: -webkit-gradient(linear, left top, left bottom, from(#646060), to(#262626));
border: none;
padding: 10px 0 3px 0;
}
+.openerp .jqstooltip {
+ height: auto !important;
+ width: auto !important;
+}
.openerp h5 {
font-weight: bold;
font-size: smaller;
margin: 3px 3px 0 !important;
}
-.jqstooltip {
- height: auto !important;
- width: auto !important;
- padding: 0;
-}
-
@-moz-document url-prefix() {
.openerp .oe_searchview .oe_searchview_search {
top: -1px;
vertical-align: middle
td
vertical-align: top
- .oe_title
- width: 50%
- float: left
- .oe_title:after
- content: "."
- display: block
- height: 0
- clear: both
- visibility: hidden
- .oe_form_group
- clear: both
.zebra tbody tr:nth-child(odd) td
background-color: #f0f0fa
@include vertical-gradient(#f0f0fa, #eeeef6)
color: #eee
// }}}
// ActionManager {{{
- a.oe_form_uri:hover
- text-decoration: underline
+ .oe_form_uri
+ color: $link-color
+ &:hover
+ text-decoration: underline
.oe_application
width: 100%
height: 100%
background: $tag-bg-light
@include radius(0 3px 3px 0)
.oe_facet_category, .oe_facet_value
+ height: 18px
padding: 0 4px
.oe_facet_category
color: white
float: right
.oe_button
margin: 3px 2px 1px
+ float: left
&:first-child
margin-left: 6px
overflow: hidden
.oe_form_embedded_html
position: relative
- width: 100%
- margin: auto
- overflow: auto
+ width: 600px
+ margin-left: 130px
+ margin-top: 32px
+ margin-bottom: 32px
text-align: justify
.oe_form_field_html .oe_input_icon
float: right
.oe_debug_view_log
font-size: 95%
line-height: 1.2em
+ .oe_debug_view_log label
+ display: block
+ width: 49%
+ text-align: right
+ float: left
+ font-weight: bold
+ color: #009
+ .oe_debug_view_log span
+ display: block
+ width: 49%
+ float: right
+ color: #333
// }}}
// Bootstrap HACKS {{{
.navbar
margin-bottom: 0px
border: none
z-index: 1
- position: static
background-color: #414141
@include vertical-gradient(#646060, #262626)
.navbar-default
border: none
padding: 10px 0 3px 0
-
+ // Customize for kanban tooltip
+ .jqstooltip
+ height: auto !important
+ width: auto !important
// Customize for chatter
h5
.oe_msg_subtype_check
margin: 3px 3px 0 !important
// }}}
-// Customize for kanban tooltip
-.jqstooltip
- height: auto !important
- width: auto !important
- padding: 0
-
+
@-moz-document url-prefix()
.openerp
.oe_searchview .oe_searchview_search
var fields = $(form).serializeArray();
self.rpc("/web/database/create", {'fields': fields}).done(function(result) {
if (result) {
- instance.web.redirect('/web');
+ instance.web.redirect('/web')
} else {
alert("Failed to create database");
}
var state = $.bbq.getState(true);
if (_.isEmpty(state) || state.action == "login") {
self.menu.has_been_loaded.done(function() {
- new instance.web.Model("res.users").call("read", [self.session.uid, ["action_id"]]).done(function(data) {
- if(data.action_id) {
- self.action_manager.do_action(data.action_id[0]);
- self.menu.open_action(data.action_id[0]);
- } else {
- var first_menu_id = self.menu.$el.find("a:first").data("menu");
- if(first_menu_id)
- self.menu.menu_click(first_menu_id);
- }
- });
+ var first_menu_id = self.menu.$el.find("a:first").data("menu");
+ if(first_menu_id) {
+ self.menu.menu_click(first_menu_id);
+ }
});
} else {
$(window).trigger('hashchange');
client.insertAfter(currentScript);
};
+openerp.web.LoginForm = openerp.web.Widget.extend({
+ init: function ($form) {
+ this._super(/* no parent */);
+ this.setElement($form);
+ this.$el.on('submit', this.on_submit);
+ this.start();
+ },
+ start: function () {
+ if (location.hash) {
+ this.$el.attr('action', this.$el.attr('action') + location.hash);
+ }
+ return this._super();
+ },
+ on_submit: function () {
+ return true;
+ },
+});
+
})();
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
{__context: {group_by: []}, __domain: []},
read_group_group);
- var raw_field = grouping_field && grouping_field.split(':')[0];
var aggregates = {};
_(fixed_group).each(function (value, key) {
if (key.indexOf('__') === 0
- || key === raw_field
- || key === raw_field + '_count') {
+ || key === grouping_field
+ || key === grouping_field + '_count') {
return;
}
aggregates[key] = value || 0;
this.model = new instance.web.Model(
model, fixed_group.__context, fixed_group.__domain);
+ var raw_field = grouping_field && grouping_field.split(':')[0];
var group_size = fixed_group[raw_field + '_count'] || fixed_group.__count || 0;
var leaf_group = fixed_group.__context.group_by.length === 0;
* 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 {Object} [options]
+ * @param {Array} fields fields to read and return, by default all fields are returned
* @returns {$.Deferred}
*/
read_ids: function (ids, fields, options) {
- if (_.isEmpty(ids))
- return $.Deferred().resolve([]);
-
options = options || {};
+ // TODO: reorder results to match ids list
return this._model.call('read',
- [ids, fields || false],
- {context: this.get_context(options.context)})
- .then(function (records) {
- if (records.length <= 1) { return records; }
- var indexes = {};
- for (var i = 0; i < ids.length; i++) {
- indexes[ids[i]] = i;
- }
- records.sort(function (a, b) {
- return indexes[a.id] - indexes[b.id];
- });
- return records;
- });
+ [ids, fields || false],
+ {context: this.get_context(options.context)});
},
/**
* Read a slice of the records represented by this DataSet, based on its
});
var return_records = function() {
var records = _.map(ids, function(id) {
- var c = _.find(self.cache, function(c) {return c.id === id;});
- return _.isUndefined(c) ? c : _.extend({}, c.values, {"id": id});
+ return _.extend({}, _.detect(self.cache, function(c) {return c.id === id;}).values, {"id": id});
});
if (self.debug_mode) {
if (_.include(records, undefined)) {
sign = -1;
field = field.slice(1);
}
- //m2o should be searched based on value[1] not based whole value(i.e. [id, value])
- if(_.isArray(a[field]) && a[field].length == 2 && _.isString(a[field][1])){
- return sign * compare(a[field][1], b[field][1]);
- }
return sign * compare(a[field], b[field]);
}, 0);
});
if (select_exp.val()) {
self.exports.unlink([parseInt(select_exp.val(), 10)]);
select_exp.remove();
- self.$el.find("#fields_list option").remove();
if (self.$el.find('#saved_export_list option').length <= 1) {
self.$el.find('#ExistsExportList').hide();
}
export_fields: _(fields).map(function (field) {
return [0, 0, {name: field}];
})
- }).then(function (export_list_id) {
- if (!export_list_id) {
+ }, function (export_list_id) {
+ if (!export_list_id.result) {
return;
}
- if (!self.$el.find("#saved_export_list").length || self.$el.find("#saved_export_list").is(":hidden")) {
+ self.$el.find("#saved_export_list").append(
+ new Option(value, export_list_id.result));
+ if (self.$el.find("#saved_export_list").is(":hidden")) {
self.show_exports_list();
}
- self.$el.find("#saved_export_list").append( new Option(value, export_list_id) );
});
this.on_show_save_list();
+ this.$el.find("#fields_list option").remove();
},
on_click: function(id, record) {
var self = this;
case 'selection': case 'statusbar':
// Each choice is [value, label]
if(_.isArray(value)) {
- return value[1];
+ value = value[0];
}
var result = _(descriptor.selection).detect(function (choice) {
return choice[0] === value;
}
},
'autocompleteopen': function () {
- this.$el.autocomplete('widget').css('z-index', 9999);
+ this.$el.autocomplete('widget').css('z-index', 1004);
},
},
/**
context: this.dataset.get_context(),
});
- this.alive($.when(load_view)).then(function (r) {
+ $.when(load_view).then(function (r) {
return self.search_view_loaded(r);
}).fail(function () {
self.ready.reject.apply(null, arguments);
* Sets up search view's view-wide auto-completion widget
*/
setup_global_completion: function () {
+ var self = this;
+
var autocomplete = this.$el.autocomplete({
source: this.proxy('complete_global_search'),
select: this.proxy('select_completion'),
+ search: function () { self.$el.autocomplete('close'); },
focus: function (e) { e.preventDefault(); },
html: true,
autoFocus: true,
delay: 250,
}).data('autocomplete');
- this.$el.on('input', function () {
- this.$el.autocomplete('close');
- }.bind(this));
-
// MonkeyPatch autocomplete instance
_.extend(autocomplete, {
_renderItem: function (ul, item) {
* @returns instance.web.search.Field
*/
make_field: function (item, field, parent) {
- // M2O combined with selection widget is pointless and broken in search views,
- // but has been used in the past for unsupported hacks -> ignore it
- if (field.type === "many2one" && item.attrs.widget === "selection"){
- item.attrs.widget = undefined;
- }
var obj = instance.web.search.fields.get_any( [item.attrs.widget, field.type]);
if(obj) {
return new (obj) (item, field, parent || this);
list_editable: ['list', 'form', 'data'],
};
- var initialized = [];
- /**
- * openerp.init is a broken-ass piece of shit, makes it impossible to
- * progressively add modules, using it, retarded openerp_inited flag
- * means the first tests being run get their dependencies loaded
- * (basically just base and web), and for *every other module* the tests
- * run without the dependencies being correctly loaded
- */
- function init(modules) {
- if (!initialized.length) {
- openerp.init(modules);
- initialized = openerp._modules.slice();
- return;
- }
- var to_initialize = _.difference(modules, initialized);
- for (var i = 0; i < to_initialize.length; i++) {
- var modname = to_initialize[i];
- var fct = openerp[modname];
- if (typeof fct === 'function') {
- var module = openerp[modname] = {};
- for(var k in fct) {
- if (!fct.hasOwnProperty(k)) { continue; }
- module[k] = fct[k];
- }
- fct(openerp, module)
- }
- initialized.push(modname);
- openerp._modules.push(modname);
- }
- }
-
testing.dependencies = window['oe_all_dependencies'] || [];
testing.current_module = null;
testing.templates = { };
});
};
+ var openerp_inited = false;
+
+ var db = window['oe_db_info'];
testing.section = function (name, options, body) {
if (_.isFunction(options)) {
body = options;
.push(env._oe.setup, env._oe.teardown)
.push(options.setup, options.teardown);
var opts = _.defaults({}, options, env._oe);
+ // FIXME: if this test is ignored, will still query
+ if (opts.rpc === 'rpc' && !db) {
+ QUnit.config.autostart = false;
+ db = {
+ source: null,
+ supadmin: null,
+ password: null
+ };
+ var $msg = $('<form style="margin: 0 1em 1em;">')
+ .append('<h3>A test needs to clone a database</h3>')
+ .append('<h4>Please provide the source clone information</h4>')
+ .append(' Source DB: ').append('<input name="source">').append('<br>')
+ .append(' DB Password: ').append('<input name="supadmin">').append('<br>')
+ .append('Admin Password: ').append('<input name="password">').append('<br>')
+ .append('<input type="submit" value="OK"/>')
+ .submit(function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ db.source = $msg.find('input[name=source]').val();
+ db.supadmin = $msg.find('input[name=supadmin]').val();
+ db.password = $msg.find('input[name=password]').val();
+ QUnit.start();
+ $.unblockUI();
+ });
+ $.blockUI({
+ message: $msg,
+ css: {
+ fontFamily: 'monospace',
+ textAlign: 'left',
+ whiteSpace: 'pre-wrap',
+ cursor: 'default'
+ }
+ });
+ }
QUnit.test(name, function () {
var instance = openerp;
- init(module_deps);
+ if (!openerp_inited) {
+ openerp.init(module_deps);
+ openerp_inited = true;
+ }
instance.session = new instance.web.Session();
instance.session.uid = 42;
if (_.isNumber(opts.asserts)) {
instance.session.responses[spec] = handler;
};
break;
+ case 'rpc':
+ async = true;
+ (function () {
+ // Bunch of random base36 characters
+ var dbname = 'test_' + Math.random().toString(36).slice(2);
+ // Add db setup/teardown at the start of the stack
+ case_stack = case_stack.unshift(function (instance) {
+ // FIXME hack: don't want the session to go through shitty loading process of everything
+ instance.session.session_init = testing.noop;
+ instance.session.load_modules = testing.noop;
+ instance.session.session_bind();
+ return instance.session.rpc('/web/database/duplicate', {
+ fields: [
+ {name: 'super_admin_pwd', value: db.supadmin},
+ {name: 'db_original_name', value: db.source},
+ {name: 'db_name', value: dbname}
+ ]
+ }).then(function (result) {
+ if (result.error) {
+ return $.Deferred().reject(result.error).promise();
+ }
+ return instance.session.session_authenticate(
+ dbname, 'admin', db.password, true);
+ });
+ }, function (instance) {
+ return instance.session.rpc('/web/database/drop', {
+ fields: [
+ {name: 'drop_pwd', value: db.supadmin},
+ {name: 'drop_db', value: dbname}
+ ]
+ }).then(function (result) {
+ if (result.error) {
+ return $.Deferred().reject(result.error).promise();
+ }
+ return result;
+ });
+ });
+ })();
}
// Always execute tests asynchronously
open_defaults_dialog: function () {
var self = this;
var display = function (field, value) {
- if (!value) { return value; }
if (field instanceof instance.web.form.FieldSelection) {
- return _(field.get('values')).find(function (option) {
+ return _(field.values).find(function (option) {
return option[0] === value;
})[1];
} else if (field instanceof instance.web.form.FieldMany2One) {
var def;
if (this.field.type === "many2one") {
var model = new openerp.Model(openerp.session, this.field.relation);
- def = model.call("name_search", ['', this.get("domain")], {"context": this.build_context()});
+ def = model.call("search", [this.get("domain")], {"context": this.build_context()}).then(function(record_ids) {
+ return model.call("name_get", [record_ids] , {"context": self.build_context()});
+ });
} else {
var values = _.reject(this.field.selection, function (v) { return v[0] === false && v[1] === ''; });
def = $.when(values);
// quick create
var raw_result = _(data.result).map(function(x) {return x[1];});
if (search_val.length > 0 && !_.include(raw_result, search_val) &&
- ! (self.options && (self.options.no_create || self.options.no_quick_create))) {
+ ! (self.options && self.options.no_quick_create)) {
values.push({
label: _.str.sprintf(_t('Create "<strong>%s</strong>"'),
$('<span />').text(search_val).html()),
});
}
// create...
- if (!(self.options && self.options.no_create)){
- values.push({
- label: _t("Create and Edit..."),
- action: function() {
- self._search_create_popup("form", undefined, self._create_context(search_val));
- },
- classname: 'oe_m2o_dropdown_option'
- });
- }
+ values.push({
+ label: _t("Create and Edit..."),
+ action: function() {
+ self._search_create_popup("form", undefined, self._create_context(search_val));
+ },
+ classname: 'oe_m2o_dropdown_option'
+ });
return values;
});
if (self.options.quick_create === undefined || self.options.quick_create) {
new instance.web.DataSet(this, this.field.relation, self.build_context())
.name_create(name).done(function(data) {
- if (!self.get('effective_readonly'))
- self.add_id(data[0]);
+ self.add_id(data[0]);
}).fail(function(error, event) {
event.preventDefault();
slow_create();
this.searchview.on('search_data', self, function(domains, contexts, groupbys) {
if (self.initial_ids) {
self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]),
- contexts.concat(self.context), groupbys);
+ contexts, groupbys);
self.initial_ids = undefined;
} else {
self.do_search(domains.concat([self.domain]), contexts.concat(self.context), groupbys);
.on('blurred', null, function () {self.trigger('blurred');});
this.m2o = new instance.web.form.FieldMany2One(fm, { attrs: {
- name: 'Referenced Document',
+ name: 'm2o',
modifiers: JSON.stringify({readonly: this.get('effective_readonly')}),
}});
this.m2o.on("change:value", this, this.data_changed);
if (total) {
var range_start = this.page * limit + 1;
var range_stop = range_start - 1 + limit;
- if (this.records.length) {
- range_stop = range_start - 1 + this.records.length;
- }
if (range_stop > total) {
range_stop = total;
}
_(ids).each(function (id) {
self.records.remove(self.records.get(id));
});
- if (self.records.length === 0 && self.dataset.size() > 0) {
- //Trigger previous manually to navigate to previous page,
- //If all records are deleted on current page.
- self.$pager.find('ul li:first a').trigger('click');
- } else if (self.dataset.size() == self.limit()) {
- //Reload listview to update current page with next page records
- //because pager going to be hidden if dataset.size == limit
- self.reload();
- } else {
- self.configure_pager(self.dataset);
- }
+ self.configure_pager(self.dataset);
self.compute_aggregates();
});
},
function synchronized(fn) {
var fn_mutex = new $.Mutex();
return function () {
- var obj = this;
var args = _.toArray(arguments);
- return fn_mutex.exec(function () {
- if (obj.isDestroyed()) { return $.when(); }
- return fn.apply(obj, args)
- });
+ args.unshift(this);
+ return fn_mutex.exec(fn.bind.apply(fn, args));
};
}
var DataGroup = instance.web.Class.extend({
action_views_ids : views_ids
}, self.flags, self.flags[view.view_type] || {}, view.options || {})
});
-
views_ids[view.view_type] = view.view_id;
});
if (this.flags.views_switcher === false) {
}
// If no default view defined, switch to the first one in sequence
var default_view = this.flags.default_view || this.views_src[0].view_type;
-
-
- return this.switch_mode(default_view, null, this.flags[default_view] && this.flags[default_view].options);
-
-
+ return this.switch_mode(default_view);
},
switch_mode: function(view_type, no_store, view_options) {
var self = this;
contexts: [action_context].concat(contexts || []),
group_by_seq: groupbys || []
}).done(function (results) {
- if (results.error) {
- throw new Error(
- _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s",
- JSON.stringify(results.error)));
- }
self.dataset._model = new instance.web.Model(
self.dataset.model, results.context, results.domain);
var groupby = results.group_by.length
this.dataset = dataset;
this.model_id = model_id;
if (args && args[0].error) {
- this.do_warn(_t('Uploading Error'), args[0].error);
+ this.do_warn( instance.web.qweb.render('message_error_uploading'), args[0].error);
}
if (!model_id) {
this.on_attachments_loaded([]);
"context": this.dataset.get_context(),
});
}
- return this.alive(view_loaded_def).then(function(r) {
+ return view_loaded_def.then(function(r) {
self.fields_view = r;
// add css classes that reflect the (absence of) access rights
self.$el.addClass('oe_view')
</div>
<table align="center" class="db_option_table">
<tr>
- <td><label for="restore_pwd">Master Password:</label></td>
- <td><input type="password" name="restore_pwd" class="required" autofocus="autofocus"/></td>
+ <td><label for="restore_db">File:</label></td>
+ <td><input type="file" name="db_file" class="required" autofocus="autofocus"/></td>
</tr>
<tr>
- <td><label for="restore_db">File:</label></td>
- <td><input type="file" name="db_file" class="required"/></td>
+ <td><label for="restore_pwd">Master Password:</label></td>
+ <td><input type="password" name="restore_pwd" class="required"/></td>
</tr>
<tr>
<td><label for="new_db">New database name:</label></td>
<td><input type="text" name="new_db" class="required"/></td>
</tr>
- <tr>
- <td><label for="mode">Mode:</label></td>
- <td><select name="mode" class="required">
- <option value="restore">Backup Restore</option>
- <option value="copy">Copy of an existing database</option>
- </select></td>
- </tr>
</table>
</form>
<form id="db_change_password" name="change_pwd_form" style="display: none;">
</t>
<t t-name="ViewManagerDebugViewLog">
<div class="oe_debug_view_log">
- <table class="table table-condensed table-striped">
- <tr>
- <th>ID:</th>
- <td><t t-esc="perm.id"/></td>
- </tr>
- <tr>
- <th>XML ID:</th>
- <td><t t-esc="perm.xmlid or '/'"/></td>
- </tr>
- <tr>
- <th>Creation User:</th>
- <td><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></td>
- </tr>
- <tr>
- <th>Creation Date:</th>
- <td><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></td>
- </tr>
- <tr>
- <th>Latest Modification by:</th>
- <td><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></td>
- </tr>
- <tr>
- <th>Latest Modification Date:</th>
- <td><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></td>
- </tr>
- </table>
+ <label>ID:</label>
+ <span><t t-esc="perm.id"/></span>
+
+ <label>XML ID:</label>
+ <span><t t-esc="perm.xmlid"/></span>
+
+ <label>Creation User:</label>
+ <span><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+ <label>Creation Date:</label>
+ <span><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></span>
+
+ <label>Latest Modification by:</label>
+ <span><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+ <label>Latest Modification Date:</label>
+ <span><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></span>
</div>
</t>
<t t-name="ViewPager">
-openerp.testing.section('data.dataset', {
- rpc: 'mock',
- dependencies: ['web.data'],
-}, function (test) {
- test('read_ids', {asserts: 2}, function (instance, _, mock) {
- var d = new instance.web.DataSet(null, 'foo');
- mock('foo:read', function (args) {
- var ids = args[0];
- deepEqual(ids, [3, 1, 2]);
- return [
- {id: 1, a: 'bar'},
- {id: 2, a: 'baz'},
- {id: 3, a: 'foo'}
- ];
- });
-
- return d.read_ids([3, 1, 2]).then(function (records) {
- deepEqual(
- records,
- [
- {id: 3, a: 'foo'},
- {id: 1, a: 'bar'},
- {id: 2, a: 'baz'}
- ]
- )
- });
- })
-});
-
openerp.testing.section('data.model.group_by', {
rpc: 'mock',
dependencies: ['web.data'],
--- /dev/null
+(function() {
+
+var ropenerp = window.openerp;
+
+var openerp = ropenerp.declare($, _, QWeb2);
+
+ropenerp.testing.section('jsonrpc', {},
+function (test) {
+ test('basic-jsonrpc', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ return session.rpc("/gen_session_id", {}).then(function(result) {
+ ok(result.length > 0, "Result returned by /gen_session_id");
+ });
+ });
+ test('basic-jsonprpc', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ return session.rpc("/gen_session_id", {}).then(function(result) {
+ ok(result.length > 0, "Result returned by /gen_session_id");
+ });
+ });
+ // desactivated because the phantomjs runner crash
+ /*test('basic-jsonprpc2', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ return session.rpc("/gen_session_id", {}, {force2step: true}).then(function(result) {
+ ok(result.length > 0, "Result returned by /gen_session_id");
+ });
+ });*/
+ test('session-jsonrpc', {asserts: 2}, function () {
+ var session = new openerp.Session();
+ var tmp = _.uniqueId("something");
+ return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+ ok(true, "set_session returned");
+ return session.rpc("/web/tests/get_session_value", {});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ });
+ });
+ test('session-jsonprpc', {asserts: 2}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ var tmp = _.uniqueId("something");
+ return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+ ok(true, "set_session returned");
+ return session.rpc("/web/tests/get_session_value", {});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ });
+ });
+ // desactivated because the phantomjs runner crash
+ /*test('session-jsonprpc2', {asserts: 2}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ var tmp = _.uniqueId("something");
+ return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
+ ok(true, "set_session returned");
+ return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ });
+ });*/
+ test('overridesession-jsonrpc', {asserts: 4}, function () {
+ var origin_session = new openerp.Session();
+ var origin_tmp = _.uniqueId("something");
+ var session = new openerp.Session(null, null, {override_session: true});
+ var tmp = _.uniqueId("something_else");
+ return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+ ok(true, "set_session returned");
+ return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+ }).then(function(result) {
+ ok(true, "set_session on origin returned");
+ return session.rpc("/web/tests/get_session_value", {});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ notEqual(result, origin_tmp, "Values in the different sessions should be different");
+ });
+ });
+ test('overridesession-jsonprpc', {asserts: 4}, function () {
+ var origin_session = new openerp.Session();
+ var origin_tmp = _.uniqueId("something");
+ var session = new openerp.Session(null, null, {override_session: true});
+ var tmp = _.uniqueId("something_else");
+ session.origin_server = false;
+ return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+ ok(true, "set_session returned");
+ return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+ }).then(function(result) {
+ ok(true, "set_session on origin returned");
+ return session.rpc("/web/tests/get_session_value", {});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ notEqual(result, origin_tmp, "Values in the different sessions should be different");
+ });
+ });
+ // desactivated because the phantomjs runner crash
+ /*test('overridesession-jsonprpc2', {asserts: 4}, function () {
+ var origin_session = new openerp.Session();
+ var origin_tmp = _.uniqueId("something");
+ var session = new openerp.Session(null, null, {override_session: true});
+ var tmp = _.uniqueId("something_else");
+ session.origin_server = false;
+ return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
+ ok(true, "set_session returned");
+ return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+ }).then(function(result) {
+ ok(true, "set_session on origin returned");
+ return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
+ }).then(function(result) {
+ equal(result, tmp, "Got the same value from the session");
+ notEqual(result, origin_tmp, "Values in the different sessions should be different");
+ });
+ });*/
+ test('timeout-jsonrpc', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
+ ok(false, "the request incorrectly succeeded");
+ return $.when();
+ }, function(a, e) {
+ e.preventDefault();
+ ok(true, "the request correctly failed");
+ return $.when();
+ });
+ });
+ test('timeout-jsonprpc', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
+ ok(false, "the request incorrectly succeeded");
+ return $.when();
+ }, function(a, e) {
+ e.preventDefault();
+ ok(true, "the request correctly failed");
+ return $.when();
+ });
+ });
+ // desactivated because the phantomjs runner crash
+ /*test('timeout-jsonprpc2', {asserts: 1}, function () {
+ var session = new openerp.Session();
+ session.origin_server = false;
+ return session.rpc("/gen_session_id", {}, {force2step: true, timeout: 1}).then(function() {
+ ok(false, "the request incorrectly succeeded");
+ return $.when();
+ }, function(a, e) {
+ e.preventDefault();
+ ok(true, "the request correctly failed");
+ return $.when();
+ });
+ });*/
+});
+
+var login = "admin";
+var password = "admin";
+
+ropenerp.testing.section('jsonrpc-auth', {
+ rpc: "rpc",
+},
+function (test) {
+ return;
+ test('basic-auth', {asserts: 3}, function () {
+ var db = ropenerp.session.db;
+ var session = new openerp.Session(null, null, {override_session: true});
+ equal(session.uid, undefined, "uid is expected to be undefined");
+ return session.session_authenticate(db, login, password).then(function() {
+ equal(session.uid, 1, "Admin's uid must be 1");
+ return session.rpc("/web/dataset/call_kw", {
+ model: "res.users",
+ method: "read",
+ args: [1, ["login"]],
+ kwargs: {},
+ }).then(function(result) {
+ equal(result.login, "admin", "Admin's name must be 'admin'");
+ });
+ });
+ });
+ test('share-sessions', {asserts: 6}, function () {
+ var db = ropenerp.session.db;
+ var session = new openerp.Session(null, null, {override_session: true});
+ var session2;
+ return session.session_authenticate(db, login, password).then(function() {
+ equal(session.uid, 1, "Admin's uid must be 1");
+ session2 = new openerp.Session(null, null, {session_id: session.session_id});
+ equal(session2.uid, undefined, "uid should be undefined");
+ equal(session2.override_session, true, "overwrite_session should be true");
+ console.log("session_id", session.session_id);
+ return session2.session_reload();
+ }).then(function() {
+ equal(session2.uid, session.uid);
+ equal(session2.uid, 1);
+ return session2.rpc("/web/dataset/call_kw", {
+ model: "res.users",
+ method: "read",
+ args: [1, ["login"]],
+ kwargs: {},
+ }).then(function(result) {
+ equal(result.login, "admin", "Admin's name must be 'admin'");
+ });
+ });
+ });
+ test('models', {asserts: 2}, function () {
+ var db = ropenerp.session.db;
+ var session = new openerp.Session(null, null, {override_session: true});
+ return session.session_authenticate(db, login, password).then(function() {
+ return session.model("res.users").call("search_read", {fields: ["login"], domain: [["id", "=", 1]]});
+ }).then(function(result) {
+ equal(result.length, 1, "Must have one result");
+ equal(result[0].login, "admin", "Must have admin's login");
+ });
+ });
+});
+
+})();
'timeout': self.timeout,
'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
})
- ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ ], stdout=subprocess.PIPE)
try:
while True:
phantom.terminate()
def process(self, line, result):
- try:
- args = json.loads(line)
- except ValueError: # phantomjs stderr
- if 'CoreText' not in line:
- print line
- return False
+ args = json.loads(line)
event_name = args[0]
if event_name == 'qunit.done':
self._test.failed = True
result.addFailure(
self._test, self.failure_to_str(*args[2:]))
- elif event_name == 'console':
- print args[1]
return False
-import urllib
import urlparse
from openerp import sql_db, tools
from qunitsuite.suite import QUnitSuite
class WebSuite(QUnitSuite):
- def __init__(self, module):
+ def __init__(self):
url = urlparse.urlunsplit([
'http',
'localhost:{port}'.format(port=tools.config['xmlrpc_port']),
'/web/tests',
- urllib.urlencode({
- 'mod': module,
- 'source': tools.config['db_name'],
- 'supadmin': tools.config['admin_passwd'],
- 'password': 'admin',
- }),
+ 'mod=*&source={db}&supadmin={supadmin}&password={password}'.format(
+ db=tools.config['db_name'],
+ # al: i dont understand why both are needed, db_password is the
+ # password for postgres and should not appear here of that i'm
+ # sure
+ #
+ # But runbot provides it with this wrong key so i let it here
+ # until it's fixed
+ supadmin=tools.config['db_password'] or 'admin',
+ password=tools.config['admin_passwd'] or 'admin'),
''
])
super(WebSuite, self).__init__(url, 50000)
def load_tests(loader, standard_tests, _):
- standard_tests.addTest(WebSuite('web'))
+ standard_tests.addTest(WebSuite())
return standard_tests
{% endif %}
</div>
+ <hr/>
{% if debug %}
<input type="hidden" name="debug" value=""/>
{% endif %}
-
- <noscript>
- <hr/>
- <input type="submit" value="Continue" class="btn btn-primary pull-right"/>
- </noscript>
+ <input type="submit" value="Continue" class="btn btn-primary pull-right"/>
<div class="oe_single_form_footer">
<a class="oe_login_manage_db" href="/web/database/manager{% if debug %}?debug{% endif %}">Manage Databases</a> |
<template id="web.login_layout" name="Login Layout">
<t t-call="web.layout">
- <t t-set="head">
- <link href="/web/static/src/css/base.css" rel="stylesheet"/>
- <link href="/web/static/lib/bootstrap/css/bootstrap.css" rel="stylesheet"/>
- </t>
<t t-set="body_classname" t-value="'oe_single_form'"/>
<div class="oe_single_form_container modal-content">
<div class="oe_single_form_logo">
</div>
<hr/>
<t t-raw="0"/>
-
- <div class="oe_single_form_footer" t-if="not disable_footer">
- <t t-if="not disable_database_manager">
- <a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
- <span class="oe_footer_seperator"> | </span>
- </t>
- <a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
- </div>
</div>
</t>
</template>
<template id="web.login" name="Login">
<t t-call="web.login_layout">
- <form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post" onsubmit="this.action = this.action + location.hash">
+ <t t-set="head">
+ <t t-foreach="css" t-as="css_file">
+ <link rel="stylesheet" t-att-href="css_file"/>
+ </t>
+ <t t-foreach="js" t-as="js_file">
+ <script type="text/javascript" t-att-src="js_file"></script>
+ </t>
+ <script type="text/javascript">
+ $(function() {
+ var s = new openerp.init(<t t-raw="modules"/>);
+ var login_form = new openerp.web.LoginForm($('.oe_login_form'));
+ });
+ </script>
+ </t>
+
+ <form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post">
<t t-call="web.database_select"/>
<div class="form-group field-password">
<label for="password" class="control-label">Password</label>
- <input type="password" name="password" id="password" class="form-control" required="required" t-att-autofocus="'autofocus' if login else None"/>
+ <input type="password" name="password" id="password" class="form-control" required="required"/>
</div>
<p class="alert alert-danger" t-if="error">
</div>
</form>
+ <div class="oe_single_form_footer" t-if="not disable_footer">
+ <t t-if="not disable_database_manager">
+ <a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
+ <span class="oe_footer_seperator"> | </span>
+ </t>
+ <a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
+ </div>
+
</t>
</template>
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
"PO-Revision-Date: 2014-01-30 17:05+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
"Language-Team: Bosnian <bs@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: web_calendar
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"Language: es\n"
#. module: web_calendar
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_calendar
#. openerp-web
* OpenERP web_calendar
*---------------------------------------------------------*/
-_.str.toBoolElse = function (str, elseValues, trueValues, falseValues) {
- var ret = _.str.toBool(str, trueValues, falseValues);
- if (_.isUndefined(ret)) {
- return elseValues;
- }
- return ret;
+_.str.toBoolElse = function(str, elseValues, trueValues, falseValues) {
+ var ret = _.str.toBool(str, trueValues, falseValues);
+ if (_.isUndefined(ret)) {
+ return elseValues
+ }
+ return ret
};
openerp.web_calendar = function(instance) {
var _t = instance.web._t,
- _lt = instance.web._lt,
- QWeb = instance.web.qweb;
+ _lt = instance.web._lt;
+ var QWeb = instance.web.qweb;
function get_class(name) {
return new instance.web.Registry({'tmp' : name}).get_object("tmp");
}
- function get_fc_defaultOptions() {
- shortTimeformat = Date.CultureInfo.formatPatterns.shortTime;
- return {
- weekNumberTitle: _t("W"),
- allDayText: _t("All day"),
- buttonText : {
- today: _t("Today"),
- month: _t("Month"),
- week: _t("Week"),
- day: _t("Day")
- },
- monthNames: Date.CultureInfo.monthNames,
- monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
- dayNames: Date.CultureInfo.dayNames,
- dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
- firstDay: Date.CultureInfo.firstDayOfWeek,
- weekNumbers: true,
- axisFormat : shortTimeformat.replace(/:mm/,'(:mm)'),
- timeFormat : {
- // for agendaWeek and agendaDay
- agenda: shortTimeformat + '{ - ' + shortTimeformat + '}', // 5:00 - 6:30
- // for all other views
- '': shortTimeformat.replace(/:mm/,'(:mm)') // 7pm
- },
- weekMode : 'liquid',
- aspectRatio: 1.8,
- snapMinutes: 15,
- };
- }
+ var fc_defaultOptions = {
+ monthNames: Date.CultureInfo.monthNames,
+ monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
+ dayNames: Date.CultureInfo.dayNames,
+ dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
+
+ weekNumberTitle: _t("W"),
+ allDayText: _t("all-day"),
+
+ firstDay: Date.CultureInfo.firstDayOfWeek,
+ };
function is_virtual_id(id) {
- return typeof id === "string" && id.indexOf('-') >= 0;
+ return typeof id == "string" && id.indexOf('-') >= 0;
}
function isNullOrUndef(value) {
- return _.isUndefined(value) || _.isNull(value);
+ return _.isUndefined(value) || _.isNull(value)
}
-
+
instance.web.views.add('calendar', 'instance.web_calendar.CalendarView');
instance.web_calendar.CalendarView = instance.web.View.extend({
this.range_start = null;
this.range_stop = null;
this.selected_filters = [];
+
},
set_default_options: function(options) {
this._super(options);
_.defaults(this.options, {
- confirm_on_delete: true
+ confirm_on_delete: true,
});
},
destroy: function() {
this.$calendar.fullCalendar('destroy');
- if (this.$small_calendar) {
- this.$small_calendar.datepicker('destroy');
- }
+ this.$small_calendar.datepicker('destroy');
this._super.apply(this, arguments);
},
view_loading: function (fv) {
- /* xml view calendar options */
- var attrs = fv.arch.attrs,
- self = this;
+ var self = this;
this.fields_view = fv;
this.$calendar = this.$el.find(".oe_calendar_widget");
self.do_switch_view('form');
});
+ /* xml view calendar options */
+ var attrs = fv.arch.attrs;
+
if (!attrs.date_start) {
throw new Error(_t("Calendar view has not defined 'date_start' attribute."));
}
this.date_start = attrs.date_start; // Field name of starting date field
this.date_delay = attrs.date_delay; // duration
this.date_stop = attrs.date_stop;
- this.all_day = attrs.all_day;
+ this.all_day = attrs.all_day;
+ this.attendee_people = attrs.attendee;
this.how_display_event = '';
- this.attendee_people = attrs.attendee;
-
+
if (!isNullOrUndef(attrs.quick_create_instance)) {
- self.quick_create_instance = 'instance.' + attrs.quick_create_instance;
+ self.quick_create_instance = 'instance.' + attrs.quick_create_instance;
}
-
+
//if quick_add = False, we don't allow quick_add
//if quick_add = not specified in view, we use the default quick_create_instance
//if quick_add = is NOT False and IS specified in view, we this one for quick_create_instance'
-
- this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add, true));
+
+ this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) );
if (this.quick_add_pop && !isNullOrUndef(attrs.quick_add)) {
- self.quick_create_instance = 'instance.' + attrs.quick_add;
+ self.quick_create_instance = 'instance.' + attrs.quick_add;
}
// The display format which will be used to display the event where fields are between "[" and "]"
if (!isNullOrUndef(attrs.display)) {
this.how_display_event = attrs.display; // String with [FIELD]
}
-
+
// If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter
- if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup, true)) {
- this.open_popup_action = false;
- } else {
+ if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup,true)) {
+ this.open_popup_action = false;
+ }
+ else {
this.open_popup_action = attrs.event_open_popup;
}
- // If this field is set to true, we will use the calendar_friends model as filter and not the color field.
- this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)) && (!isNullOrUndef(self.options.$sidebar));
+
+ // If this field is set to true, we will use de calendar_friends model as filter and not the color field.
+ this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts));
// If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event
// The color is the color of the attendee, so don't need to show again that it will be present
- this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee, true))) && (!isNullOrUndef(self.options.$sidebar));
-
- // if we have not sidebar, (eg: Dashboard), we don't use the filter "coworkers"
- if (isNullOrUndef(self.options.$sidebar)) {
- this.useContacts = false;
- this.colorIsAttendee = false;
- this.attendee_people = undefined;
- }
-
+ this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee,true)));
+
/*
Will be more logic to do it in futur, but see below to stay Retro-compatible
}
*/
if (isNullOrUndef(attrs.avatar_model)) {
- this.avatar_model = null;
- } else {
+ this.avatar_model = null;
+ }
+ else {
this.avatar_model = attrs.avatar_model;
}
-
+
if (isNullOrUndef(attrs.avatar_title)) {
- this.avatar_title = this.avatar_model;
- } else {
+ this.avatar_title = this.avatar_model;
+ }
+ else {
this.avatar_title = attrs.avatar_title;
}
+
this.color_field = attrs.color;
-
+
if (this.color_field && this.selected_filters.length === 0) {
var default_filter;
if ((default_filter = this.dataset.context['calendar_default_' + this.color_field])) {
this.selected_filters.push(default_filter + '');
}
}
-
this.fields = fv.fields;
for (var fld = 0; fld < fv.arch.children.length; fld++) {
this.info_fields.push(fv.arch.children[fld].attrs.name);
}
-
+
return (new instance.web.Model(this.dataset.model))
.call("check_access_rights", ["create", false])
.then(function (create_right) {
self.create_right = create_right;
- self.init_calendar().then(function() {
+ self.init_calendar().then(function() {
self.trigger('calendar_view_loaded', fv);
self.ready.resolve();
});
get_fc_init_options: function () {
//Documentation here : http://arshaw.com/fullcalendar/docs/
var self = this;
- return $.extend({}, get_fc_defaultOptions(), {
+ return $.extend({}, fc_defaultOptions, {
defaultView: (this.mode == "month")?"month":
(this.mode == "week"?"agendaWeek":
self.proxy('update_record')(event._id, data);
},
eventRender: function (event, element, view) {
- element.find('.fc-event-title').html(event.title);
+ element.find('.fc-event-title').html(event.title);
},
- eventAfterRender: function (event, element, view) {
+ eventAfterRender: function (event, element, view) {
if ((view.name !== 'month') && (((event.end-event.start)/60000)<=30)) {
//if duration is too small, we see the html code of img
var current_title = $(element.find('.fc-event-time')).text();
- var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length);
+ var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length)
element.find('.fc-event-time').html(new_title);
- }
+ }
},
eventClick: function (event) { self.open_event(event._id,event.title); },
select: function (start_date, end_date, all_day, _js_event, _view) {
end: end_date,
allDay: all_day,
});
+
self.open_quick_create(data_template);
},
+ drop: function(start_date, all_day) {
+ if (this.classList.contains("ui-dialog")) {
+ return; //don't look click event on calendar if popup hover !
+ }
+ var data_template = self.get_event_data({
+ start: start_date,
+ allDay: all_day,
+ });
+ var stored_data = $(this).data('eventDefaults');
+ data_template = $.extend({}, stored_data, data_template);
+ self.open_quick_create(data_template);
+ },
unselectAuto: false,
+ // Options
+ weekNumbers: true,
+ snapMinutes: 15,
+ timeFormat : {
+
+ // for agendaWeek and agendaDay
+ agenda: 'h:mm{ - h:mm}', // 5:00 - 6:30
+
+ // for all other views
+ '': 'h(:mm)tt' // 7pm
+ },
+ weekMode : 'liquid',
+ aspectRatio: 1.8,
});
},
context.$calendar.fullCalendar('changeView','agendaDay');
}
}
- else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)===0)) {
+ else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)==0)) {
context.$calendar.fullCalendar('changeView','agendaWeek');
}
context.$calendar.fullCalendar('gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay);
- };
+ }
},
init_calendar: function() {
var self = this;
if (!this.sidebar && this.options.$sidebar) {
- translate = get_fc_defaultOptions();
this.sidebar = new instance.web_calendar.Sidebar(this);
this.sidebar.appendTo(this.$el.find('.oe_calendar_sidebar_container'));
this.$small_calendar = self.$el.find(".oe_calendar_mini");
- this.$small_calendar.datepicker({
- onSelect: self.calendarMiniChanged(self),
- dayNamesMin : translate.dayNamesShort,
- monthNames: translate.monthNamesShort,
- firstDay: translate.firstDay,
- });
-
+ this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) });
if (this.useContacts) {
- //Get my Partner ID
-
new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first()
.done(
- function(result) {
+ function(result) {
var sidebar_items = {};
var filter_value = result.partner_id[0];
var filter_item = {
- value: filter_value,
- label: result.partner_id[1] + _lt(" [Me]"),
- color: self.get_color(filter_value),
- avatar_model: self.avatar_model,
- is_checked: true
- };
-
+ value: filter_value,
+ label: result.partner_id[1] + _lt(" [Me]"),
+ color: self.get_color(filter_value),
+ avatar_model: self.avatar_model
+ };
sidebar_items[filter_value] = filter_item ;
filter_item = {
value: -1,
- label: _lt("Everybody's calendars"),
+ label: _lt("All calendars"),
color: self.get_color(-1),
- avatar_model: self.avatar_model,
- is_checked: false
+ avatar_model: self.avatar_model
};
sidebar_items[-1] = filter_item ;
- //Get my coworkers/contacts
+
new instance.web.Model("calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) {
_.each(result, function(item) {
filter_value = item.partner_id[0];
value: filter_value,
label: item.partner_id[1],
color: self.get_color(filter_value),
- avatar_model: self.avatar_model,
- is_checked: true
+ avatar_model: self.avatar_model
};
sidebar_items[filter_value] = filter_item ;
});
-
- self.all_filters = sidebar_items;
- self.now_filter_ids = $.map(self.all_filters, function(o) { return o.value; });
- self.sidebar.filter.events_loaded(self.all_filters);
- self.sidebar.filter.set_filters();
-
+ self.allFilters = sidebar_items;
+ self.sidebar.filter.events_loaded(sidebar_items);
self.sidebar.filter.addUpdateButton();
- }).done(function () {
- self.$calendar.fullCalendar('refetchEvents');
+ }).done(function () {
+ self.$calendar.fullCalendar('refetchEvents');
});
}
- );
- }
- this.extraSideBar();
+ );
+ };
+ this.extraSideBar();
+
}
self.$calendar.fullCalendar(self.get_fc_init_options());
+
return $.when();
},
delete this.quick;
this.$calendar.fullCalendar('unselect');
});
- this.quick.replace(this.$el.find('.oe_calendar_qc_placeholder'));
+ this.quick.replace($(".oe_calendar_qc_placeholder"));
this.quick.focus();
},
event_data_transform: function(evt) {
var self = this;
- var date_delay = evt[this.date_delay] || 1.0,
+ var date_start = instance.web.auto_str_to_date(evt[this.date_start]),
+ date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null,
+ date_delay = evt[this.date_delay] || 1.0,
all_day = this.all_day ? evt[this.all_day] : false,
res_computed_text = '',
the_title = '',
- attendees = [];
+ attendees = [];
- if (!all_day) {
- date_start = instance.web.auto_str_to_date(evt[this.date_start]);
- date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null;
- }
- else {
- date_start = instance.web.auto_str_to_date(evt[this.date_start].split(' ')[0],'date');
- date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop].split(' ')[0],'date').addMinutes(-1) : null;
+ if (this.date_stop && this.fields[this.date_stop].type == 'date') {
+ date_stop.addDay(1);
}
if (this.info_fields) {
temp_ret[fieldname] = value;
}
res_computed_text = res_computed_text.replace("["+fieldname+"]",temp_ret[fieldname]);
- });
+ });
if (res_computed_text.length) {
}
else {
var res_text= [];
- _.each(temp_ret, function(val,key) { res_text.push(val); });
- the_title = res_text.join(', ');
+ _.each(temp_ret, function(val,key) { res_text.push(val)} );
+ the_title = res_text.join(', ');
}
the_title = _.escape(the_title);
var attendee_showed = 0;
var attendee_other = '';
- _.each(temp_ret[this.attendee_people],
- function (the_attendee_people) {
+ _.each(temp_ret[this.attendee_people],
+ function (the_attendee_people) {
attendees.push(the_attendee_people);
attendee_showed += 1;
- if (attendee_showed<= MAX_ATTENDEES) {
- if (self.avatar_model !== null) {
- the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head" \
- src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';
+ if (attendee_showed<= MAX_ATTENDEES) {
+ if (self.avatar_model != null) {
+ the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head" src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';
}
else {
if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) {
- tempColor = (self.all_filters[the_attendee_people] !== undefined)
- ? self.all_filters[the_attendee_people].color
- : self.all_filters[-1].color;
- the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>';
+ tempColor = (self.all_filters[the_attendee_people] != undefined)
+ ? self.all_filters[the_attendee_people].color
+ : self.all_filters[-1].color;
+
+ the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>'
}//else don't add myself
}
}
else {
attendee_other += self.all_attendees[the_attendee_people] +", ";
- }
+ }
}
);
if (attendee_other.length>2) {
- the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';
+ the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';
}
the_title = the_title_avatar + the_title;
- }
+ }
}
if (!date_stop && date_delay) {
date_stop = date_start.clone().addHours(date_delay);
}
+ if (this.fields[this.date_start].type != "date" && all_day) {
+ date_stop.addDays(-1);
+ }
var r = {
'start': date_start.toString('yyyy-MM-dd HH:mm:ss'),
'end': date_stop.toString('yyyy-MM-dd HH:mm:ss'),
- 'title': the_title,
+ 'title': the_title, //res_text.join(', '),
'allDay': (this.fields[this.date_start].type == 'date' || (this.all_day && evt[this.all_day]) || false),
'id': evt.id,
'attendees':attendees
};
- if (!self.useContacts || self.all_filters[evt[this.color_field]] !== undefined) {
+
+
+ if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) {
if (this.color_field && evt[this.color_field]) {
var color_key = evt[this.color_field];
if (typeof color_key === "object") {
color_key = color_key[0];
}
- r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);
+ r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);
}
}
else { // if form all, get color -1
+
r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color;
}
+
return r;
},
// Normalize event_end without changing fullcalendars event.
var data = {
name: event.title
- };
+ };
+
var event_end = event.end;
//Bug when we move an all_day event from week or day view, we don't have a dateend or duration...
if (event.allDay) {
// Sometimes fullcalendar doesn't give any event.end.
- if (event_end == null || _.isUndefined(event_end)) {
+ if (event_end === null || _.isUndefined(event_end)) {
event_end = new Date(event.start);
}
if (this.all_day) {
- event_end = (new Date(event_end.getTime())).addDays(1);
- date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),12);
- date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),12);
+ event_end = (new Date(event_end.getTime())).addDays(1);
+ date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate()))
+ date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate()))
}
else {
- date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7);
- date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19);
- }
+ date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7))
+ date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19))
+ }
data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]);
if (this.date_stop) {
data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]);
}
- diff_seconds = Math.round((date_stop_day.getTime() - date_start_day.getTime()) / 1000);
}
else {
+
data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]);
if (this.date_stop) {
data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]);
- }
- diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
+ }
+
}
+
if (this.all_day) {
- data[this.all_day] = event.allDay;
+ data[this.all_day] = event.allDay;
}
if (this.date_delay) {
-
+ var diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
data[this.date_delay] = diff_seconds / 3600;
}
return data;
},
-
do_search: function(domain, context, _group_by) {
var self = this;
- if (! self.all_filters) {
- self.all_filters = {}
- }
-
if (! _.isUndefined(this.event_source)) {
this.$calendar.fullCalendar('removeEventSource', this.event_source);
}
domain: self.get_range_domain(domain, start, end),
context: context,
}).done(function(events) {
-
if (self.event_source !== current_event_source) {
console.log("Consecutive ``do_search`` called. Cancelling.");
return;
}
+ // We should make sure that *2many used in title of event have their extended form [ID, NAME]...
+
+ events = $.map(events, function (e) {
+
+ if (self.attendee_people != undefined) { //If we filter on contacts...
+ if (_.intersection(self.selected_filters,e[self.attendee_people]).length || (self.selected_filters.indexOf(-1) > -1)) {
+ return e;
+ }
+ else {
+ return null;
+ }
+ }
+ else { //We adds all events
+ return e;
+ }
+ return null;
+ });
- if (!self.useContacts) { // If we use all peoples displayed in the current month as filter in sidebars
-
+ if (!self.useContacts) { // If we use all peoples as filter in sidebars
+ var now_filters = {};
var filter_value;
var filter_item;
- self.now_filter_ids = [];
-
_.each(events, function (e) {
filter_value = e[self.color_field][0];
- if (!self.all_filters[e[self.color_field][0]]) {
- filter_item = {
- value: filter_value,
- label: e[self.color_field][1],
- color: self.get_color(filter_value),
- avatar_model: self.avatar_model,
- is_checked: true
- };
- self.all_filters[e[self.color_field][0]] = filter_item;
- }
- if (! _.contains(self.now_filter_ids, filter_value)) {
- self.now_filter_ids.push(filter_value);
+ filter_item = {
+ value: filter_value,
+ label: e[self.color_field][1],
+ color: self.get_color(filter_value),
+ avatar_model: self.avatar_model
+ };
+ if (!now_filters[e[self.color_field][0]]) {
+ now_filters[e[self.color_field][0]] = filter_item;
}
});
-
- if (self.sidebar) {
- self.sidebar.filter.events_loaded();
- self.sidebar.filter.set_filters();
-
- events = $.map(events, function (e) {
- if (_.contains(self.now_filter_ids,e[self.color_field][0]) && self.all_filters[e[self.color_field][0]].is_checked) {
- return e;
- }
- return null;
- });
- }
+
+ self.allFilters = now_filters;
+ self.sidebar.filter.events_loaded(now_filters);
+
return self.perform_necessary_name_gets(events).then(callback);
}
- else { //WE USE CONTACT
- if (self.attendee_people !== undefined) {
- //if we don't filter on 'Everybody's Calendar
- if (!self.all_filters[-1] || !self.all_filters[-1].is_checked) {
- var checked_filter = $.map(self.all_filters, function(o) { if (o.is_checked) { return o.value; }});
- // If we filter on contacts... we keep only events from coworkers
- events = $.map(events, function (e) {
- if (_.intersection(checked_filter,e[self.attendee_people]).length) {
- return e;
- }
- return null;
- });
- }
- }
-
- var all_attendees = $.map(events, function (e) { return e[self.attendee_people]; });
+ else {
+ var all_attendees = [];
+
+ _.each(events, function (e) {
+ all_attendees.push(e[self.attendee_people]);
+ });
+
+ self.all_attendees = {}
+
all_attendees = _.chain(all_attendees).flatten().uniq().value();
-
- self.all_attendees = {};
- if (self.avatar_title !== null) {
- new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in", all_attendees]]).all().then(function(result) {
+
+ if (self.avatar_title != null) {
+ new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) {
_.each(result, function(item) {
self.all_attendees[item.id] = item.name;
});
- }).done(function() {
+ }).done(function() {
return self.perform_necessary_name_gets(events).then(callback);
});
- }
+ }
else {
_.each(all_attendees,function(item){
self.all_attendees[item] = '';
});
return self.perform_necessary_name_gets(events).then(callback);
+
}
+
}
+
+
});
},
eventDataTransform: function (event) {
*/
get_range_domain: function(domain, start, end) {
var format = instance.web.date_to_str;
-
- extend_domain = [[this.date_start, '>=', format(start.clone())],
- [this.date_start, '<=', format(end.clone())]];
-
- if (this.date_stop) {
- //add at start
- extend_domain.splice(0,0,'|','|','&');
- //add at end
- extend_domain.push(
- '&',
- [this.date_start, '<=', format(start.clone())],
- [this.date_stop, '>=', format(start.clone())],
- '&',
- [this.date_start, '<=', format(end.clone())],
- [this.date_stop, '>=', format(start.clone())]
- );
- //final -> (A & B) | (C & D) | (E & F) -> | | & A B & C D & E F
- }
- return new instance.web.CompoundDomain(domain, extend_domain);
+ return new instance.web.CompoundDomain(
+ domain,
+ [[this.date_start, '>=', format(start.clone())],
+ [this.date_start, '<=', format(end.clone())]]);
},
+
/**
* Updates record identified by ``id`` with values in object ``data``
*/
}
return false;
},
- open_event: function(id, title) {
+ open_event: function(id,title) {
var self = this;
- if (! this.open_popup_action) {
+ if (! this.open_popup_action) {
var index = this.dataset.get_id_index(id);
this.dataset.index = index;
this.do_switch_view('form', null, { mode: "edit" });
- }
+ }
else {
+
+ var self = this;
+
var pop = new instance.web.form.FormOpenPopup(this);
+ console.log(this.open_popup_action, +this.open_popup_action);
pop.show_element(this.dataset.model, id, this.dataset.get_context(), {
title: _.str.sprintf(_t("View: %s"),title),
view_id: +this.open_popup_action,
res_id: id,
target: 'new',
readonly:true
- });
+ });
var form_controller = pop.view_form;
form_controller.on("load_record", self, function(){
button_edit = _.str.sprintf("<button class='oe_button oe_bold editme oe_highlight'><span> %s </span></button>",_t("Edit Event"));
- pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete);
- pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit);
+ pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete)
+ pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit)
$('.delme').click(
- function() {
- $('.oe_form_button_cancel').trigger('click');
- self.remove_event(id);
+ function() {
+ $('.oe_form_button_cancel').trigger('click');
+ self.remove_event(id);
}
);
$('.editme').click(
- function() {
- $('.oe_form_button_cancel').trigger('click');
- self.dataset.index = self.dataset.get_id_index(id);
+ function() {
+ $('.oe_form_button_cancel').trigger('click');
+
+ var index = self.dataset.get_id_index(id);
+ self.dataset.index = index;
self.do_switch_view('form', null, { mode: "edit" });
+
}
);
+
+
});
- }
- return false;
+
+ }
+
+ return false;
+
},
do_show: function() {
slow_created: function () {
// refresh all view, because maybe some recurrents item
var self = this;
- if (self.sidebar) {
- // force filter refresh
- self.sidebar.filter.is_loaded = false;
- }
self.$calendar.fullCalendar('refetchEvents');
},
template: 'CalendarView.quick_create',
init: function(parent, dataset, buttons, options, data_template) {
- this._super(parent);
+ this._super(parent);
this.dataset = dataset;
this._buttons = buttons || false;
this.options = options;
get_title: function () {
var parent = this.getParent();
if (_.isUndefined(parent)) {
- return _t("Create");
+ return _t("Create")
}
var title = (_.isUndefined(parent.field_widget)) ?
(parent.string || parent.name) :
if(event.keyCode == 13){
self.$input.off('keyup', enterHandler);
if (!self.quick_add()){
- self.$input.on('keyup', enterHandler);
+ self.$input.on('keyup', enterHandler);
}
}
});
submit.click(function clickHandler() {
submit.off('click', clickHandler);
if (!self.quick_add()){
- submit.on('click', clickHandler); }
+ submit.on('click', clickHandler);
+ }
self.focus();
});
this.$el.find(".oe_calendar_quick_create_edit").click(function () {
self.slow_add();
self.focus();
- });
+ });
this.$el.find(".oe_calendar_quick_create_close").click(function (ev) {
ev.preventDefault();
self.trigger('close');
});
self.$el.on('dialogclose', self, function() {
+ console.log("dialogclose");
self.trigger('close');
});
*/
quick_add: function() {
var val = this.$input.val();
- if (/^\s*$/.test(val)) {
- return false;
+ if (/^\s*$/.test(val)) {
+ return false;
}
- return this.quick_create({'name': val}).always(function() { return true; });
+ return this.quick_create({'name': val}).always(function() { return true });
},
slow_add: function() {
return infos;
},
slow_create: function(data) {
- //if all day, we could reset time to display 00:00:00
-
var self = this;
var def = $.Deferred();
var defaults = {};
-
_.each($.extend({}, this.data_template, data), function(val, field_name) {
defaults['default_' + field_name] = val;
});
-
+
+ if (defaults['default_allday'] && (defaults['default_date_deadline'] || defaults['default_duration'])) {
+ delete defaults['default_date_deadline'];
+ delete defaults['default_duration'];
+ }
+
var pop_infos = self.get_form_popup_infos();
var pop = new instance.web.form.FormOpenPopup(this);
- var context = new instance.web.CompoundContext(this.dataset.context, defaults);
+ var context = new instance.web.CompoundContext(this.dataset.context, defaults)
pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
title: this.get_title(),
disable_multiple_selection: true,
if (this.$calendar.width() !== 0) { // visible
return this._super();
}
+
// find all parents tabs.
var def = $.Deferred();
var self = this;
});
return def;
},
+
+
});
+
}
instance.web_calendar.BufferedDataSet = instance.web.BufferedDataSet.extend({
$.async_when().done(function () {
self.calendar_view.appendTo(self.$el);
});
+
+
return loaded;
},
render_value: function() {
+ console.log("In render value");
var self = this;
this.dataset.set_ids(this.get("value"));
this.is_loaded = this.is_loaded.then(function() {
open_popup: function(type, unused) {
if (type !== "form") { return; }
- if (this.dataset.index == null) {
+ if (this.dataset.index === null) {
if (typeof this.open_popup_add === "function") {
this.open_popup_add();
}
}
}
},
-
open_popup_add: function() {
throw new Error("Not Implemented");
},
-
open_popup_edit: function() {
var id = this.dataset.ids[this.dataset.index];
var self = this;
},
alternative_form_view: this.field.views ? this.field.views.form : undefined,
- parent_view: this.view,
+ parent_view: this.view, //XXXvlab: to check ! this.view is likely undefined
child_name: this.name,
readonly: this.get("effective_readonly")
});
},
init: function(parent, view) {
this._super(parent);
- this.view = view;
- },
- set_filters: function() {
- var self = this;
- _.forEach(self.view.all_filters, function(o) {
- if (_.contains(self.view.now_filter_ids, o.value)) {
- self.$('div.oe_calendar_responsible input[value=' + o.value + ']').prop('checked',o.is_checked);
- }
- });
+ this.view = view;
},
events_loaded: function(filters) {
var self = this;
- if (filters == null) {
- filters = [];
- _.forEach(self.view.all_filters, function(o) {
- if (_.contains(self.view.now_filter_ids, o.value)) {
- filters.push(o);
- }
- });
- }
+ self.selected_filters = [];
+ self.view.all_filters = filters;
this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
+ this.filter_click(null);
},
filter_click: function(e) {
- var self = this;
- self.view.all_filters[parseInt(e.target.value)].is_checked = e.target.checked;
- self.view.$calendar.fullCalendar('refetchEvents');
+ var self = this,
+ responsibles = [];
+ self.view.selected_filters = [];
+ this.$('div.oe_calendar_responsible input:checked').each(function() {
+ responsibles.push($(this).val());
+
+ if (e==null && parseInt($(this).val())<0) {
+ $(this).prop('checked',false);
+ return;
+ }
+ self.view.selected_filters.push(parseInt($(this).val()));
+ });
+
+ if (e !== null) { //First intialize
+ self.view.$calendar.fullCalendar('refetchEvents');
+ }
+
+
},
addUpdateButton: function() {
var self=this;
this.$('div.oe_calendar_all_responsibles').append(QWeb.render('CalendarView.sidebar.button_add_contact'));
- this.$(".add_contacts_link_btn").on('click', function() {
- self.rpc("/web/action/load", {
- action_id: "calendar.action_calendar_contacts"
+ this.$(".add_contacts_link_btn").on('click', function() {
+ self.rpc("/web/action/load", {
+ action_id: "calendar.action_calendar_contacts"
}).then( function(result) { return self.do_action(result); });
});
});
};
+
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: web_diagram
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"Language: es\n"
#. module: web_diagram
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_diagram
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: web_gantt
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_gantt
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_graph
#. openerp-web
-.graph_pivot_mode {
- position:initial;
-}
-
-.graph_chart_mode {
- position:relative;
-}
-
.graph_main_content td {
font-size: 12px;
margin: 45px;
},
do_search: function (domain, context, group_by) {
- if (this.ignore_do_search) {
- this.ignore_do_search = false;
- return;
- }
var self = this,
- groupbys = this.get_groupbys_from_searchview(),
+ groupbys = this.get_groupbys_dos(),
col_group_by = groupbys.col_group_by;
if (!this.graph_widget) {
this.widget_config.row_groupby = group_by;
}
if (col_group_by.length) {
- this.widget_config.col_groupby = col_group_by;
+ this.widget_config.col_groupby = group_by;
}
this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config);
this.graph_widget.appendTo(this.$el);
searchdata = this.search_view.build_search_data();
_.each(searchdata.groupbys, function (data) {
- data = (_.isString(data)) ? py.eval(data) : data;
+ data = (_isString(data)) ? py.eval(data) : data;
result.group_by = result.group_by.concat(data.group_by);
if (data.col_group_by) {
result.col_group_by = result.col_group_by.concat(data.col_group_by);
// add groupby to the search view
register_groupby: function(row_groupby, col_groupby) {
- var query = this.search_view.query,
- groupbys = this.get_groupbys_from_searchview(),
- search_row_groupby = groupbys.group_by,
- search_col_groupby = groupbys.col_group_by,
- row_gb_changed = !_.isEqual(_.pluck(row_groupby, 'field'), search_row_groupby),
- col_gb_changed = !_.isEqual(_.pluck(col_groupby, 'field'), search_col_groupby);
+ var query = this.search_view.query;
if (!_.has(this.search_view, '_s_groupby')) { return; }
- if (!row_gb_changed && !col_gb_changed) {
- return;
- }
-
- if (row_gb_changed && col_gb_changed) {
- // when two changes to the search view will be done, the method do_search
- // will be called twice, once with the correct groupby and incorrect col_groupby,
- // and once with correct informations. This flag is necessary to prevent the
- // incorrect informations to propagate and trigger useless queries
- this.ignore_do_search = true;
- }
-
- if (row_gb_changed) {
- // add row groupbys
- var row_facet = this.make_row_groupby_facets(row_groupby),
- row_search_facet = query.findWhere({category:'GroupBy'});
+ // add row groupbys
+ var row_facet = this.make_row_groupby_facets(row_groupby),
+ row_search_facet = query.findWhere({category:'GroupBy'});
- if (row_search_facet) {
- row_search_facet.values.reset(row_facet.values);
- } else {
- if (row_groupby.length) {
- query.add(row_facet);
- }
+ if (row_search_facet) {
+ row_search_facet.values.reset(row_facet.values);
+ } else {
+ if (row_groupby.length) {
+ query.add(row_facet);
}
}
-
- if (col_gb_changed) {
- // add col groupbys
- var col_facet = this.make_col_groupby_facets(col_groupby),
- col_search_facet = query.findWhere({category:'ColGroupBy'});
-
- if (col_search_facet) {
- col_search_facet.values.reset(col_facet.values);
- } else {
- if (col_groupby.length) {
- query.add(col_facet);
- }
+ // add col groupbys
+ var col_facet = this.make_col_groupby_facets(col_groupby),
+ col_search_facet = query.findWhere({category:'ColGroupBy'});
+
+ if (col_search_facet) {
+ col_search_facet.values.reset(col_facet.values);
+ } else {
+ if (col_groupby.length) {
+ query.add(col_facet);
}
}
},
if (this.mode !== 'pivot') {
this.$('.graph_heatmap label').addClass('disabled');
- this.$('.graph_main_content').addClass('graph_chart_mode');
- } else {
- this.$('.graph_main_content').addClass('graph_pivot_mode');
}
openerp.session.rpc('/web_graph/check_xlwt').then(function (result) {
return;
}
- if (!dom_changed && col_reduced && row_reduced) {
- this.pivot.fold_with_depth(this.pivot.rows, row_gbs.length);
- this.pivot.fold_with_depth(this.pivot.cols, col_gbs.length);
- this.display_data();
- return;
- }
-
if (dom_changed || row_gb_changed || col_gb_changed) {
this.pivot.set(domain, row_gbs, col_gbs).then(this.proxy('display_data'));
}
if (mode === 'pivot') {
this.$('.graph_heatmap label').removeClass('disabled');
- this.$('.graph_main_content').removeClass('graph_chart_mode').addClass('graph_pivot_mode');
} else {
this.$('.graph_heatmap label').addClass('disabled');
- this.$('.graph_main_content').removeClass('graph_pivot_mode').addClass('graph_chart_mode');
}
this.display_data();
},
case 'swap_axis':
this.swap_axis();
break;
+ case 'expand_all':
+ this.pivot.expand_all().then(this.proxy('display_data'));
+ break;
case 'update_values':
this.pivot.update_data().then(this.proxy('display_data'));
break;
if (header.expanded) {
this.fold(header);
- return;
- }
- if (header.path.length < header.root.groupby.length) {
- this.expand(id);
- return;
- }
- if (!this.important_fields.length) {
- return;
- }
+ } else {
+ if (header.path.length < header.root.groupby.length) {
+ this.expand(id);
+ } else {
+ if (!this.important_fields.length) {
+ return;
+ }
- var fields = _.map(this.important_fields, function (field) {
- return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
- });
- if (this.dropdown) {
- this.dropdown.remove();
+ var fields = _.map(this.important_fields, function (field) {
+ return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
+ });
+ this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
+ $(event.target).after(this.dropdown);
+ this.dropdown.css({position:'absolute',
+ left:event.pageX,
+ top:event.pageY});
+ this.$('.field-selection').next('.dropdown-menu').toggle();
+ }
}
- this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
- $(event.target).after(this.dropdown);
- this.dropdown.css({position:'absolute',
- left:event.pageX,
- top:event.pageY});
- this.$('.field-selection').next('.dropdown-menu').toggle();
-
-
},
field_selection: function (event) {
<label class="btn btn-default" data-choice="swap_axis" title="Swap Axis">
<span class="fa fa-expand"></span>
</label>
+ <label class="btn btn-default" data-choice="expand_all" title="Expand All">
+ <span class="fa fa-arrows-alt"></span>
+ </label>
<label class="btn btn-default" data-choice="update_values" title="Reload Data">
<span class="fa fa-refresh"></span>
</label>
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
"PO-Revision-Date: 2014-01-30 17:06+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
"Language-Team: Bosnian <bs@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: web_kanban
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_kanban
#. openerp-web
-openerp.testing.section('basic section', function (test) {
+// niv: I desactivate these until the testing framework has been adapted to better use
+// the new way to declare JavaScript modules
+/*openerp.testing.section('basic section', function (test) {
test('my first test', function () {
ok(true, "this test has run");
});
deepEqual(dbm.db_list, ['foo', 'bar', 'baz']);
});
});
-});
+
+// test('actual RPC', {rpc: 'rpc', asserts: 4}, function (instance) {
+// var Model = new instance.web.Model('web_tests_demo.model');
+// return Model.call('create', [{name: "Bob"}])
+// .then(function (id) {
+// return Model.call('read', [[id]]);
+// }).then(function (records) {
+// strictEqual(records.length, 1);
+// var record = records[0];
+// strictEqual(record.name, "Bob");
+// strictEqual(record.thing, false);
+// // default value
+// strictEqual(record.other, 'bob');
+// });
+// });
+});*/
+++ /dev/null
-# -*- coding: utf-8 -*-
-import test_js
+++ /dev/null
-# -*- coding: utf-8 -*-
-from openerp.addons.web.tests.test_js import WebSuite
-
-def load_tests(loader, standard_tests, _):
- standard_tests.addTest(WebSuite('web_tests_demo'))
- return standard_tests
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
#. module: web_view_editor
#. openerp-web
}
evt.currentTarget.selectedIndex = 0;
}else{
- return this._super.apply(this,arguments);
+ return this._super.apply(this,arguments);
}
}
});
$.when(this.action_manager.do_action(action)).done(function() {
var viewmanager = self.action_manager.inner_widget;
var controller = viewmanager.views[viewmanager.active_view].controller;
- $(controller.groups).bind({
- 'selected': function (e, ids, records, deselected) {
+ controller.on('view_loaded', self, function(){
+ $(controller.groups).bind({
+ 'selected': function(e, ids, records) {
self.main_view_id = ids[0];
- }
+ }
+ });
});
});
},
return main_object;
},
parse_xml: function(arch, view_id) {
- //First element of att_list must be element tagname.
main_object = {
'level': 0,
'id': this.xml_element_id +=1,
- 'att_list': ["view"],
+ 'att_list': [],
'name': _.str.sprintf("<view view_id = %s>", view_id),
'child_id': []
};
var field_dataset = new instance.web.DataSetSearch(this, this.model, null, null);
parent_tr = self.get_object_by_id(parseInt($(parent_tr).attr('id').replace(/[^0-9]+/g, '')), this.one_object['main_object'], [])[0].att_list[0];
_.each([tr, parent_tr],function(element) {
- var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
+ var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
property_to_check.push(value);
});
field_dataset.call( 'fields_get', []).done(function(result) {
var fields = _.keys(result);
fields.push(" "),fields.sort();
- self.on_add_node(property_to_check, fields, self.inject_position(parent_tr,tr));
+ self.on_add_node(property_to_check, fields);
});
},
- inject_position : function(parent_tag,current_tag){
- if(parent_tag == "view")
- return ['Inside'];
- if(current_tag == "field")
- return ['After','Before'];
- return ['After','Before','Inside'];
- },
do_node_edit: function(side) {
var self = this;
var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []);
var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) {
return child.nodeType == 1;
});
- var inherited_view = _.detect(children, function(xml_child) {
+ arch.arch = _.detect(children, function(xml_child) {
var temp_obj = self.create_View_Node(xml_child),
insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list));
if (insert.length == _.uniq(check_list).length ) {return xml_child;}
});
- xml_arch = QWeb.load_xml(instance.web.xml_to_str(inherited_view));
+ xml_arch = QWeb.load_xml(arch.arch);
}
return self.do_save_xml(xml_arch.documentElement, obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
},
});
return def.promise();
},
- on_add_node: function(properties, fields, position){
+ on_add_node: function(properties, fields){
var self = this;
var render_list = [{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), 'value': 'field', 'string': 'Node Type','type': 'selection'},
{'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'},
- {'name': 'position','selection': position, 'value': false, 'string': 'Position','type': 'selection'}];
+ {'name': 'position','selection': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}];
this.add_widget = [];
this.add_node_dialog = new instance.web.Dialog(this,{
title: _t("Properties"),
//e.g.:xyz 'td' : ['field']
};
// Generic html_tag list and can be added html tag in future. It's support above _CHILDREN dict's *html_tag* by default.
-// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
+// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
var html_tag = ['div','h1','h2','h3','h4','h5','h6','td','tr'];
var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
#----------------------------------------------------------
application = openerp.service.wsgi_server.application
-openerp.service.server.load_server_wide_modules()
-
#----------------------------------------------------------
# Gunicorn
#----------------------------------------------------------
import module
import res
import report
+import test
import tests
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
'ir/ir_values_view.xml',
'ir/osv_memory_autovacuum.xml',
'ir/ir_model_report.xml',
- 'ir/ir_logging_view.xml',
'workflow/workflow_view.xml',
'module/module_view.xml',
'module/module_data.xml',
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:21+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Language: Czech\n"
#. module: base
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
-msgstr "Nabídky, zakázky, řízení dodávek a fakturace"
+msgstr "Nabídky, zakázky, řízení dopravy a fakturace"
#. module: base
#: selection:ir.sequence,implementation:0
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
-"Pomůže vám řídit projekty a úkoly jejich sledováním, generováním plánů, aj."
+"Pomůže vám spravovat projekty a úkoly jejich sledováním, generováním plánů, "
+"apod."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
-msgstr "Zaškrtněte toto pole, pokud je kontakt zaměstnancem."
+msgstr "Zaškrtněte toto pole, pokud je kontakt zaměstnanec."
#. module: base
#: help:ir.model.fields,domain:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_product_visible_discount
msgid "Prices Visible Discounts"
-msgstr "Zobrazení slevy u ceny"
+msgstr ""
#. module: base
#: field:ir.attachment,datas:0
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
"X-Poedit-SourceCharset: utf-8\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
"Language: \n"
#. module: base
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
"X-Poedit-Language: Persian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"invoices from picking, OpenERP is able to add and compute the shipping "
"line.\n"
msgstr ""
-"\n"
-"Sallii toimitustapojen lisäämisen myyntitilauksille ja keräilyyn. \n"
-"==============================================================\n"
-"\n"
-"Voit määritellä oman huolitsijan ja toimitustaulukon hinnoille. Kun laskut "
-"luodaan \n"
-"keräilyssä, OpenERP lisää lähetysrivit ja laskee nille hinnat.\n"
#. module: base
#: code:addons/base/ir/ir_filters.py:80
#. module: base
#: view:workflow.transition:0
msgid "Workflow Transition"
-msgstr "Työnkulun eteneminen"
+msgstr ""
#. module: base
#: model:res.country,name:base.gf
"* Use emails to automatically confirm and send acknowledgements for any "
"event registration\n"
msgstr ""
-"\n"
-"Tapahtumien organisointi ja hallinta.\n"
-"====================================\n"
-"\n"
-"Tapahtumamoduuli mahdollistaa tehokkaan tapahtumien organisoinnin ja niihin "
-"liittyvien \n"
-"töiden hallinnan: suunnittelun, rekisteröintien seurannan, osallistumisen "
-"jne. \n"
-"\n"
-"Pääominaisuudet\n"
-"------------\n"
-"* Hallitse tapahtumia ja rekisteröintejä\n"
-"* Käytä sähköpostia automatisoimaan vahvistuksia ja lähettämään kuittaus "
-"jokaisesta rekisteröitymisestä.\n"
#. module: base
#: selection:base.language.install,lang:0
"=============\n"
" "
msgstr ""
-"\n"
-"Tämä moduuli lisää palautevalikon ja toimii jos Palauteportaali on "
-"asennettu. \n"
-"=======================================================================\n"
-" "
#. module: base
#: model:ir.actions.act_window,help:base.action_res_partner_bank_account_form
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_project_issue
msgid "Portal Issue"
-msgstr "Portaaliongelma"
+msgstr "Porttaaliongelma"
#. module: base
#: model:ir.ui.menu,name:base.menu_tools
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_event
msgid "Portal Event"
-msgstr "Portaalitapahtuma"
+msgstr "Porttaalitapahtuma"
#. module: base
#: selection:ir.translation,state:0
#: view:ir.module.module:0
#: model:ir.ui.menu,name:base.module_mi
msgid "Apps"
-msgstr "Sovelluskauppa"
+msgstr "Sovellukset"
#. module: base
#: view:ir.ui.view_sc:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_anonymous
msgid "Anonymous portal"
-msgstr "Anonyymiportaali"
+msgstr "Yleinen porttaali"
#. module: base
#: field:base.language.export,format:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_claim
msgid "Portal Claim"
-msgstr "Palauteportaali"
+msgstr "Reklmaatioporttaali"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_pe
#. module: base
#: field:ir.actions.act_window,search_view_id:0
msgid "Search View Ref."
-msgstr "Hae näytettävä referenssi"
+msgstr "Hae näytettävä viite"
#. module: base
#: help:res.users,partner_id:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_project
msgid "Portal Project"
-msgstr "Portaaliprojekti"
+msgstr "Porttaaliprojekti"
#. module: base
#: model:res.country,name:base.cc
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_sale
msgid "Portal Sale"
-msgstr "Myyntiportaali"
+msgstr "Myyntiporttaali"
#. module: base
#: field:ir.default,ref_id:0
#. module: base
#: report:ir.module.reference:0
msgid "Introspection report on objects"
-msgstr "Moduulin tekninen opas"
+msgstr "Introspektioraportti objekteista"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_analytics
#. module: base
#: model:ir.ui.menu,name:base.menu_view_base_module_update
msgid "Update Modules List"
-msgstr "Päivitä moduulilista"
+msgstr "Päivitä lista moduuleista"
#. module: base
#: code:addons/base/module/module.py:359
#. module: base
#: model:ir.module.module,shortdesc:base.module_analytic_contract_hr_expense
msgid "Contracts Management: hr_expense link"
-msgstr "Sopimushallinat: hr_expense link"
+msgstr "Sopimushallint: hr_expense link"
#. module: base
#: view:ir.attachment:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_stock
msgid "Portal Stock"
-msgstr "Portaalivarasto"
+msgstr "Porttaalivarasto"
#. module: base
#: field:workflow.activity,kind:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_analytic_analysis
msgid "Contracts Management"
-msgstr "Sopimushallinta"
+msgstr "Sopimustenhallinta"
#. module: base
#: selection:base.language.install,lang:0
#: model:ir.module.category,name:base.module_category_portal
#: model:ir.module.module,shortdesc:base.module_portal
msgid "Portal"
-msgstr "Portaali"
+msgstr "Porttaali"
#. module: base
#: selection:ir.translation,state:0
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_hr_employees
msgid "Portal HR employees"
-msgstr "Henkilöstöhallinnon työntekijäportaali"
+msgstr "Henkilöstöhallinnon työntekijäporttaali"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: report:ir.module.reference:0
msgid "Reference Guide"
-msgstr "Tekninen opas"
+msgstr "Referenssiopaste"
#. module: base
#: model:ir.model,name:base.model_res_partner
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_crm
msgid "Portal CRM"
-msgstr "CRM-portaali"
+msgstr "CRM-porttaali"
#. module: base
#: model:ir.ui.menu,name:base.next_id_4
#. module: base
#: model:ir.ui.menu,name:base.menu_aftersale
msgid "After-Sale Services"
-msgstr "Asiakaspalvelut"
+msgstr "Jälkimarkkinapalvelut"
#. module: base
#: field:base.language.import,code:0
#: model:ir.actions.act_window,name:base.open_module_tree
#: model:ir.ui.menu,name:base.menu_module_tree
msgid "Installed Modules"
-msgstr "Asenna moduulit"
+msgstr "Asennetut moduulit"
#. module: base
#: code:addons/base/res/res_users.py:170
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
#. module: base
#: model:res.country,name:base.sh
msgid "Saint Helena"
-msgstr "Sainte Hélène"
+msgstr ""
#. module: base
#: view:ir.actions.report.xml:0
#. module: base
#: selection:ir.property,type:0
msgid "DateTime"
-msgstr "Date et heure"
+msgstr ""
#. module: base
#: code:addons/fields.py:652
#. module: base
#: selection:base.language.install,lang:0
msgid "Hungarian / Magyar"
-msgstr "Hongrois / Magyar"
+msgstr ""
#. module: base
#: selection:base.language.install,lang:0
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
-"Vous aide à gérer vos projets et tâches, en assurant leur suivi, en générant "
-"des planifications, etc."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
#. module: base
#: model:res.country,name:base.sz
msgid "Swaziland"
-msgstr "Swaziland"
+msgstr ""
#. module: base
#: code:addons/orm.py:4485
#. module: base
#: model:ir.module.category,name:base.module_category_customer_relationship_management
msgid "Customer Relationship Management"
-msgstr "Gestion de la relation client (CRM)"
+msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_delivery
#. module: base
#: field:res.partner,credit_limit:0
msgid "Credit Limit"
-msgstr "Limite de crédit"
+msgstr ""
#. module: base
#: field:ir.model.constraint,date_update:0
#: field:ir.model.data,date_update:0
#: field:ir.model.relation,date_update:0
msgid "Update Date"
-msgstr "Mettre à jour la date"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_base_action_rule
#: view:ir.attachment:0
#: field:ir.attachment,create_uid:0
msgid "Owner"
-msgstr "Propriétaire"
+msgstr ""
#. module: base
#: view:ir.actions.act_window:0
msgid "Source Object"
-msgstr "Objet source"
+msgstr ""
#. module: base
#: model:res.partner.bank.type,format_layout:base.bank_normal
#: field:ir.model.access,group_id:0
#: view:res.groups:0
msgid "Group"
-msgstr "Groupe"
+msgstr ""
#. module: base
#: constraint:res.lang:0
"Invalid date/time format directive specified. Please refer to the list of "
"allowed directives, displayed when you edit a language."
msgstr ""
-"Vous avez spécifié une directive de format date/temps non valide. Veuillez "
-"vous référer à la liste des directives autorisées, qui s'affiche lorsque "
-"vous modifiez une langue."
#. module: base
#: code:addons/orm.py:4153
"* Use emails to automatically confirm and send acknowledgements for any "
"event registration\n"
msgstr ""
-"\n"
-"Gestion et organisation d'événements\n"
-"====================================\n"
-"\n"
-"Le module 'Événement' vous permet d'organiser efficacement des événements et "
-"toutes les tâches liées : planification, suivi des inscriptions, des "
-"présences, etc.\n"
-"\n"
-"Fonctionnalités clés\n"
-"--------------------\n"
-"* Gestion des événements et des inscriptions\n"
-"* Utilisation d'e-mails pour automatiquement confirmer et envoyer des "
-"accusés de réception pour chaque inscription à un événement\n"
#. module: base
#: selection:base.language.install,lang:0
"If you check this, then the second time the user prints with same attachment "
"name, it returns the previous report."
msgstr ""
-"Si vous cochez ceci, alors la seconde fois que l'utilisateur imprimera avec "
-"le même nom de pièce jointe, cela retournera le rapport stocké"
#. module: base
#: model:ir.module.module,description:base.module_mrp_byproduct
#. module: base
#: model:ir.module.module,shortdesc:base.module_hr_timesheet_invoice
msgid "Invoice on Timesheets"
-msgstr "Facture sur les feuilles de temps"
+msgstr ""
#. module: base
#: view:base.module.upgrade:0
#. module: base
#: field:res.country,name:0
msgid "Country Name"
-msgstr "Nom du pays"
+msgstr ""
#. module: base
#: model:res.country,name:base.co
msgid "Colombia"
-msgstr "Colombie"
+msgstr ""
#. module: base
#: model:res.partner.title,name:base.res_partner_title_mister
#. module: base
#: view:res.partner:0
msgid "Sales & Purchases"
-msgstr "Achats et ventes"
+msgstr ""
#. module: base
#: view:ir.translation:0
"module named account_voucher.\n"
" "
msgstr ""
-"\n"
-"Comptabilité et gestion financière\n"
-"==================================\n"
-"\n"
-"Le module de comptabilité et de finance couvre :\n"
-"------------------------------------------------\n"
-" * Comptabilité générale\n"
-" * Comptabilité de coût / comptabilité analytique\n"
-" * Comptabilité de tiers\n"
-" * Gestion des taxes\n"
-" * Budgets\n"
-" * Factures clients et fournisseurs\n"
-" * Relevés bancaires\n"
-" * Réconciliations par partenaire\n"
-"\n"
-"Il créé également un tableau de bord pour les comptables qui inclut :\n"
-"---------------------------------------------------------------------\n"
-" * Une liste des factures clients à approuver\n"
-" * L'analyse de la société\n"
-" * Un graphe de la trésorerie\n"
-"\n"
-"Les processus tels que le maintien de la comptabilité générale se fait par "
-"le biais des revues financières définies (les lignes d'écriture à regrouper "
-"le sont à travers un journal)\n"
-"pour un exercice donné et pour la préparation des reçus il ya un module "
-"nommé account_voucher.\n"
-" "
#. module: base
#: view:ir.model:0
#. module: base
#: model:res.country,name:base.jo
msgid "Jordan"
-msgstr "Jordanie"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_hr
#. module: base
#: sql_constraint:res.company:0
msgid "The company name must be unique !"
-msgstr "Le nom de la société doit être unique !"
+msgstr ""
#. module: base
#: model:ir.ui.menu,name:base.menu_base_action_rule_admin
"invoice, then `object.invoice_address_id.mobile` is the field which gives "
"the correct mobile number"
msgstr ""
-"Fournit les champs qui seront utilisés pour récupérer le numéro du "
-"cellulaire. Exemple: vous sélectionnez une facture, alors, "
-"`object.invoice_address_id.mobile` est le champ qui représente le numéro du "
-"cellulaire correct."
#. module: base
#: view:ir.mail_server:0
#: field:base.language.export,name:0
#: field:ir.attachment,datas_fname:0
msgid "File Name"
-msgstr "Nom du fichier"
+msgstr ""
#. module: base
#: model:res.country,name:base.rs
"also possible in order to automatically create a meeting when a holiday "
"request is accepted by setting up a type of meeting in Leave Type.\n"
msgstr ""
-"\n"
-"Gère les absences et les demandes de congés\n"
-"===========================================\n"
-"\n"
-"Cette application contrôle la programmation des congés de votre société. Il "
-"permet aux employés de faire des demandes de congés. Ensuite, les managers "
-"peuvent examiner les demandes et les approuver ou les rejeter. De cette "
-"façon, vous pouvez contrôler la planification de l'ensemble des congés de "
-"votre entreprise ou de votre département.\n"
-"\n"
-"Vous pouvez configurer plusieurs sortes d'absences (maladie, congés payés, "
-"congés sans soldes…) et allouer rapidement ces absences à un employé ou un "
-"département en utilisant les demandes de congés. Un employé peut aussi faire "
-"une demande de congés pour plus de jours en ajoutant une allocation. Cela va "
-"augmenter le total des jours disponibles pour ce type de congés (si la "
-"demande est acceptée).\n"
-"\n"
-"Vous pouvez suivre les absences de différentes façons grâce aux rapports "
-"suivants : \n"
-"\n"
-"* Résumé des absences\n"
-"* Absences par département\n"
-"* Analyse des absences\n"
-"\n"
-"Une synchronisation avec les agendas internes (Réunions du module CRM) est "
-"aussi possible dans le but de créer automatiquement une réunion quand une "
-"demande de congés est accepté en ajoutant une type de réunion Absence.\n"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: model:ir.ui.menu,name:base.menu_crm_config_opportunity
msgid "Opportunities"
-msgstr "Opportunités"
+msgstr ""
#. module: base
#: model:ir.model,name:base.model_base_language_export
#. module: base
#: model:res.country,name:base.pg
msgid "Papua New Guinea"
-msgstr "Papouasie-Nouvelle-Guinée"
+msgstr ""
#. module: base
#: help:ir.actions.report.xml,report_type:0
#. module: base
#: model:res.country,name:base.zw
msgid "Zimbabwe"
-msgstr "Zimbabwe"
+msgstr ""
#. module: base
#: help:ir.model.constraint,type:0
#. module: base
#: model:res.country,name:base.es
msgid "Spain"
-msgstr "Espagne"
+msgstr ""
#. module: base
#: help:ir.actions.act_window,domain:0
#. module: base
#: field:res.partner,mobile:0
msgid "Mobile"
-msgstr "Cellulaire"
+msgstr ""
#. module: base
#: model:res.country,name:base.om
msgid "Oman"
-msgstr "Oman"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_mrp
msgid "MRP"
-msgstr "MRP - PBM"
+msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_hr_attendance
#: model:ir.actions.act_window,name:base.act_menu_create
#: view:wizard.ir.model.menu.create:0
msgid "Create Menu"
-msgstr "Créer un menu"
+msgstr ""
#. module: base
#: model:res.country,name:base.in
msgid "India"
-msgstr "Inde"
+msgstr ""
#. module: base
#: model:ir.actions.act_window,name:base.res_request_link-act
#. module: base
#: model:ir.module.module,shortdesc:base.module_fleet
msgid "Fleet Management"
-msgstr "Gestion de flotte"
+msgstr ""
#. module: base
#: help:ir.server.object.lines,value:0
"* Planned Revenue by Stage and User (graph)\n"
"* Opportunities by Stage (graph)\n"
msgstr ""
-"\n"
-"Le module OpenERP de gestion de la relation client (CRM)\n"
-"=============================================\n"
-"\n"
-"Cette application permet aux utilisateurs de gérer efficacement et "
-"intelligemment leurs pistes, opportunités, réunions et appels "
-"téléphoniques.\n"
-"\n"
-"Elle gère les tâches clés comme la communication, l'identification, les "
-"assignations, les résolutions et les notifications.\n"
-"\n"
-"OpenERP assure que toutes les demandes sont suivis par les utilisateurs, les "
-"clients et les fournisseurs. Il permet d'envoyer automatiquement des "
-"rappels, d'escalader des requêtes, de lancer des actions spécifiques et de "
-"nombreuses autres selon les règles de l'entreprise.\n"
-"\n"
-"Le grand avantage de ce système est que les utilisateurs n'ont rien à faire "
-"de spécial. Le module CRM dispose d'une passerelle de courriel permettant de "
-"synchroniser les courriels reçus et OpenERP. De cette façon, les "
-"utilisateurs peuvent simplement envoyer des courriels au système de suivi "
-"des demandes.\n"
-"\n"
-"OpenERP s'occupera de remercier les utilisateurs de leur message, de diriger "
-"cette demande à l'équipe appropriée et de s'assurer que toute les "
-"communications futures seront rangées à la bonne place.\n"
-"\n"
-"\n"
-"Le tableau bord de cette application inclus:\n"
-"* les revenus prévus par étape de vente et par utilisateur (graphique);\n"
-"* les opportunités par étape de vente (graphique).\n"
#. module: base
#: selection:base.language.export,format:0
#: selection:ir.actions.server,state:0
#: selection:workflow.activity,kind:0
msgid "Dummy"
-msgstr "Factice"
+msgstr ""
#. module: base
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
-msgstr "XML invalide pour l'architecture de la vue"
+msgstr ""
#. module: base
#: model:res.country,name:base.ky
msgid "Cayman Islands"
-msgstr "Îles Caïmans"
+msgstr ""
#. module: base
#: view:ir.rule:0
#. module: base
#: selection:ir.property,type:0
msgid "Char"
-msgstr "Caractère"
+msgstr ""
#. module: base
#: field:ir.module.category,visible:0
"decimal number [00,53]. All days in a new year preceding the first Monday "
"are considered to be in week 0."
msgstr ""
-"%W - Numéro de semaine dans l'année (lundi est le premier jour de la "
-"semaine) en nombre décimal [00,53]. Tous les jours de la nouvelle année "
-"précédant le premier lundi sont considérés faisant partie de la semaine 0."
#. module: base
#: code:addons/base/module/wizard/base_language_install.py:53
#. module: base
#: field:ir.actions.act_url,url:0
msgid "Action URL"
-msgstr "URL de l'action"
+msgstr ""
#. module: base
#: field:base.module.import,module_name:0
#: field:ir.module.module,shortdesc:0
msgid "Module Name"
-msgstr "Nom du module"
+msgstr ""
#. module: base
#: model:res.country,name:base.mh
#: view:ir.ui.view:0
#: selection:ir.ui.view,type:0
msgid "Search"
-msgstr "Recherche"
+msgstr ""
#. module: base
#: code:addons/osv.py:154
#: code:addons/base/res/res_users.py:131
#, python-format
msgid "Operation Canceled"
-msgstr "Opération annulée"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_document
msgid "Document Management System"
-msgstr "Système de gestion des documents"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_crm_claim
#: model:ir.module.category,name:base.module_category_purchase_management
#: model:ir.ui.menu,name:base.menu_purchase_root
msgid "Purchases"
-msgstr "Achats"
+msgstr ""
#. module: base
#: model:res.country,name:base.md
#. module: base
#: view:ir.module.module:0
msgid "Features"
-msgstr "Fonctionnalités"
+msgstr ""
#. module: base
#: view:ir.attachment:0
msgid "Data"
-msgstr "Données"
+msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_portal_claim
#: model:ir.module.category,name:base.module_category_social_network
#: model:ir.module.module,shortdesc:base.module_mail
msgid "Social Network"
-msgstr "Réseau social"
+msgstr ""
#. module: base
#: view:res.lang:0
#. module: base
#: model:res.country,name:base.ao
msgid "Angola"
-msgstr "Angola"
+msgstr ""
#. module: base
#: model:res.country,name:base.tf
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
"Language: hr\n"
#. module: base
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"revenue\n"
"reports."
msgstr ""
-"\n"
-"Bentuk tagihan anda dari entri Expenses, Timesheet.\n"
-"========================================================\n"
-"\n"
-"Modul untuk menerbitkan tagihan berbasis biaya (sdm, biaya, dsb).\n"
-"\n"
-"Anda dapat mendefinisikan daftar harga pada akun analitik, membuat laporan "
-"anggaran \n"
-"penghasilan."
#. module: base
#: code:addons/base/ir/ir_sequence.py:134
"\n"
" "
msgstr ""
-"\n"
-"Lokalisasi skema akunting dan pajak Chili.\n"
-"==============================================\n"
-"Plan contable chileno e impuestos de acuerdo a disposiciones vigentes\n"
-"\n"
-" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale
"invoices from picking, OpenERP is able to add and compute the shipping "
"line.\n"
msgstr ""
-"\n"
-"Mengizinkan anda untuk menambahkan metode deliveri pada order penjualan dan "
-"pengambilan.\n"
-"==============================================================\n"
-"\n"
-"Anda dapat menentukan carrier sendiri dan metode antar untuk harga tersebut. "
-"Saat membuat\n"
-"tagihan dari pengantaran, OpenERP dapat menambah dan menghitung biaya "
-"pengiriman.\n"
#. module: base
#: code:addons/base/ir/ir_filters.py:80
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
#: field:ir.model.data,date_update:0
#: field:ir.model.relation,date_update:0
msgid "Update Date"
-msgstr "更新日"
+msgstr "日付の更新"
#. module: base
#: model:ir.module.module,shortdesc:base.module_base_action_rule
#. module: base
#: model:ir.module.module,summary:base.module_hr_evaluation
msgid "Periodical Evaluations, Appraisals, Surveys"
-msgstr "定期評価、査定、調査"
+msgstr ""
#. module: base
#: model:ir.actions.act_window,name:base.ir_property_form
#. module: base
#: view:ir.sequence.type:0
msgid "Sequence Type"
-msgstr "付番タイプ"
+msgstr "順序タイプ"
#. module: base
#: view:base.language.export:0
#. module: base
#: help:ir.sequence,suffix:0
msgid "Suffix value of the record for the sequence"
-msgstr "この付番定義でレコードに適用するサフィックス値"
+msgstr "順序のためのレコードのサフィックス値"
#. module: base
#: help:ir.mail_server,smtp_user:0
#. module: base
#: model:ir.module.module,summary:base.module_mrp
msgid "Manufacturing Orders, Bill of Materials, Routing"
-msgstr "製造オーダ、部品表、工順"
+msgstr ""
#. module: base
#: field:ir.attachment,name:0
#. module: base
#: field:ir.model.data,date_init:0
msgid "Init Date"
-msgstr "作成日"
+msgstr "整数データ"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: help:ir.sequence,number_next:0
msgid "Next number of this sequence"
-msgstr "この付番定義の次の番号"
+msgstr "この順序の次の番号"
#. module: base
#: view:res.partner:0
#. module: base
#: model:ir.module.module,summary:base.module_account_accountant
msgid "Financial and Analytic Accounting"
-msgstr "財務会計、分析会計"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_project
#. module: base
#: model:ir.module.module,summary:base.module_hr_recruitment
msgid "Jobs, Recruitment, Applications, Job Interviews"
-msgstr "仕事、求人、応募、面接"
+msgstr ""
#. module: base
#: code:addons/base/module/module.py:539
#. module: base
#: model:ir.module.module,summary:base.module_note
msgid "Sticky notes, Collaborative, Memos"
-msgstr "付箋、コラボレーション、メモ"
+msgstr ""
#. module: base
#: model:ir.module.module,shortdesc:base.module_hr_attendance
#. module: base
#: model:ir.module.module,summary:base.module_hr_holidays
msgid "Holidays, Allocation and Leave Requests"
-msgstr "休暇割当、申請・承認"
+msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_web_hello
#: model:ir.actions.act_window,name:base.ir_sequence_type
#: model:ir.ui.menu,name:base.menu_ir_sequence_type
msgid "Sequence Codes"
-msgstr "付番コード"
+msgstr "順序コード"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: model:ir.ui.menu,name:base.next_id_5
msgid "Sequences & Identifiers"
-msgstr "付番定義とID"
+msgstr "順序と識別子"
#. module: base
#: model:ir.module.module,description:base.module_l10n_th
#. module: base
#: view:ir.sequence.type:0
msgid "Sequences Type"
-msgstr "付番タイプ"
+msgstr "順序タイプ"
#. module: base
#: view:res.partner:0
#: view:ir.sequence:0
#: model:ir.ui.menu,name:base.menu_ir_sequence_form
msgid "Sequences"
-msgstr "付番"
+msgstr "順序"
#. module: base
#: help:res.lang,code:0
#: field:multi_company.default,sequence:0
#: field:res.partner.bank,sequence:0
msgid "Sequence"
-msgstr "付番"
+msgstr "順序"
#. module: base
#: model:res.country,name:base.tn
msgid ""
"External Key/Identifier that can be used for data integration with third-"
"party systems"
-msgstr "サードパーティシステムとのデータ統合のために利用する外部キー / ID"
+msgstr "サードパーティのシステムとのデータ統合のために利用する外部キー / 識別子"
#. module: base
#: field:ir.actions.act_window,view_id:0
#. module: base
#: model:ir.ui.menu,name:base.next_id_4
msgid "Low Level Objects"
-msgstr "低レベルオブジェクト"
+msgstr "低レベルのオブジェクト"
#. module: base
#: help:ir.values,model:0
#: view:ir.model.data:0
#: model:ir.ui.menu,name:base.ir_model_data_menu
msgid "External Identifiers"
-msgstr "外部ID"
+msgstr "外部識別子"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: model:ir.module.module,summary:base.module_stock
msgid "Inventory, Logistic, Storage"
-msgstr "在庫、経路、保管場所"
+msgstr ""
#. module: base
#: view:ir.actions.act_window:0
#: view:ir.model.data:0
#: field:ir.model.data,name:0
msgid "External Identifier"
-msgstr "外部ID"
+msgstr "外部識別子"
#. module: base
#: model:ir.module.module,description:base.module_audittrail
"Two sequence object implementations are offered: Standard and 'No gap'. The "
"later is slower than the former but forbids any gap in the sequence (while "
"they are possible in the former)."
-msgstr "「標準」と「ギャップなし」の2種類の付番定義が可能です。後者の場合、付番ごとにギャップを設けることができません。"
+msgstr ""
+"2つのシーケンスオブジェクトの実装が提供されます:標準と\"ギャップなし\"です。後者は前者よりも遅いですが、どんな順序のギャップを禁じます(前者は可能で"
+"す)。"
#. module: base
#: model:res.country,name:base.gn
#: help:ir.values,res_id:0
msgid ""
"Database identifier of the record to which this applies. 0 = for all records"
-msgstr ""
+msgstr "これを適用するためのレコードのデータベース識別子。0 = 全てのレコードのため"
#. module: base
#: field:ir.model.fields,relation:0
#. module: base
#: model:ir.module.module,summary:base.module_purchase
msgid "Purchase Orders, Receptions, Supplier Invoices"
-msgstr "発注、入荷、仕入先請求"
+msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_hr_payroll
#. module: base
#: field:ir.model.data,noupdate:0
msgid "Non Updatable"
-msgstr "更新不可"
+msgstr "更新可能でない"
#. module: base
#: selection:base.language.install,lang:0
#. module: base
#: help:ir.sequence,prefix:0
msgid "Prefix value of the record for the sequence"
-msgstr "この付番定義でレコードに適用するプレフィックス値"
+msgstr "順序のためのレコードのプレフィックス値"
#. module: base
#: model:res.country,name:base.sc
#. module: base
#: field:ir.model.data,complete_name:0
msgid "Complete ID"
-msgstr "完全ID"
+msgstr "完了ID"
#. module: base
#: model:ir.module.module,description:base.module_stock
#. module: base
#: help:ir.sequence,number_increment:0
msgid "The next number of the sequence will be incremented by this number"
-msgstr "付番毎にこの数値分だけ番号が増加します。"
+msgstr "順序の次の番号はこの数値だけ増加します。"
#. module: base
#: selection:workflow.activity,kind:0
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
#. module: base
#: selection:res.currency,position:0
msgid "Before Amount"
-msgstr "Voor bedrag"
+msgstr "Voormalig bedrag"
#. module: base
#: field:res.request,act_from:0
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
import ir_fields
import ir_qweb
import ir_http
-import ir_logging
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
_sequence = 'ir_actions_id_seq'
_order = 'name'
_columns = {
- 'type': fields.char('Action Type', size=32, required=True),
'name': fields.char('Name', size=64, required=True, translate=True),
-
- 'model': fields.char('Model', required=True),
- 'report_type': fields.selection([('qweb-pdf', 'PDF'),
- ('qweb-html', 'HTML'),
- ('other', 'Other'),
- ('pdf', 'RML pdf (deprecated)'),
- ('sxw', 'RML sxw (deprecated)'),
- ('webkit', 'Webkit (deprecated)'),
- ], 'Report Type', required=True, help="PDF will use wkhtmltopdf to render html to pdf, HTML will directly show html, Other will force download the controller output keeping the MIME type."),
- 'report_name': fields.char('Controller Name', required=True, help="URL of the report will be /report/<controller name>/<ids>, the default controller also use this field to get the name of the qweb ir.ui.view to render. For RML reports, this is the LocalService name."),
+ 'model': fields.char('Object', size=64, required=True),
+ 'type': fields.char('Action Type', size=32, required=True),
+ 'report_name': fields.char('Service Name', size=64, required=True),
+ 'usage': fields.char('Action Usage', size=32),
+ 'report_type': fields.char('Report Type', size=32, required=True, help="Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..."),
'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
-
- # options
'multi': fields.boolean('On Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view."),
- 'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.'),
'attachment': fields.char('Save as Attachment Prefix', size=128, help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'),
+ 'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.'),
+ 'auto': fields.boolean('Custom Python Parser'),
- # Deprecated rml stuff
- 'usage': fields.char('Action Usage', size=32),
'header': fields.boolean('Add RML Header', help="Add or not the corporate RML header"),
- 'parser': fields.char('Parser Class'),
- 'auto': fields.boolean('Custom Python Parser'),
- 'report_xsl': fields.char('XSL Path'),
- 'report_xml': fields.char('XML Path'),
+ 'report_xsl': fields.char('XSL Path', size=256),
+ 'report_xml': fields.char('XML Path', size=256, help=''),
- 'report_rml': fields.char('Main Report File Path', help="The path to the main report file (depending on Report Type) or NULL if the content is in another data field"),
- 'report_file': fields.related('report_rml', type="char", required=False, readonly=False, string='Report File', help="The path to the main report file (depending on Report Type) or NULL if the content is in another field", store=True),
+ # Pending deprecation... to be replaced by report_file as this object will become the default report object (not so specific to RML anymore)
+ 'report_rml': fields.char('Main Report File Path', size=256, help="The path to the main report file (depending on Report Type) or NULL if the content is in another data field"),
+ # temporary related field as report_rml is pending deprecation - this field will replace report_rml after v6.0
+ 'report_file': fields.related('report_rml', type="char", size=256, required=False, readonly=False, string='Report File', help="The path to the main report file (depending on Report Type) or NULL if the content is in another field", store=True),
'report_sxw': fields.function(_report_sxw, type='char', string='SXW Path'),
'report_sxw_content_data': fields.binary('SXW Content'),
'report_rml_content_data': fields.binary('RML Content'),
'report_sxw_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='SXW Content',),
'report_rml_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='RML Content'),
+
+ 'parser': fields.char('Parser Class'),
}
_defaults = {
'type': 'ir.actions.report.xml',
<group>
<group>
<field name="name"/>
- <field name="model"/>
- <field name="report_type"/>
<field name="report_name"/>
+ <field name="model"/>
</group>
<group>
- <field name="multi"/>
- <field name="attachment_use"/>
- <field name="attachment"/>
+ <field name="usage"/>
+ <field name="report_type"/>
+ <field name="report_file"/>
</group>
</group>
<notebook>
- <page string="Security">
- <field name="groups_id"/>
- </page>
- <page string="RML Configuration" attrs="{'invisible':[('report_type','not in',['pdf','sxw'])]}">
+ <page string="Other Configuration">
<group>
<group string="RML Report">
<field name="header"/>
- <field name="report_file"/>
- <field name="auto"/>
- <field name="parser"/>
- <field name="usage"/>
</group>
<group string="XML Report">
<field name="report_xsl"/>
<field name="report_xml"/>
</group>
+ <group string="Attachments">
+ <field name="attachment"/>
+ <field name="attachment_use"/>
+ </group>
+ <group string="Miscellaneous">
+ <field name="multi"/>
+ <field name="auto"/>
+ <field name="parser"/>
+ </group>
</group>
</page>
+ <page string="Security">
+ <field name="groups_id"/>
+ </page>
</notebook>
</form>
</field>
filter_domain="['|', '|', '|', '|', ('name','ilike',self), ('model','ilike',self), ('type','ilike',self), ('report_name','ilike',self), ('report_type','ilike',self)]"
string="Report"/>
<group expand="0" string="Group By" colspan="4">
- <filter string="Report Type" domain="[]" context="{'group_by':'report_type'}"/>
- <filter string="Report Model" domain="[]" context="{'group_by':'model'}"/>
+ <filter string="Report Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'report_type'}"/>
</group>
</search>
</field>
data[attachment.id] = False
return data
- def _storage(self, cr, uid, context=None):
- return self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'ir_attachment.location', 'file')
-
- @tools.ormcache()
- def _filestore(self, cr, uid, context=None):
- return os.path.join(tools.config['data_dir'], 'filestore', cr.dbname)
-
# 'data' field implementation
def _full_path(self, cr, uid, location, path):
- # sanitize ath
- path = re.sub('[.]', '', path)
- path = path.strip('/\\')
- return os.path.join(self._filestore(cr, uid), path)
-
- def _get_path(self, cr, uid, location, bin_data):
- sha = hashlib.sha1(bin_data).hexdigest()
+ # location = 'file:filestore'
+ assert location.startswith('file:'), "Unhandled filestore location %s" % location
+ location = location[5:]
- # retro compatibility
- fname = sha[:3] + '/' + sha
- full_path = self._full_path(cr, uid, location, fname)
- if os.path.isfile(full_path):
- return fname, full_path # keep existing path
+ # sanitize location name and path
+ location = re.sub('[.]','',location)
+ location = location.strip('/\\')
- # scatter files across 256 dirs
- # we use '/' in the db (even on windows)
- fname = sha[:2] + '/' + sha
- full_path = self._full_path(cr, uid, location, fname)
- dirname = os.path.dirname(full_path)
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- return fname, full_path
+ path = re.sub('[.]','',path)
+ path = path.strip('/\\')
+ return os.path.join(tools.config['root_path'], location, cr.dbname, path)
def _file_read(self, cr, uid, location, fname, bin_size=False):
full_path = self._full_path(cr, uid, location, fname)
def _file_write(self, cr, uid, location, value):
bin_value = value.decode('base64')
- fname, full_path = self._get_path(cr, uid, location, bin_value)
- if not os.path.exists(full_path):
- try:
- with open(full_path, 'wb') as fp:
- fp.write(bin_value)
- except IOError:
- _logger.error("_file_write writing %s", full_path)
+ fname = hashlib.sha1(bin_value).hexdigest()
+ # scatter files across 1024 dirs
+ # we use '/' in the db (even on windows)
+ fname = fname[:3] + '/' + fname
+ full_path = self._full_path(cr, uid, location, fname)
+ try:
+ dirname = os.path.dirname(full_path)
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+ open(full_path,'wb').write(bin_value)
+ except IOError:
+ _logger.error("_file_write writing %s",full_path)
return fname
def _file_delete(self, cr, uid, location, fname):
if context is None:
context = {}
result = {}
- location = self._storage(cr, uid, context)
+ location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
bin_size = context.get('bin_size')
for attach in self.browse(cr, uid, ids, context=context):
- if location != 'db' and attach.store_fname:
+ if location and attach.store_fname:
result[attach.id] = self._file_read(cr, uid, location, attach.store_fname, bin_size)
else:
result[attach.id] = attach.db_datas
return True
if context is None:
context = {}
- location = self._storage(cr, uid, context)
+ location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
file_size = len(value.decode('base64'))
- if location != 'db':
+ if location:
attach = self.browse(cr, uid, id, context=context)
if attach.store_fname:
self._file_delete(cr, uid, location, attach.store_fname)
if isinstance(ids, (int, long)):
ids = [ids]
self.check(cr, uid, ids, 'unlink', context=context)
- location = self._storage(cr, uid, context)
- if location != 'db':
+ location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
+ if location:
for attach in self.browse(cr, uid, ids, context=context):
if attach.store_fname:
self._file_delete(cr, uid, location, attach.store_fname)
cr, uid, 'base', 'action_attachment', context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
lock_cr = db.cursor()
try:
# Try to grab an exclusive lock on the job row from within the task transaction
- # Restrict to the same conditions as for the search since the job may have already
- # been run by an other thread when cron is running in multi thread
lock_cr.execute("""SELECT *
FROM ir_cron
- WHERE numbercall != 0
- AND active
- AND nextcall <= (now() at time zone 'UTC')
- AND id=%s
+ WHERE id=%s
FOR UPDATE NOWAIT""",
(job['id'],), log_exceptions=False)
- locked_job = lock_cr.fetchone()
- if not locked_job:
- # job was already executed by another parallel process/thread, skipping it.
- continue
# Got the lock on the job row, run its code
_logger.debug('Starting job `%s`.', job['name'])
job_cr = db.cursor()
def _get_converters(self):
return {'model': ModelConverter, 'models': ModelsConverter}
- def _find_handler(self, return_rule=False):
- return self.routing_map().bind_to_environ(request.httprequest.environ).match(return_rule=return_rule)
+ def _find_handler(self):
+ return self.routing_map().bind_to_environ(request.httprequest.environ).match()
def _auth_method_user(self):
request.uid = request.session.uid
# what if error in security.check()
# -> res_users.check()
# -> res_users.check_credentials()
- except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
- # All other exceptions mean undetermined status (e.g. connection pool full),
- # let them bubble up
+ except Exception:
request.session.logout()
getattr(self, "_auth_method_%s" % auth_method)()
return auth_method
def _dispatch(self):
# locate the controller method
try:
- rule, arguments = self._find_handler(return_rule=True)
- func = rule.endpoint
+ func, arguments = self._find_handler()
except werkzeug.exceptions.NotFound, e:
return self._handle_exception(e)
convert_exception_to(
werkzeug.exceptions.Forbidden))
- processing = self._postprocess_args(arguments, rule)
+ processing = self._postprocess_args(arguments)
if processing:
return processing
return result
- def _postprocess_args(self, arguments, rule):
+ def _postprocess_args(self, arguments):
""" post process arg to set uid on browse records """
for arg in arguments.itervalues():
if isinstance(arg, orm.browse_record) and arg._uid is UID_PLACEHOLDER:
+++ /dev/null
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2014 OpenERP SA (<http://www.openerp.com>)
-#
-# 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/>.
-#
-##############################################################################
-import logging
-
-from openerp.osv import osv, fields
-from openerp.tools.translate import _
-
-class ir_logging(osv.Model):
- _name = 'ir.logging'
- _order = 'id DESC'
-
- EXCEPTIONS_TYPE = [
- ('client', 'Client'),
- ('server', 'Server')
- ]
-
- _columns = {
- 'create_date': fields.datetime('Create Date', readonly=True),
- 'create_uid': fields.integer('Uid', readonly=True), # Integer not m2o is intentionnal
- 'name': fields.char('Name', required=True),
- 'type': fields.selection(EXCEPTIONS_TYPE, string='Type', required=True, select=True),
- 'dbname': fields.char('Database Name'),
- 'level': fields.char('Level'),
- 'message': fields.text('Message', required=True),
- 'path': fields.char('Path', required=True),
- 'func': fields.char('Function', required=True),
- 'line': fields.char('Line', required=True),
- }
-
+++ /dev/null
-<?xml version="1.0"?>
-<openerp>
- <data>
- <record model="ir.ui.view" id="ir_logging_form_view">
- <field name="model">ir.logging</field>
- <field name="arch" type="xml">
- <form string="Log" version="7.0">
- <group>
- <field name="create_date" />
- <field name="dbname" />
- <field name="type" />
- <field name="name" />
- <field name="level" />
- <field name="path" />
- <field name="line" />
- <field name="func" />
- <field name="message" />
- </group>
- </form>
- </field>
- </record>
- <record model="ir.ui.view" id="ir_logging_tree_view">
- <field name="model">ir.logging</field>
- <field name="arch" type="xml">
- <tree string="Logs" version="7.0">
- <field name="create_date" />
- <field name="create_uid" />
- <field name="dbname" />
- <field name="type" />
- <field name="name" />
- <field name="level" />
- <field name="path" />
- <field name="line" />
- <field name="func" />
- </tree>
- </field>
- </record>
- <record model="ir.ui.view" id="ir_logging_search_view">
- <field name="model">ir.logging</field>
- <field name="arch" type="xml">
- <search string="Logs">
- <field name="dbname" />
- <field name="type" />
- <field name="name" />
- <field name="level" />
- <field name="message" />
- <group expand="0" string="Group By...">
- <filter string="Database" domain="[]" context="{'group_by': 'dbname'}" />
- <filter string="Level" domain="[]" context="{'group_by': 'level'}" />
- <filter string="Type" domain="[]" context="{'group_by': 'type'}" />
- <filter string="Month" domain="[]" context="{'group_by': 'create_date'}" />
- <filter string="Day" domain="[]" context="{'group_by': 'create_date:day'}" />
- </group>
- </search>
- </field>
- </record>
- <record model="ir.actions.act_window" id="ir_logging_all_act">
- <field name="name">Logging</field>
- <field name="res_model">ir.logging</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="search_view_id" ref="ir_logging_search_view" />
- </record>
- <menuitem parent="base.menu_custom" id="ir_logging_all_menu" action="ir_logging_all_act" />
- </data>
-</openerp>
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools import config
from openerp.tools.translate import _
-from openerp.osv.orm import except_orm, browse_record, MAGIC_COLUMNS
+from openerp.osv.orm import except_orm, browse_record
_logger = logging.getLogger(__name__)
def _drop_column(self, cr, uid, ids, context=None):
for field in self.browse(cr, uid, ids, context):
- if field.name in MAGIC_COLUMNS:
- continue
model = self.pool[field.model]
cr.execute('select relkind from pg_class where relname=%s', (model._table,))
result = cr.fetchone()
# Don't remove the LOG_ACCESS_COLUMNS unless _log_access
# has been turned off on the model.
field = self.pool[model].browse(cr, uid, [res_id], context=context)[0]
- if not field.exists():
- _logger.info('Deleting orphan external_ids %s', external_ids)
- self.unlink(cr, uid, external_ids)
- continue
if field.name in openerp.osv.orm.LOG_ACCESS_COLUMNS and self.pool[field.model]._log_access:
continue
if field.name == 'id':
class QWebTemplateNotFound(QWebException):
pass
-def raise_qweb_exception(etype=None, **kw):
+def convert_to_qweb_exception(etype=None, **kw):
if etype is None:
etype = QWebException
orig_type, original, tb = sys.exc_info()
e.qweb[k] = v
# Will use `raise foo from bar` in python 3 and rename cause to __cause__
e.qweb['cause'] = original
- raise
+ return e
class QWebContext(dict):
def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
try:
xml_doc = qwebcontext.loader(name)
except ValueError:
- raise_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
+ raise convert_to_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
self.load_document(xml_doc, qwebcontext=qwebcontext)
if name in qwebcontext.templates:
return qwebcontext.safe_eval(expr)
except Exception:
template = qwebcontext.get('__template__')
- raise_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
+ raise convert_to_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
def eval_object(self, expr, qwebcontext):
return self.eval(expr, qwebcontext)
return str(expr % qwebcontext)
except Exception:
template = qwebcontext.get('__template__')
- raise_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
+ raise convert_to_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
def eval_bool(self, expr, qwebcontext):
return int(bool(self.eval(expr, qwebcontext)))
raise
except Exception:
template = qwebcontext.get('__template__')
- raise_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
+ raise convert_to_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
name = str(element.nodeName)
inner = "".join(g_inner)
trim = template_attributes.get("trim", 0)
A default configuration key is ``widget`` which can override the
field's own ``_type``.
"""
+ content = None
try:
content = self.record_to_html(
cr, uid, field_name, record,
field_name, record._model._name, exc_info=True)
content = None
- if context and context.get('inherit_branding'):
- # add branding attributes
- g_att += ''.join(
- ' %s="%s"' % (name, werkzeug.utils.escape(value))
- for name, value in self.attributes(
- cr, uid, field_name, record, options,
- source_element, g_att, t_att, qweb_context)
- )
+ g_att += ''.join(
+ ' %s="%s"' % (name, werkzeug.utils.escape(value))
+ for name, value in self.attributes(
+ cr, uid, field_name, record, options,
+ source_element, g_att, t_att, qweb_context)
+ )
return self.render_element(cr, uid, source_element, t_att, g_att,
qweb_context, content)
strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
- if options and options.get('hide_seconds'):
- pattern = pattern.replace(":ss", "").replace(":s", "")
-
return babel.dates.format_datetime(value, format=pattern, locale=locale)
class TextConverter(osv.AbstractModel):
def clear_cache(self):
self.read_template.clear_cache(self)
- def _contains_branded(self, node):
- return node.tag == 't'\
- or 't-raw' in node.attrib\
- or any(self.is_node_branded(child) for child in node.iterdescendants())
-
- def _pop_view_branding(self, element):
- distributed_branding = dict(
- (attribute, element.attrib.pop(attribute))
- for attribute in MOVABLE_BRANDING
- if element.get(attribute))
- return distributed_branding
-
def distribute_branding(self, e, branding=None, parent_xpath='',
index_map=misc.ConstantMapping(1)):
if e.get('t-ignore') or e.tag == 'head':
- # remove any view branding possibly injected by inheritance
- attrs = set(MOVABLE_BRANDING)
- for descendant in e.iterdescendants(tag=etree.Element):
- if not attrs.intersection(descendant.attrib): continue
- self._pop_view_branding(descendant)
# TODO: find a better name and check if we have a string to boolean helper
return
e.set('data-oe-xpath', node_path)
if not e.get('data-oe-model'): return
- if set(('t-esc', 't-escf', 't-raw', 't-rawf')).intersection(e.attrib):
- # nodes which fully generate their content and have no reason to
- # be branded because they can not sensibly be edited
- self._pop_view_branding(e)
- elif self._contains_branded(e):
- # if a branded element contains branded elements distribute own
- # branding to children unless it's t-raw, then just remove branding
- # on current element
- distributed_branding = self._pop_view_branding(e)
+ # if a branded element contains branded elements distribute own
+ # branding to children unless it's t-raw, then just remove branding
+ # on current element
+ if e.tag == 't' or 't-raw' in e.attrib or \
+ any(self.is_node_branded(child) for child in e.iterdescendants()):
+ distributed_branding = dict(
+ (attribute, e.attrib.pop(attribute))
+ for attribute in MOVABLE_BRANDING
+ if e.get(attribute))
if 't-raw' not in e.attrib:
# TODO: collections.Counter if remove p2.6 compat
if child.get('data-oe-xpath'):
# injected by view inheritance, skip otherwise
# generated xpath is incorrect
- self.distribute_branding(child)
- else:
- indexes[child.tag] += 1
- self.distribute_branding(
- child, distributed_branding,
- parent_xpath=node_path, index_map=indexes)
+ continue
+ indexes[child.tag] += 1
+ self.distribute_branding(child, distributed_branding,
+ parent_xpath=node_path,
+ index_map=indexes)
def is_node_branded(self, node):
""" Finds out whether a node is branded or qweb-active (bears a
from openerp.osv import osv, fields
from openerp.tools.translate import _
+ADDONS_PATH = tools.config['addons_path'].split(",")[-1]
+
class base_module_import(osv.osv_memory):
""" Import Module """
res['value'] = {'currency_id': currency_id}
return res
- def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=100):
+ def _search(self, cr, uid, args, offset=0, limit=None, order=None,
+ context=None, count=False, access_rights_uid=None):
if context is None:
context = {}
- if context.pop('user_preference', None):
+ if context.get('user_preference'):
# We browse as superuser. Otherwise, the user would be able to
# select only the currently visible companies (according to rules,
# which are probably to allow to see the child companies) even if
# she belongs to some other companies.
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
cmp_ids = list(set([user.company_id.id] + [cmp.id for cmp in user.company_ids]))
- uid = SUPERUSER_ID
- args = (args or []) + [('id', 'in', cmp_ids)]
- return super(res_company, self).name_search(cr, uid, name=name, args=args, operator=operator, context=context, limit=limit)
+ return cmp_ids
+ return super(res_company, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
+ context=context, count=count, access_rights_uid=access_rights_uid)
def _company_default_get(self, cr, uid, object=False, field=False, context=None):
"""
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
- default['user_ids'] = False
name = self.read(cr, uid, [id], ['name'], context)[0]['name']
default.update({'name': _('%s (copy)') % name})
return super(res_partner, self).copy(cr, uid, id, default, context)
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
}
def on_change_login(self, cr, uid, ids, login, context=None):
- if login and tools.single_email_re.match(login):
- return {'value': {'email': login}}
- return {}
+ v = {'email': login} if tools.single_email_re.match(login) else {}
+ return {'value': v}
def onchange_state(self, cr, uid, ids, state_id, context=None):
partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)]
}))
return {'user_ids': res}
+
def change_password_button(self, cr, uid, id, context=None):
wizard = self.browse(cr, uid, id, context=context)[0]
- need_reload = any(uid == user.user_id.id for user in wizard.user_ids)
- line_ids = [user.id for user in wizard.user_ids]
-
- self.pool.get('change.password.user').change_password_button(cr, uid, line_ids, context=context)
+ user_ids = []
+ for user in wizard.user_ids:
+ user_ids.append(user.id)
+ self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context)
# don't keep temporary password copies in the database longer than necessary
- self.pool.get('change.password.user').write(cr, uid, line_ids, {'new_passwd': False}, context=context)
-
- if need_reload:
- return {
- 'type': 'ir.actions.client',
- 'tag': 'reload'
- }
-
- return {'type': 'ir.actions.act_window_close'}
+ self.pool.get('change.password.user').unlink(cr, uid, user_ids)
+ return {
+ 'type': 'ir.actions.act_window_close',
+ }
class change_password_user(osv.TransientModel):
"""
<group name="preferences" col="4">
<field name="lang" readonly="0"/>
<field name="tz" readonly="0"/>
- <field name="company_id" options="{'no_create': True}" readonly="0"
+ <field name="company_id" widget="selection" readonly="0"
groups="base.group_multi_company"/>
</group>
<group string="Email Preferences">
"access_ir_needaction_mixin","ir_needaction_mixin","model_ir_needaction_mixin",,1,1,1,1
"access_res_font_all","res_res_font all","model_res_font",,1,0,0,0
"access_res_font_group_user","res_res_font group_user","model_res_font","group_user",1,1,1,1
-"access_ir_logging","ir_logging admin","model_ir_logging","group_erp_manager",1,1,1,1
super(test_base,self).setUp()
self.res_partner = self.registry('res.partner')
self.res_users = self.registry('res.users')
- self.res_partner_title = self.registry('res.partner.title')
# samples use effective TLDs from the Mozilla public suffix
# list at http://publicsuffix.org
def test_60_read_group(self):
cr, uid = self.cr, self.uid
- title_sir = self.res_partner_title.create(cr, uid, {'name': 'Sir', 'domain': 'contact'})
- title_lady = self.res_partner_title.create(cr, uid, {'name': 'Lady', 'domain': 'contact'})
- test_users = [
- {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend', 'date': '2015-03-28', 'title': title_lady},
- {'name': 'Alice', 'login': 'alice2', 'color': 0, 'function': 'Friend', 'date': '2015-01-28', 'title': title_lady},
- {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend', 'date': '2015-03-02', 'title': title_sir},
- {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper', 'date': '2015-03-20', 'title': title_lady},
- {'name': 'Nab', 'login': 'nab', 'color': -3, 'function': '5$ Wrench', 'date': '2014-09-10', 'title': title_sir},
- {'name': 'Nab', 'login': 'nab-she', 'color': 6, 'function': '5$ Wrench', 'date': '2014-01-02', 'title': title_lady},
- ]
- ids = [self.res_users.create(cr, uid, u) for u in test_users]
- domain = [('id', 'in', ids)]
-
- # group on local char field without domain and without active_test (-> empty WHERE clause)
- groups_data = self.res_users.read_group(cr, uid, [], fields=['login'], groupby=['login'], orderby='login DESC', context={'active_test': False})
- self.assertGreater(len(groups_data), 6, "Incorrect number of results when grouping on a field")
-
- # group on local char field with limit
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['login'], groupby=['login'], orderby='login DESC', limit=3, offset=3)
- self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field with limit")
- self.assertEqual(['bob', 'alice2', 'alice'], [g['login'] for g in groups_data], 'Result mismatch')
-
- # group on inherited char field, aggregate on int field (second groupby ignored on purpose)
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color', 'function'], groupby=['function', 'login'])
- self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
- self.assertEqual(['5$ Wrench', 'Eavesdropper', 'Friend'], [g['function'] for g in groups_data], 'incorrect read_group order')
- for group_data in groups_data:
- self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
- self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
-
- # group on inherited char field, reverse order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='name DESC')
- self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
-
- # group on int field, default ordering
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['color'], groupby='color')
- self.assertEqual([-3, 0, 1, 2, 3, 6], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
-
- # multi group, second level is int field, should still be summed in first level grouping
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby=['name', 'color'], orderby='name DESC')
- self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([3, 3, 2, 1], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
-
- # group on inherited char field, multiple orders with directions
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='color DESC, name')
- self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
- self.assertEqual(['Eve', 'Nab', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([1, 2, 1, 2], [g['name_count'] for g in groups_data], 'Incorrect number of results')
-
- # group on inherited date column (res_partner.date) -> Year-Month, default ordering
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'])
- self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
- self.assertEqual(['January 2014', 'September 2014', 'January 2015', 'March 2015'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([1, 1, 1, 3], [g['date_count'] for g in groups_data], 'Incorrect number of results')
-
- # group on inherited date column (res_partner.date) -> Year-Month, custom order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'], orderby='date DESC')
- self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
- self.assertEqual(['March 2015', 'January 2015', 'September 2014', 'January 2014'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([3, 1, 1, 1], [g['date_count'] for g in groups_data], 'Incorrect number of results')
-
- # group on inherited many2one (res_partner.title), default order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'])
- self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
- # m2o is returned as a (id, label) pair
- self.assertEqual([(title_lady, 'Lady'), (title_sir, 'Sir')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
- self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
-
- # group on inherited many2one (res_partner.title), reversed natural order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="title desc")
- self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
- # m2o is returned as a (id, label) pair
- self.assertEqual([(title_sir, 'Sir'), (title_lady, 'Lady')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
- self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+ for user_data in [
+ {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend'},
+ {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend'},
+ {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper'},
+ {'name': 'Nab', 'login': 'nab', 'color': 2, 'function': '5$ Wrench'},
+ ]:
+ self.res_users.create(cr, uid, user_data)
- # group on inherited many2one (res_partner.title), multiple orders with m2o in second position
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="color desc, title desc")
+ groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color', 'function'], groupby='function')
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
- # m2o is returned as a (id, label) pair
- self.assertEqual([(title_lady, 'Lady'), (title_sir, 'Sir')], [g['title'] for g in groups_data], 'Incorrect ordering of the result')
- self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
- self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+ for group_data in groups_data:
+ self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
+ self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
- # group on inherited many2one (res_partner.title), ordered by other inherited field (color)
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby='color')
- self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
- # m2o is returned as a (id, label) pair
- self.assertEqual([(title_sir, 'Sir'), (title_lady, 'Lady')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
- self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
- self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+ groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color'], groupby='name', orderby='name DESC, color asc')
+ self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
+ self.assertEqual([user['name'] for user in groups_data], ['Eve', 'Bob', 'Alice'], 'Incorrect ordering of the list')
+ groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve', 'nab'))], fields=['function', 'color'], groupby='function', orderby='color ASC')
+ self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
+ self.assertEqual(groups_data, sorted(groups_data, key=lambda x: x['color']), 'Incorrect ordering of the list')
class test_partner_recursion(common.TransactionCase):
self.partner.write(cr, alice, [partner_id], {'property_country': country_be})
self.assertEqual(self.partner.browse(cr, alice, partner_id).property_country.id, country_be, "Alice does not see the value he has set on the property field")
self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Changes made by Alice have overwritten Bob's value")
-
-
-class TestHtmlField(common.TransactionCase):
-
- def setUp(self):
- super(TestHtmlField, self).setUp()
- self.partner = self.registry('res.partner')
-
- def test_00_sanitize(self):
- cr, uid, context = self.cr, self.uid, {}
- old_columns = self.partner._columns
- self.partner._columns = dict(old_columns)
- self.partner._columns.update({
- 'comment': fields.html('Secure Html', sanitize=False),
- })
- some_ugly_html = """<p>Oops this should maybe be sanitized
-% if object.some_field and not object.oriented:
-<table>
- % if object.other_field:
- <tr>
- ${object.mako_thing}
- <td>
- </tr>
- % endif
- <tr>
-%if object.dummy_field:
- <p>Youpie</p>
-%endif"""
-
- pid = self.partner.create(cr, uid, {
- 'name': 'Raoul Poilvache',
- 'comment': some_ugly_html,
- }, context=context)
- partner = self.partner.browse(cr, uid, pid, context=context)
- self.assertEqual(partner.comment, some_ugly_html, 'Error in HTML field: content was sanitized but field has sanitize=False')
-
- self.partner._columns.update({
- 'comment': fields.html('Unsecure Html', sanitize=True),
- })
- self.partner.write(cr, uid, [pid], {
- 'comment': some_ugly_html,
- }, context=context)
- partner = self.partner.browse(cr, uid, pid, context=context)
- # sanitize should have closed tags left open in the original html
- self.assertIn('</table>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
- self.assertIn('</td>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
-
- self.partner._columns = old_columns
import hashlib
import os
+import unittest2
+
import openerp
import openerp.tests.common
-HASH_SPLIT = 2 # FIXME: testing implementations detail is not a good idea
-
class test_ir_attachment(openerp.tests.common.TransactionCase):
- def setUp(self):
- super(test_ir_attachment, self).setUp()
+
+ def test_00_attachment_flow(self):
registry, cr, uid = self.registry, self.cr, self.uid
- self.ira = registry('ir.attachment')
- self.filestore = self.ira._filestore(cr, uid)
+ root_path = openerp.tools.config['root_path']
+ ira = registry('ir.attachment')
# Blob1
- self.blob1 = 'blob1'
- self.blob1_b64 = self.blob1.encode('base64')
- blob1_hash = hashlib.sha1(self.blob1).hexdigest()
- self.blob1_fname = blob1_hash[:HASH_SPLIT] + '/' + blob1_hash
+ blob1 = 'blob1'
+ blob1_b64 = blob1.encode('base64')
+ blob1_hash = hashlib.sha1(blob1).hexdigest()
+ blob1_fname = blob1_hash[:3] + '/' + blob1_hash
# Blob2
blob2 = 'blob2'
- self.blob2_b64 = blob2.encode('base64')
-
- def test_01_store_in_db(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- # force storing in database
- registry('ir.config_parameter').set_param(cr, uid, 'ir_attachment.location', 'db')
+ blob2_b64 = blob2.encode('base64')
+ blob2_hash = hashlib.sha1(blob2).hexdigest()
+ blob2_fname = blob2_hash[:3] + '/' + blob2_hash
# 'ir_attachment.location' is undefined test database storage
- a1 = self.ira.create(cr, uid, {'name': 'a1', 'datas': self.blob1_b64})
- a1_read = self.ira.read(cr, uid, [a1], ['datas'])
- self.assertEqual(a1_read[0]['datas'], self.blob1_b64)
-
- a1_db_datas = self.ira.browse(cr, uid, a1).db_datas
- self.assertEqual(a1_db_datas, self.blob1_b64)
+ a1 = ira.create(cr, uid, {'name': 'a1', 'datas': blob1_b64})
+ a1_read = ira.read(cr, uid, [a1], ['datas'])
+ self.assertEqual(a1_read[0]['datas'], blob1_b64)
- def test_02_store_on_disk(self):
- registry, cr, uid = self.registry, self.cr, self.uid
+ cr.execute("select id,db_datas from ir_attachment where id = %s", (a1,) )
+ a1_db_datas = str(cr.fetchall()[0][1])
+ self.assertEqual(a1_db_datas, blob1_b64)
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
+ # define a location for filestore
+ registry('ir.config_parameter').set_param(cr, uid, 'ir_attachment.location', 'file:///filestore')
- self.assertEqual(a2_store_fname, self.blob1_fname)
- self.assertTrue(os.path.isfile(os.path.join(self.filestore, a2_store_fname)))
+ # Test file storage
+ a2 = ira.create(cr, uid, {'name': 'a2', 'datas': blob1_b64})
+ a2_read = ira.read(cr, uid, [a2], ['datas'])
+ self.assertEqual(a2_read[0]['datas'], blob1_b64)
- def test_03_no_duplication(self):
- registry, cr, uid = self.registry, self.cr, self.uid
+ cr.execute("select id,store_fname from ir_attachment where id = %s", (a2,) )
+ a2_store_fname = cr.fetchall()[0][1]
+ self.assertEqual(a2_store_fname, blob1_fname)
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
+ a2_fn = os.path.join(root_path, 'filestore', cr.dbname, blob1_hash[:3], blob1_hash)
+ fc = file(a2_fn).read()
+ self.assertEqual(fc, blob1)
- a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
- a3_store_fname = self.ira.browse(cr, uid, a3).store_fname
+ # create a3 with same blob
+ a3 = ira.create(cr, uid, {'name': 'a3', 'datas': blob1_b64})
+ a3_read = ira.read(cr, uid, [a3], ['datas'])
+ self.assertEqual(a3_read[0]['datas'], blob1_b64)
+ cr.execute("select id,store_fname from ir_attachment where id = %s", (a3,) )
+ a3_store_fname = cr.fetchall()[0][1]
self.assertEqual(a3_store_fname, a2_store_fname)
- def test_04_keep_file(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
+ # create a4 blob2
+ a4 = ira.create(cr, uid, {'name': 'a4', 'datas': blob2_b64})
+ a4_read = ira.read(cr, uid, [a4], ['datas'])
+ self.assertEqual(a4_read[0]['datas'], blob2_b64)
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- a2_fn = os.path.join(self.filestore, a2_store_fname)
+ a4_fn = os.path.join(root_path, 'filestore', cr.dbname, blob2_hash[:3], blob2_hash)
+ self.assertTrue(os.path.isfile(a4_fn))
- self.ira.unlink(cr, uid, [a3])
+ # delete a3 but file stays
+ ira.unlink(cr, uid, [a3])
self.assertTrue(os.path.isfile(a2_fn))
# delete a2 it is unlinked
- self.ira.unlink(cr, uid, [a2])
+ ira.unlink(cr, uid, [a2])
self.assertFalse(os.path.isfile(a2_fn))
- def test_05_change_data_change_file(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- a2_fn = os.path.join(self.filestore, a2_store_fname)
+ # update a4 blob2 by blob1
+ ira.write(cr, uid, [a4], {'datas': blob1_b64})
+ a4_read = ira.read(cr, uid, [a4], ['datas'])
+ self.assertEqual(a4_read[0]['datas'], blob1_b64)
+ # file of a4 disapear and a2 reappear
+ self.assertFalse(os.path.isfile(a4_fn))
self.assertTrue(os.path.isfile(a2_fn))
- self.ira.write(cr, uid, [a2], {'datas': self.blob2_b64})
- self.assertFalse(os.path.isfile(a2_fn))
+ # everybody applause
- new_a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- self.assertNotEqual(a2_store_fname, new_a2_store_fname)
- new_a2_fn = os.path.join(self.filestore, new_a2_store_fname)
- self.assertTrue(os.path.isfile(new_a2_fn))
# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence
# This assume an existing database.
import psycopg2
-import psycopg2.errorcodes
import unittest2
import openerp
cr0 = cursor()
cr1 = cursor()
cr1._default_log_exceptions = False # Prevent logging a traceback
- with self.assertRaises(psycopg2.OperationalError) as e:
+ msg_re = '^could not obtain lock on row in relation "ir_sequence"$'
+ with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re):
n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {})
assert n0
n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {})
- self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
cr0.close()
cr1.close()
self.engine = self.registry('ir.qweb')
def context(self, values):
- return ir_qweb.QWebContext(
- self.cr, self.uid, values, context={'inherit_branding': True})
+ return ir_qweb.QWebContext(self.cr, self.uid, values)
def test_trivial(self):
field = document.createElement('span')
# -*- encoding: utf-8 -*-
from functools import partial
-import unittest2
-
from lxml import etree as ET
from lxml.builder import E
Field = E.field
-class ViewCase(common.TransactionCase):
- def setUp(self):
- super(ViewCase, self).setUp()
- self.addTypeEqualityFunc(ET._Element, self.assertTreesEqual)
-
- def assertTreesEqual(self, n1, n2, msg=None):
- self.assertEqual(n1.tag, n2.tag)
- self.assertEqual((n1.text or '').strip(), (n2.text or '').strip(), msg)
- self.assertEqual((n1.tail or '').strip(), (n2.tail or '').strip(), msg)
-
- # Because lxml uses ordereddicts in which order is important to
- # equality (!?!?!?!)
- self.assertEqual(dict(n1.attrib), dict(n2.attrib), msg)
-
- for c1, c2 in zip(n1, n2):
- self.assertTreesEqual(c1, c2, msg)
-
-
class TestNodeLocator(common.BaseCase):
"""
The node locator returns None when it can not find a node, and the first
E.foo(attr='1', version='3'))
self.assertIsNone(node)
-class TestViewInheritance(ViewCase):
+class TestViewInheritance(common.TransactionCase):
def arch_for(self, name, view_type='form', parent=None):
""" Generates a trivial view of the specified ``view_type``.
self.View.default_view(
self.cr, self.uid, model=self.model, view_type='graph'))
-class TestApplyInheritanceSpecs(ViewCase):
+class TestApplyInheritanceSpecs(common.TransactionCase):
""" Applies a sequence of inheritance specification nodes to a base
architecture. IO state parameters (cr, uid, model, context) are used for
error reporting
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(Field(name="replacement"), string="Title"))
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(Field(name="replacement"), string="Title")))
def test_delete(self):
spec = Field(name="target", position="replace")
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(string="Title"))
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(string="Title")))
def test_insert_after(self):
spec = Field(
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(
Field(name="target"),
Field(name="inserted"),
string="Title"
- ))
+ )))
def test_insert_before(self):
spec = Field(
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(
Field(name="inserted"),
Field(name="target"),
- string="Title"))
+ string="Title")))
def test_insert_inside(self):
default = Field(Field(name="inserted"), name="target")
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(
Field(
Field(name="inserted"),
Field(name="inserted 2"),
name="target"),
- string="Title"))
+ string="Title")))
def test_unpack_data(self):
spec = E.data(
spec, None)
self.assertEqual(
- self.base_arch,
- E.form(
+ ET.tostring(self.base_arch),
+ ET.tostring(E.form(
Field(
Field(name="inserted 0"),
Field(name="inserted 1"),
Field(name="inserted 2"),
Field(name="inserted 3"),
name="target"),
- string="Title"))
+ string="Title")))
def test_invalid_position(self):
spec = Field(
self.base_arch,
spec, None)
-class TestApplyInheritedArchs(ViewCase):
+class TestApplyInheritedArchs(common.TransactionCase):
""" Applies a sequence of modificator archs to a base view
"""
-class TestViewCombined(ViewCase):
+class TestViewCombined(common.TransactionCase):
"""
Test fallback operations of View.read_combined:
* defaults mapping
* ?
"""
-class TestNoModel(ViewCase):
+class TestNoModel(common.TransactionCase):
def test_create_view_nomodel(self):
View = self.registry('ir.ui.view')
view_id = View.create(self.cr, self.uid, {
'value': translated_text,
})
sarch = View.translate_qweb(self.cr, self.uid, None, self.arch, 'fr_FR')
-
+
self.text_para.text = translated_text
- self.assertEqual(sarch, self.arch)
+ self.assertEqual(
+ ET.tostring(sarch, encoding='utf-8'),
+ ET.tostring(self.arch, encoding='utf-8'))
-class TestTemplating(ViewCase):
+class TestTemplating(common.TransactionCase):
def setUp(self):
import openerp.modules
super(TestTemplating, self).setUp()
second.get('data-oe-id'),
"second should come from the extension view")
- def test_branding_distribute_inner(self):
- """ Checks that the branding is correctly distributed within a view
- extension
- """
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
- 'name': "Base view",
- 'type': 'qweb',
- 'arch': """<root>
- <item order="1"/>
- </root>"""
- })
- id2 = Views.create(self.cr, self.uid, {
- 'name': "Extension",
- 'type': 'qweb',
- 'inherit_id': id,
- 'arch': """<xpath expr="//item" position="before">
- <item order="2">
- <content t-att-href="foo">bar</content>
- </item>
- </xpath>"""
- })
-
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
-
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
-
- self.assertEqual(
- arch,
- E.root(
- E.item(
- E.content("bar", {
- 't-att-href': "foo",
- 'data-oe-model': 'ir.ui.view',
- 'data-oe-id': str(id2),
- 'data-oe-field': 'arch',
- 'data-oe-xpath': '/xpath/item/content[1]',
- }), {
- 'order': '2',
- 'data-oe-source-id': str(id)
- }),
- E.item({
- 'order': '1',
- 'data-oe-model': 'ir.ui.view',
- 'data-oe-id': str(id),
- 'data-oe-field': 'arch',
- 'data-oe-xpath': '/root[1]/item[1]'
- })
- )
- )
-
- def test_esc_no_branding(self):
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
- 'name': "Base View",
- 'type': 'qweb',
- 'arch': """<root>
- <item><span t-esc="foo"/></item>
- </root>""",
- })
-
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
-
- self.assertEqual(arch, E.root(E.item(E.span({'t-esc': "foo"}))))
-
- def test_ignore_unbrand(self):
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
- 'name': "Base view",
- 'type': 'qweb',
- 'arch': """<root>
- <item order="1" t-ignore="true">
- <t t-esc="foo"/>
- </item>
- </root>"""
- })
- id2 = Views.create(self.cr, self.uid, {
- 'name': "Extension",
- 'type': 'qweb',
- 'inherit_id': id,
- 'arch': """<xpath expr="//item[@order='1']" position="inside">
- <item order="2">
- <content t-att-href="foo">bar</content>
- </item>
- </xpath>"""
- })
-
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
-
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
-
- self.assertEqual(
- arch,
- E.root(
- E.item(
- {'t-ignore': 'true', 'order': '1'},
- E.t({'t-esc': 'foo'}),
- E.item(
- {'order': '2', 'data-oe-source-id': str(id)},
- E.content(
- {'t-att-href': 'foo'},
- "bar")
- )
- )
- ),
- "t-ignore should apply to injected sub-view branding, not just to"
- " the main view's"
- )
-
-class test_views(ViewCase):
+class test_views(common.TransactionCase):
def test_nonexistent_attribute_removal(self):
Views = self.registry('ir.ui.view')
})
self.assertEqual(view['type'], 'form')
self.assertEqual(
- ET.fromstring(
+ ET.tostring(ET.fromstring(
view['arch'],
parser=ET.XMLParser(remove_blank_text=True)
- ),
- E.form(
- E.p("Replacement data"),
- E.footer(
- E.button(name="action_next", type="object", string="New button"),
- thing="bob"
- ),
- string="Replacement title", version="7.0"))
+ )),
+ '<form string="Replacement title" version="7.0">'
+ '<p>Replacement data</p>'
+ '<footer thing="bob">'
+ '<button name="action_next" type="object" string="New button"/>'
+ '</footer>'
+ '</form>')
def test_view_inheritance_divergent_models(self):
Views = self.registry('ir.ui.view')
})
self.assertEqual(view['type'], 'form')
self.assertEqual(
- ET.fromstring(
+ ET.tostring(ET.fromstring(
view['arch'],
parser=ET.XMLParser(remove_blank_text=True)
- ),
- E.form(
- E.p("Replacement data"),
- E.footer(
- E.button(name="action_next", type="object", string="New button")),
- string="Replacement title", version="7.0"
- ))
+ )),
+ '<form string="Replacement title" version="7.0">'
+ '<p>Replacement data</p>'
+ '<footer>'
+ '<button name="action_next" type="object" string="New button"/>'
+ '</footer>'
+ '</form>')
+
'widget': 'monetary',
'display_currency': 'c2'
}
- context = dict(inherit_branding=True)
converted = converter.to_html(
self.cr, self.uid, 'value', obj, options,
doc.createElement('span'),
{'field': 'obj.value', 'field-options': json.dumps(options)},
- '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }),
- context=context,
- )
+ '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }))
return converted
def test_currency_post(self):
def test_external_id(self):
integer_id = self.registry('export.integer').create(
self.cr, openerp.SUPERUSER_ID, {'value': 42})
- # Expecting the m2o target model name in the external id,
- # not this model's name
- external_id = u'__export__.export_integer_%d' % integer_id
+ # __export__.$class.$id
+ external_id = u'__export__.export_many2one_%d' % integer_id
self.assertEqual(
self.export(integer_id, fields=['value/id']),
[[external_id]])
"""
config = openerp.tools.config
_logger.info("OpenERP version %s", __version__)
- for name, value in [('addons paths', openerp.modules.module.ad_paths),
+ for name, value in [('addons paths', config['addons_path']),
('database hostname', config['db_host'] or 'localhost'),
('database port', config['db_port'] or '5432'),
('database user', config['db_user'])]:
import warnings
import babel.core
-import psutil
import psycopg2
import simplejson
import werkzeug.contrib.sessions
import openerp
from openerp.service import security, model as service_model
+import openerp.tools
_logger = logging.getLogger(__name__)
A global proxy that always redirect to the current request object.
"""
-def replace_request_password(args):
- # password is always 3rd argument in a request, we replace it in RPC logs
- # so it's easier to forward logs for diagnostics/debugging purposes...
- if len(args) > 2:
- args = list(args)
- args[2] = '*'
- return tuple(args)
-
-def dispatch_rpc(service_name, method, params):
- """ Handle a RPC call.
-
- This is pure Python code, the actual marshalling (from/to XML-RPC) is done
- in a upper layer.
- """
- try:
- rpc_request = logging.getLogger(__name__ + '.rpc.request')
- rpc_response = logging.getLogger(__name__ + '.rpc.response')
- rpc_request_flag = rpc_request.isEnabledFor(logging.DEBUG)
- rpc_response_flag = rpc_response.isEnabledFor(logging.DEBUG)
- if rpc_request_flag or rpc_response_flag:
- start_time = time.time()
- start_rss, start_vms = 0, 0
- start_rss, start_vms = psutil.Process(os.getpid()).get_memory_info()
- if rpc_request and rpc_response_flag:
- openerp.netsvc.log(rpc_request, logging.DEBUG, '%s.%s' % (service_name, method), replace_request_password(params))
-
- threading.current_thread().uid = None
- threading.current_thread().dbname = None
- if service_name == 'common':
- dispatch = openerp.service.common.dispatch
- elif service_name == 'db':
- dispatch = openerp.service.db.dispatch
- elif service_name == 'object':
- dispatch = openerp.service.model.dispatch
- elif service_name == 'report':
- dispatch = openerp.service.report.dispatch
- else:
- dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name)
- result = dispatch(method, params)
-
- if rpc_request_flag or rpc_response_flag:
- end_time = time.time()
- end_rss, end_vms = 0, 0
- end_rss, end_vms = psutil.Process(os.getpid()).get_memory_info()
- logline = '%s.%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % (service_name, method, end_time - start_time, start_vms / 1024, end_vms / 1024, (end_vms - start_vms)/1024)
- if rpc_response_flag:
- openerp.netsvc.log(rpc_response, logging.DEBUG, logline, result)
- else:
- openerp.netsvc.log(rpc_request, logging.DEBUG, logline, replace_request_password(params), depth=1)
-
- return result
- except (openerp.osv.orm.except_orm, openerp.exceptions.AccessError, \
- openerp.exceptions.AccessDenied, openerp.exceptions.Warning, \
- openerp.exceptions.RedirectWarning):
- raise
- except openerp.exceptions.DeferredException, e:
- _logger.exception(openerp.tools.exception_to_unicode(e))
- openerp.tools.debugger.post_mortem(openerp.tools.config, e.traceback)
- raise
- except Exception, e:
- _logger.exception(openerp.tools.exception_to_unicode(e))
- openerp.tools.debugger.post_mortem(openerp.tools.config, sys.exc_info())
- raise
-
def local_redirect(path, query=None, keep_hash=False, forward_debug=True, code=303):
url = path
if not query:
self.session_id = httprequest.session.sid
self.disable_db = False
self.uid = None
- self.endpoint = None
+ self.func = None
+ self.func_arguments = {}
self.auth_method = None
self._cr_cm = None
self._cr = None
-
- # prevents transaction commit, use when you catch an exception during handling
- self._failed = None
-
+ self.func_request_type = None
# set db/uid trackers - they're cleaned up at the WSGI
# dispatching phase in openerp.service.wsgi_server.application
if self.db:
_request_stack.pop()
if self._cr:
- # Dont close test cursors
- if not openerp.tests.common.release_test_cursor(self._cr):
- if exc_type is None and not self._failed:
+ # Dont commit test cursors
+ if not openerp.tests.common.release_test_cursor(self.session_id):
+ if exc_type is None:
self._cr.commit()
- else:
- # just to be explicit - happens at close() anyway
- self._cr.rollback()
self._cr.close()
# just to be sure no one tries to re-use the request
self.disable_db = True
self.uid = None
- def set_handler(self, endpoint, arguments, auth):
+ def set_handler(self, func, arguments, auth):
# is this needed ?
arguments = dict((k, v) for k, v in arguments.iteritems()
if not k.startswith("_ignored_"))
- endpoint.arguments = arguments
- self.endpoint = endpoint
+ self.func = func
+ self.func_request_type = func.routing['type']
+ self.func_arguments = arguments
self.auth_method = auth
def _call_function(self, *args, **kwargs):
request = self
- if self.endpoint.routing['type'] != self._request_type:
+ if self.func_request_type != self._request_type:
raise Exception("%s, %s: Function declared as capable of handling request of type '%s' but called with a request of type '%s'" \
- % (self.endpoint.original, self.httprequest.path, self.endpoint.routing['type'], self._request_type))
+ % (self.func, self.httprequest.path, self.func_request_type, self._request_type))
- kwargs.update(self.endpoint.arguments)
+ kwargs.update(self.func_arguments)
# Backward for 7.0
- if self.endpoint.first_arg_is_req:
+ if getattr(self.func.method, '_first_arg_is_req', False):
args = (request,) + args
-
# Correct exception handling and concurency retry
@service_model.check
def checked_call(___dbname, *a, **kw):
- # The decorator can call us more than once if there is an database error. In this
- # case, the request cursor is unusable. Rollback transaction to create a new one.
+ return self.func(*a, **kw)
+
+ # FIXME: code and rollback management could be cleaned
+ try:
+ if self.db:
+ return checked_call(self.db, *args, **kwargs)
+ return self.func(*args, **kwargs)
+ except Exception:
if self._cr:
self._cr.rollback()
- return self.endpoint(*a, **kw)
-
- if self.db:
- return checked_call(self.db, *args, **kwargs)
- return self.endpoint(*args, **kwargs)
+ raise
@property
def debug(self):
else:
routes = [route]
routing['routes'] = routes
- @functools.wraps(f)
- def response_wrap(*args, **kw):
- response = f(*args, **kw)
- if isinstance(response, Response) or f.routing_type == 'json':
- return response
- elif isinstance(response, werkzeug.wrappers.BaseResponse):
- response = Response.force_type(response)
- response.set_default()
- return response
- elif isinstance(response, basestring):
- return Response(response)
- else:
- _logger.warn("<function %s.%s> returns an invalid response type for an http request" % (f.__module__, f.__name__))
- return response
- response_wrap.routing = routing
- response_wrap.original_func = f
- return response_wrap
+ f.routing = routing
+ return f
return decorator
class JsonRequest(WebRequest):
response['id'] = self.jsonrequest.get('id')
response["result"] = self._call_function(**self.params)
except AuthenticationError, e:
- _logger.exception("JSON-RPC AuthenticationError in %s.", self.httprequest.path)
+ _logger.exception("Exception during JSON request handling.")
se = serialize_exception(e)
error = {
'code': 100,
'message': "OpenERP Session Invalid",
'data': se
}
- self._failed = e # prevent tx commit
except Exception, e:
- # Mute test cursor error for runbot
- if not (openerp.tools.config['test_enable'] and isinstance(e, psycopg2.OperationalError)):
- _logger.exception("JSON-RPC Exception in %s.", self.httprequest.path)
+ _logger.exception("Exception during JSON request handling.")
se = serialize_exception(e)
error = {
'code': 200,
'message': "OpenERP Server Error",
'data': se
}
- self._failed = e # prevent tx commit
if error:
response["error"] = error
mime = 'application/json'
body = simplejson.dumps(response)
- r = Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
+ r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
return r
def serialize_exception(e):
self.params = params
def dispatch(self):
- if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
- headers = {
- 'Access-Control-Max-Age': 60 * 60 * 24,
- 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
- }
- return Response(status=200, headers=headers)
+ # TODO: refactor this correctly. This is a quick fix for pos demo.
+ if request.httprequest.method == 'OPTIONS' and request.func and request.func.routing.get('cors'):
+ response = werkzeug.wrappers.Response(status=200)
+ response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
+ methods = 'GET, POST'
+ if request.func_request_type == 'json':
+ methods = 'POST'
+ elif request.func.routing.get('methods'):
+ methods = ', '.join(request.func.routing['methods'])
+ response.headers.set('Access-Control-Allow-Methods', methods)
+ response.headers.set('Access-Control-Max-Age',60*60*24)
+ response.headers.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
+ return response
r = self._call_function(**self.params)
if not r:
- r = Response(status=204) # no content
+ r = werkzeug.wrappers.Response(status=204) # no content
return r
def make_response(self, data, headers=None, cookies=None):
:type headers: ``[(name, value)]``
:param collections.Mapping cookies: cookies to set on the client
"""
- response = Response(data, headers=headers)
+ response = werkzeug.wrappers.Response(data, headers=headers)
if cookies:
for k, v in cookies.iteritems():
response.set_cookie(k, v)
return response
- def render(self, template, qcontext=None, **kw):
- """ Lazy render of QWeb template.
-
- The actual rendering of the given template will occur at then end of
- the dispatching. Meanwhile, the template and/or qcontext can be
- altered or even replaced by a static response.
-
- :param basestring template: template to render
- :param dict qcontext: Rendering context to use
- """
- return Response(template=template, qcontext=qcontext, **kw)
-
def not_found(self, description=None):
""" Helper for 404 response, return its result from the method
"""
class EndPoint(object):
def __init__(self, method, routing):
self.method = method
- self.original = getattr(method, 'original_func', method)
self.routing = routing
- self.arguments = {}
-
- @property
- def first_arg_is_req(self):
- # Backward for 7.0
- return getattr(self.method, '_first_arg_is_req', False)
-
def __call__(self, *args, **kw):
return self.method(*args, **kw)
if inspect.ismethod(mv) and hasattr(mv, 'routing'):
routing = dict(type='http', auth='user', methods=None, routes=None)
methods_done = list()
- routing_type = None
for claz in reversed(mv.im_class.mro()):
fn = getattr(claz, mv.func_name, None)
if fn and hasattr(fn, 'routing') and fn not in methods_done:
- fn_type = fn.routing.get('type')
- if not routing_type:
- routing_type = fn_type
- else:
- if fn_type and routing_type != fn_type:
- _logger.warn("Subclass re-defines <function %s.%s> with different type than original."
- " Will use original type: %r", fn.__module__, fn.__name__, routing_type)
- fn.routing['type'] = routing_type
- fn.original_func.routing_type = routing_type
methods_done.append(fn)
routing.update(fn.routing)
if not nodb_only or nodb_only == (routing['auth'] == "none"):
class Service(object):
"""
.. deprecated:: 8.0
- Use ``dispatch_rpc()`` instead.
+ Use ``openerp.netsvc.dispatch_rpc()`` instead.
"""
def __init__(self, session, service_name):
self.session = session
def __getattr__(self, method):
def proxy_method(*args):
- result = dispatch_rpc(self.service_name, method, args)
+ result = openerp.netsvc.dispatch_rpc(self.service_name, method, args)
return result
return proxy_method
HTTP_HOST=wsgienv['HTTP_HOST'],
REMOTE_ADDR=wsgienv['REMOTE_ADDR'],
)
- uid = dispatch_rpc('common', 'authenticate', [db, login, password, env])
+ uid = openerp.netsvc.dispatch_rpc('common', 'authenticate', [db, login, password, env])
else:
security.check(db, uid, password)
self.db = db
self.setdefault("uid", None)
self.setdefault("login", None)
self.setdefault("password", None)
- self.setdefault("context", {})
+ self.setdefault("context", {'tz': "UTC", "uid": None})
def get_context(self):
"""
def send(self, service_name, method, *args):
"""
.. deprecated:: 8.0
- Use ``dispatch_rpc()`` instead.
+ Use ``openerp.netsvc.dispatch_rpc()`` instead.
"""
- return dispatch_rpc(service_name, method, args)
+ return openerp.netsvc.dispatch_rpc(service_name, method, args)
def proxy(self, service):
"""
.. deprecated:: 8.0
- Use ``dispatch_rpc()`` instead.
+ Use ``openerp.netsvc.dispatch_rpc()`` instead.
"""
return Service(self, service)
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
mimetypes.add_type('application/x-font-ttf', '.ttf')
-class Response(werkzeug.wrappers.Response):
- """ Response object passed through controller route chain.
-
- In addition to the werkzeug.wrappers.Response parameters, this
- classe's constructor can take the following additional parameters
- for QWeb Lazy Rendering.
-
- :param basestring template: template to render
- :param dict qcontext: Rendering context to use
- :param int uid: User id to use for the ir.ui.view render call
- """
- default_mimetype = 'text/html'
- def __init__(self, *args, **kw):
- template = kw.pop('template', None)
- qcontext = kw.pop('qcontext', None)
- uid = kw.pop('uid', None)
- super(Response, self).__init__(*args, **kw)
- self.set_default(template, qcontext, uid)
-
- def set_default(self, template=None, qcontext=None, uid=None):
- self.template = template
- self.qcontext = qcontext or dict()
- self.uid = uid
- # Support for Cross-Origin Resource Sharing
- if request.endpoint and 'cors' in request.endpoint.routing:
- self.headers.set('Access-Control-Allow-Origin', request.endpoint.routing['cors'])
- methods = 'GET, POST'
- if request.endpoint.routing['type'] == 'json':
- methods = 'POST'
- elif request.endpoint.routing.get('methods'):
- methods = ', '.join(request.endpoint.routing['methods'])
- self.headers.set('Access-Control-Allow-Methods', methods)
-
- @property
- def is_qweb(self):
- return self.template is not None
-
- def render(self):
- view_obj = request.registry["ir.ui.view"]
- uid = self.uid or request.uid or openerp.SUPERUSER_ID
- return view_obj.render(request.cr, uid, self.template, self.qcontext, context=request.context)
+class LazyResponse(werkzeug.wrappers.Response):
+ """ Lazy werkzeug response.
+ API not yet frozen"""
- def flatten(self):
- self.response.append(self.render())
- self.template = None
+ def __init__(self, callback, status_code=None, **kwargs):
+ super(LazyResponse, self).__init__(mimetype='text/html')
+ if status_code:
+ self.status_code = status_code
+ self.callback = callback
+ self.params = kwargs
+ def process(self):
+ response = self.callback(**self.params)
+ self.response.append(response)
class DisableCacheMiddleware(object):
def __init__(self, app):
start_response(status, new_headers)
return self.app(environ, start_wrapped)
+def session_path():
+ try:
+ import pwd
+ username = pwd.getpwuid(os.geteuid()).pw_name
+ except ImportError:
+ try:
+ username = getpass.getuser()
+ except Exception:
+ username = "unknown"
+ path = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
+ try:
+ os.mkdir(path, 0700)
+ except OSError as exc:
+ if exc.errno == errno.EEXIST:
+ # directory exists: ensure it has the correct permissions
+ # this will fail if the directory is not owned by the current user
+ os.chmod(path, 0700)
+ else:
+ raise
+ return path
+
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
"""
def __init__(self):
# Setup http sessions
- path = openerp.tools.config.session_dir
+ path = session_path()
_logger.debug('HTTP sessions stored in: %s', path)
self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path, session_class=OpenERPSession)
return HttpRequest(httprequest)
def get_response(self, httprequest, result, explicit_session):
- if isinstance(result, Response) and result.is_qweb:
+ if isinstance(result, LazyResponse):
try:
- result.flatten()
+ result.process()
except(Exception), e:
if request.db:
result = request.registry['ir.http']._handle_exception(e)
raise
if isinstance(result, basestring):
- response = Response(result, mimetype='text/html')
+ response = werkzeug.wrappers.Response(result, mimetype='text/html')
else:
response = result
if not explicit_session and hasattr(response, 'set_cookie'):
response.set_cookie('session_id', httprequest.session.sid, max_age=90 * 24 * 60 * 60)
+ # Support for Cross-Origin Resource Sharing
+ if request.func and 'cors' in request.func.routing:
+ response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
+ methods = 'GET, POST'
+ if request.func_request_type == 'json':
+ methods = 'POST'
+ elif request.func.routing.get('methods'):
+ methods = ', '.join(request.func.routing['methods'])
+ response.headers.set('Access-Control-Allow-Methods', methods)
+
return response
def dispatch(self, environ, start_response):
return request.registry['ir.http'].routing_map()
def db_list(force=False, httprequest=None):
- dbs = dispatch_rpc("db", "list", [force])
+ dbs = openerp.netsvc.dispatch_rpc("db", "list", [force])
return db_filter(dbs, httprequest=httprequest)
def db_filter(dbs, httprequest=None):
httprequest = httprequest or request.httprequest
- h = httprequest.environ.get('HTTP_HOST', '').split(':')[0]
+ h = httprequest.environ['HTTP_HOST'].split(':')[0]
d = h.split('.')[0]
r = openerp.tools.config['dbfilter'].replace('%h', h).replace('%d', d)
dbs = [i for i in dbs if re.match(r, i)]
@route('/jsonrpc', type='json', auth="none")
def jsonrpc(self, service, method, args):
""" Method used by client APIs to contact OpenERP. """
- return dispatch_rpc(service, method, args)
+ return openerp.netsvc.dispatch_rpc(service, method, args)
+
+ @route('/gen_session_id', type='json', auth="none")
+ def gen_session_id(self):
+ nsession = root.session_store.new()
+ return nsession.sid
root = None
# Yamel test
report.record_result(load_test(module_name, idref, mode))
# Python tests
- ir_http = registry['ir.http']
- if hasattr(ir_http, '_routing_map'):
- # Force routing map to be rebuilt between each module test suite
- del(ir_http._routing_map)
report.record_result(openerp.modules.module.run_unit_tests(module_name, cr.dbname))
processed_modules.append(package.name)
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
from openerp.tools.safe_eval import safe_eval as eval
_logger = logging.getLogger(__name__)
+_test_logger = logging.getLogger('openerp.tests')
+
+# addons path ','.joined
+_ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base)
# addons path as a list
ad_paths = []
if ad_paths:
return
- ad_paths = [tools.config.addons_data_dir]
- ad_paths += map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
-
- # add base module path
- base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons'))
- ad_paths += [base_path]
-
+ ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
+ ad_paths.append(os.path.abspath(_ad)) # for get_module_path
sys.meta_path.append(AddonsImportHook())
def get_module_path(module, downloaded=False, display_warning=True):
return opj(adp, module)
if downloaded:
- return opj(tools.config.addons_data_dir, module)
+ return opj(_ad, module)
if display_warning:
_logger.warning('module %s: module not found', module)
return False
# Use a custom stream object to log the test executions.
class TestStream(object):
- def __init__(self, logger_name='openerp.tests'):
- self.logger = logging.getLogger(logger_name)
+ def __init__(self):
self.r = re.compile(r'^-*$|^ *... *$|^ok$')
def flush(self):
pass
if not first:
c = '` ' + c
first = False
- self.logger.info(c)
+ _test_logger.info(c)
current_test = None
for m in mods:
tests = unwrap_suite(unittest2.TestLoader().loadTestsFromModule(m))
suite = unittest2.TestSuite(itertools.ifilter(runs_at_install, tests))
- _logger.info('running %s tests.', m.__name__)
+ _logger.info('module %s: running test %s.', module_name, m.__name__)
- result = unittest2.TextTestRunner(verbosity=2, stream=TestStream(m.__name__)).run(suite)
+ result = unittest2.TextTestRunner(verbosity=2, stream=TestStream()).run(suite)
if not result.wasSuccessful():
r = False
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2014 OpenERP SA (<http://www.openerp.com>)
+# Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
#
##############################################################################
+
import logging
import logging.handlers
import os
-import pprint
import release
import sys
import threading
+import time
+import types
+from pprint import pformat
+import psutil
-import psycopg2
-
-import openerp
-import sql_db
import tools
+import openerp
_logger = logging.getLogger(__name__)
-def log(logger, level, prefix, msg, depth=None):
- indent=''
- indent_after=' '*len(prefix)
- for line in (prefix + pprint.pformat(msg, depth=depth)).split('\n'):
- logger.log(level, indent+line)
- indent=indent_after
-
def LocalService(name):
"""
The openerp.netsvc.LocalService() function is deprecated. It still works
with registry.cursor() as cr:
return registry['ir.actions.report.xml']._lookup_report(cr, name[len('report.'):])
-class PostgreSQLHandler(logging.Handler):
- """ PostgreSQL Loggin Handler will store logs in the database, by default
- the current database, can be set using --log-db=DBNAME
- """
- def emit(self, record):
- ct = threading.current_thread()
- ct_db = getattr(ct, 'dbname', None)
- ct_uid = getattr(ct, 'uid', None)
- dbname = tools.config['log_db'] or ct_db
- if dbname:
- cr = None
- try:
- cr = sql_db.db_connect(dbname).cursor()
- msg = unicode(record.msg)
- traceback = getattr(record, 'exc_text', '')
- if traceback:
- msg = "%s\n%s" % (msg, traceback)
- level = logging.getLevelName(record.levelno)
- val = (ct_uid, ct_uid, 'server', dbname, record.name, level, msg, record.pathname, record.lineno, record.funcName)
- cr.execute("""
- INSERT INTO ir_logging(create_date, write_date, create_uid, write_uid, type, dbname, name, level, message, path, line, func)
- VALUES (NOW() at time zone 'UTC', NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
- """, val )
- cr.commit()
- except Exception, e:
- pass
- finally:
- if cr:
- cr.close()
-
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, _NOTHING, DEFAULT = range(10)
#The background is set with 40 plus the number of the color, and the foreground with 30
#These are the sequences need to get colored ouput
record.levelname = COLOR_PATTERN % (30 + fg_color, 40 + bg_color, record.levelname)
return DBFormatter.format(self, record)
-_logger_init = False
def init_logger():
- global _logger_init
- if _logger_init:
- return
- _logger_init = True
-
from tools.translate import resetlocale
resetlocale()
if os.name == 'nt':
handler = logging.handlers.NTEventLogHandler("%s %s" % (release.description, release.version))
else:
- handler = logging.handlers.SysLogHandler()
+ handler = logging.handlers.SysLogHandler('/dev/log')
format = '%s %s' % (release.description, release.version) \
+ ':%(dbname)s:%(levelname)s:%(name)s:%(message)s'
# LogFile Handler
logf = tools.config['logfile']
try:
- # We check we have the right location for the log files
dirname = os.path.dirname(logf)
if dirname and not os.path.isdir(dirname):
os.makedirs(dirname)
if tools.config['logrotate'] is not False:
- handler = logging.handlers.TimedRotatingFileHandler(filename=logf, when='D', interval=1, backupCount=30)
+ handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
elif os.name == 'posix':
handler = logging.handlers.WatchedFileHandler(logf)
else:
# behind Apache with mod_wsgi, handler.stream will have type mod_wsgi.Log,
# which has no fileno() method. (mod_wsgi.Log is what is being bound to
# sys.stderr when the logging.StreamHandler is being constructed above.)
- def is_a_tty(stream):
- return hasattr(stream, 'fileno') and os.isatty(stream.fileno())
-
- if isinstance(handler, logging.StreamHandler) and is_a_tty(handler.stream):
+ if isinstance(handler, logging.StreamHandler) \
+ and hasattr(handler.stream, 'fileno') \
+ and os.isatty(handler.stream.fileno()):
formatter = ColoredFormatter(format)
else:
formatter = DBFormatter(format)
handler.setFormatter(formatter)
- logging.getLogger().addHandler(handler)
-
- if tools.config['log_db']:
- postgresqlHandler = PostgreSQLHandler()
- postgresqlHandler.setLevel(logging.WARNING)
- logging.getLogger().addHandler(postgresqlHandler)
-
- # Configure loggers levels
+ # Configure handlers
pseudo_config = PSEUDOCONFIG_MAPPER.get(tools.config['log_level'], [])
logconfig = tools.config['log_handler']
loggername, level = logconfig_item.split(':')
level = getattr(logging, level, logging.INFO)
logger = logging.getLogger(loggername)
+ logger.handlers = []
logger.setLevel(level)
+ logger.addHandler(handler)
+ if loggername != '':
+ logger.propagate = False
for logconfig_item in logging_configurations:
_logger.debug('logger level set: "%s"', logconfig_item)
DEFAULT_LOG_CONFIGURATION = [
'openerp.workflow.workitem:WARNING',
- 'openerp.http.rpc.request:INFO',
- 'openerp.http.rpc.response:INFO',
+ 'openerp.netsvc.rpc.request:INFO',
+ 'openerp.netsvc.rpc.response:INFO',
'openerp.addons.web.http:INFO',
'openerp.sql_db:INFO',
':INFO',
]
PSEUDOCONFIG_MAPPER = {
- 'debug_rpc_answer': ['openerp:DEBUG','openerp.http.rpc.request:DEBUG', 'openerp.http.rpc.response:DEBUG'],
- 'debug_rpc': ['openerp:DEBUG','openerp.http.rpc.request:DEBUG'],
+ 'debug_rpc_answer': ['openerp:DEBUG','openerp.netsvc.rpc.request:DEBUG', 'openerp.netsvc.rpc.response:DEBUG'],
+ 'debug_rpc': ['openerp:DEBUG','openerp.netsvc.rpc.request:DEBUG'],
'debug': ['openerp:DEBUG'],
'debug_sql': ['openerp.sql_db:DEBUG'],
'info': [],
'critical': ['openerp:CRITICAL'],
}
+# A alternative logging scheme for automated runs of the
+# server intended to test it.
+def init_alternative_logger():
+ class H(logging.Handler):
+ def emit(self, record):
+ if record.levelno > 20:
+ print record.levelno, record.pathname, record.msg
+ handler = H()
+ # Add the handler to the 'openerp' logger.
+ logger = logging.getLogger('openerp')
+ logger.addHandler(handler)
+ logger.setLevel(logging.ERROR)
+
+def replace_request_password(args):
+ # password is always 3rd argument in a request, we replace it in RPC logs
+ # so it's easier to forward logs for diagnostics/debugging purposes...
+ if len(args) > 2:
+ args = list(args)
+ args[2] = '*'
+ return tuple(args)
+
+def log(logger, level, prefix, msg, depth=None):
+ indent=''
+ indent_after=' '*len(prefix)
+ for line in (prefix+pformat(msg, depth=depth)).split('\n'):
+ logger.log(level, indent+line)
+ indent=indent_after
+
+def dispatch_rpc(service_name, method, params):
+ """ Handle a RPC call.
+
+ This is pure Python code, the actual marshalling (from/to XML-RPC) is done
+ in a upper layer.
+ """
+ try:
+ rpc_request = logging.getLogger(__name__ + '.rpc.request')
+ rpc_response = logging.getLogger(__name__ + '.rpc.response')
+ rpc_request_flag = rpc_request.isEnabledFor(logging.DEBUG)
+ rpc_response_flag = rpc_response.isEnabledFor(logging.DEBUG)
+ if rpc_request_flag or rpc_response_flag:
+ start_time = time.time()
+ start_rss, start_vms = 0, 0
+ start_rss, start_vms = psutil.Process(os.getpid()).get_memory_info()
+ if rpc_request and rpc_response_flag:
+ log(rpc_request,logging.DEBUG,'%s.%s'%(service_name,method), replace_request_password(params))
+
+ threading.current_thread().uid = None
+ threading.current_thread().dbname = None
+ if service_name == 'common':
+ dispatch = openerp.service.common.dispatch
+ elif service_name == 'db':
+ dispatch = openerp.service.db.dispatch
+ elif service_name == 'object':
+ dispatch = openerp.service.model.dispatch
+ elif service_name == 'report':
+ dispatch = openerp.service.report.dispatch
+ else:
+ dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name)
+ result = dispatch(method, params)
+
+ if rpc_request_flag or rpc_response_flag:
+ end_time = time.time()
+ end_rss, end_vms = 0, 0
+ end_rss, end_vms = psutil.Process(os.getpid()).get_memory_info()
+ logline = '%s.%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % (service_name, method, end_time - start_time, start_vms / 1024, end_vms / 1024, (end_vms - start_vms)/1024)
+ if rpc_response_flag:
+ log(rpc_response,logging.DEBUG, logline, result)
+ else:
+ log(rpc_request,logging.DEBUG, logline, replace_request_password(params), depth=1)
+
+ return result
+ except openerp.osv.orm.except_orm:
+ raise
+ except openerp.exceptions.AccessError:
+ raise
+ except openerp.exceptions.AccessDenied:
+ raise
+ except openerp.exceptions.Warning:
+ raise
+ except openerp.exceptions.RedirectWarning:
+ raise
+ except openerp.exceptions.DeferredException, e:
+ _logger.exception(tools.exception_to_unicode(e))
+ post_mortem(e.traceback)
+ raise
+ except Exception, e:
+ _logger.exception(tools.exception_to_unicode(e))
+ post_mortem(sys.exc_info())
+ raise
+
+def post_mortem(info):
+ if tools.config['debug_mode'] and isinstance(info[2], types.TracebackType):
+ import pdb
+ pdb.post_mortem(info[2])
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class text(_column):
_type = 'text'
-
class html(text):
_type = 'html'
_symbol_c = '%s'
-
- def _symbol_set_html(self, value):
- if value is None or value is False:
+ def _symbol_f(x):
+ if x is None or x == False:
return None
- if not self._sanitize:
- return value
- return html_sanitize(value)
-
- def __init__(self, string='unknown', sanitize=True, **args):
- super(html, self).__init__(string=string, **args)
- self._sanitize = sanitize
- # symbol_set redefinition because of sanitize specific behavior
- self._symbol_f = self._symbol_set_html
- self._symbol_set = (self._symbol_c, self._symbol_f)
+ return html_sanitize(x)
+
+ _symbol_set = (_symbol_c, _symbol_f)
import __builtin__
# List of etree._Element subclasses that we choose to ignore when parsing XML.
from openerp.tools import SKIPPED_ELEMENT_TYPES
-regex_order = re.compile('^( *([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
+regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
regex_object_name = re.compile(r'^[a-z0-9_.]+$')
AUTOINIT_RECALCULATE_STORED_FIELDS = 1000
def _get_xml_id(self, cr, uid, r):
model_data = self.pool.get('ir.model.data')
- data_ids = model_data.search(cr, uid, [('model', '=', r._model._name), ('res_id', '=', r['id'])])
+ data_ids = model_data.search(cr, uid, [('model', '=', r._table_name), ('res_id', '=', r['id'])])
if len(data_ids):
d = model_data.read(cr, uid, data_ids, ['name', 'module'])[0]
if d['module']:
else:
postfix = 0
while True:
- n = r._model._table+'_'+str(r['id']) + (postfix and ('_'+str(postfix)) or '' )
+ n = self._table+'_'+str(r['id']) + (postfix and ('_'+str(postfix)) or '' )
if not model_data.search(cr, uid, [('name', '=', n)]):
break
postfix += 1
model_data.create(cr, SUPERUSER_ID, {
'name': n,
- 'model': r._model._name,
+ 'model': self._name,
'res_id': r['id'],
'module': '__export__',
})
r['__fold'] = folded.get(r[groupby] and r[groupby][0], False)
return result
- def _read_group_prepare(self, orderby, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type=None):
+ def _read_group_generate_order_by(self, orderby, aggregated_fields, groupby, query):
"""
- Prepares the GROUP BY and ORDER BY terms for the read_group method. Adds the missing JOIN clause
+ Generates the ORDER BY sql clause for the read group method. Adds the missing JOIN clause
to the query if order should be computed against m2o field.
:param orderby: the orderby definition in the form "%(field)s %(order)s"
:param aggregated_fields: list of aggregated fields in the query
:param groupby: the current groupby field name
- :param qualified_groupby_field: the fully qualified SQL name for the grouped field
- :param osv.Query query: the query under construction
- :param groupby_type: the type of the grouped field
- :return: (groupby_terms, orderby_terms)
+ :param query: the query object used to construct the query afterwards
"""
- orderby_terms = []
- groupby_terms = [qualified_groupby_field] if groupby else []
- if not orderby:
- return groupby_terms, orderby_terms
-
- self._check_qorder(orderby)
- for order_part in orderby.split(','):
- order_split = order_part.split()
- order_field = order_split[0]
- if order_field == groupby:
- if groupby_type == 'many2one':
- order_clause = self._generate_order_by(order_part, query).replace('ORDER BY ', '')
- if order_clause:
- orderby_terms.append(order_clause)
- groupby_terms += [order_term.split()[0] for order_term in order_clause.split(',')]
- else:
- orderby_terms.append(order_part)
- elif order_field in aggregated_fields:
- orderby_terms.append(order_part)
- else:
- # Cannot order by a field that will not appear in the results (needs to be grouped or aggregated)
- _logger.warn('%s: read_group order by `%s` ignored, cannot sort on empty columns (not grouped/aggregated)',
- self._name, order_part)
- return groupby_terms, orderby_terms
+ orderby_list = []
+ ob = []
+ for order_splits in orderby.split(','):
+ order_split = order_splits.split()
+ orderby_field = order_split[0]
+ fields = openerp.osv.fields
+ if isinstance(self._all_columns[orderby_field].column, (fields.date, fields.datetime)):
+ continue
+ orderby_dir = len(order_split) == 2 and order_split[1].upper() == 'ASC' and 'ASC' or 'DESC'
+ if orderby_field == groupby:
+ orderby_item = self._generate_order_by(order_splits, query).replace('ORDER BY ', '')
+ if orderby_item:
+ orderby_list.append(orderby_item)
+ ob += [obi.split()[0] for obi in orderby_item.split(',')]
+ elif orderby_field in aggregated_fields:
+ orderby_list.append('%s %s' % (orderby_field,orderby_dir))
+
+ if orderby_list:
+ return ' ORDER BY %s' % (','.join(orderby_list)), ob and ','.join(ob) or ''
+ else:
+ return '', ''
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
"""
# TODO it seems fields_get can be replaced by _all_columns (no need for translation)
fget = self.fields_get(cr, uid, fields)
+ flist = ''
+ group_count = group_by = groupby
group_by_params = {}
- select_terms = []
- groupby_type = None
if groupby:
if fget.get(groupby):
groupby_type = fget[groupby]['type']
timezone = context.get('tz', 'UTC')
qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field)
qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field)
+ flist = "%s as %s " % (qualified_groupby_field, groupby)
elif groupby_type == 'boolean':
qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field
- select_terms.append("%s as %s " % (qualified_groupby_field, groupby))
+ flist = "%s as %s " % (qualified_groupby_field, groupby)
+ else:
+ flist = qualified_groupby_field
else:
# Don't allow arbitrary values, as this would be a SQL injection vector!
raise except_orm(_('Invalid group_by'),
aggregated_fields = [
f for f in fields
- if f not in ('id', 'sequence', groupby)
+ if f not in ('id', 'sequence')
if fget[f]['type'] in ('integer', 'float')
if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))]
for f in aggregated_fields:
group_operator = fget[f].get('group_operator', 'sum')
+ if flist:
+ flist += ', '
qualified_field = self._inherits_join_calc(f, query)
- select_terms.append("%s(%s) AS %s" % (group_operator, qualified_field, f))
+ flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
+
+ order = orderby or groupby
+ orderby_clause = ''
+ ob = ''
+ if order:
+ orderby_clause, ob = self._read_group_generate_order_by(order, aggregated_fields, groupby, query)
- order = orderby or groupby or ''
- groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type)
+ gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
from_clause, where_clause, where_clause_params = query.get_sql()
+ where_clause = where_clause and ' WHERE ' + where_clause
+ limit_str = limit and ' limit %d' % limit or ''
+ offset_str = offset and ' offset %d' % offset or ''
if len(groupby_list) < 2 and context.get('group_by_no_leaf'):
- count_field = '_'
- else:
- count_field = groupby
-
- prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else ''
- prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else ''
-
- query = """
- SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count
- %(extra_fields)s
- FROM %(from)s
- %(where)s
- %(groupby)s
- %(orderby)s
- %(limit)s
- %(offset)s
- """ % {
- 'table': self._table,
- 'count_field': count_field,
- 'extra_fields': prefix_terms(',', select_terms),
- 'from': from_clause,
- 'where': prefix_term('WHERE', where_clause),
- 'groupby': prefix_terms('GROUP BY', groupby_terms),
- 'orderby': prefix_terms('ORDER BY', orderby_terms),
- 'limit': prefix_term('LIMIT', int(limit) if limit else None),
- 'offset': prefix_term('OFFSET', int(offset) if limit else None),
- }
- cr.execute(query, where_clause_params)
+ group_count = '_'
+ cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + (ob and ',') + ob + orderby_clause + limit_str + offset_str, where_clause_params)
alldata = {}
+ groupby = group_by
+
fetched_data = cr.dictfetchall()
data_ids = []
data_ids.append(r['id'])
del r['id']
+
+
if groupby:
data = self.read(cr, uid, data_ids, [groupby], context=context)
# restore order of the search as read() uses the default _order (this is only for groups, so the footprint of data should be small):
msg = "Table '%s': dropping index for column '%s' of type '%s' as it is not required anymore"
_schema.debug(msg, self._table, k, f._type)
- if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
+ if isinstance(f, fields.many2one):
dest_model = self.pool[f._obj]
if dest_model._table != 'ir_actions':
self._m2o_fix_foreign_key(cr, self._table, k, dest_model, f.ondelete)
todo_end.append((order, self._update_store, (f, k)))
# and add constraints if needed
- if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
+ if isinstance(f, fields.many2one):
if f._obj not in self.pool:
raise except_orm('Programming Error', 'There is no reference available for %s' % (f._obj,))
dest_model = self.pool[f._obj]
# (6,1,0,'candidate',2) < (6,1,0,'final',0) < (6,1,2,'final',0)
version_info = (8, 0, 0, ALPHA, 1)
version = '.'.join(map(str, version_info[:2])) + RELEASE_LEVELS_DISPLAY[version_info[3]] + str(version_info[4] or '')
-series = serie = major_version = '.'.join(map(str, version_info[:2]))
+serie = major_version = '.'.join(map(str, version_info[:2]))
description = 'OpenERP Server'
long_desc = '''OpenERP is a complete ERP and CRM. The main features are accounting (analytic
author_email = 'info@openerp.com'
license = 'AGPL-3'
-nt_service_name = "openerp-server-" + series
+nt_service_name = "openerp-server-" + serie
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# -*- coding: utf-8 -*-
-from contextlib import closing
-from functools import wraps
+
+import base64
+import contextlib
import logging
import os
-import shutil
import threading
import traceback
-import tempfile
-import zipfile
-
-import psycopg2
+from contextlib import contextmanager, closing
import openerp
from openerp import SUPERUSER_ID
self_actions[id]['progress'] = 0
db = openerp.sql_db.db_connect(db_name)
with closing(db.cursor()) as cr:
- # TODO this should be removed as it is done by RegistryManager.new().
- openerp.modules.db.initialize(cr)
+ openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by RegistryManager.new().
openerp.tools.config['lang'] = lang
cr.commit()
self_actions[id]['traceback'] = traceback.format_exc()
def dispatch(method, params):
- if method in ['create', 'get_progress', 'drop', 'dump', 'restore', 'rename',
- 'change_admin_password', 'migrate_databases',
- 'create_database', 'duplicate_database']:
+ if method in [ 'create', 'get_progress', 'drop', 'dump',
+ 'restore', 'rename',
+ 'change_admin_password', 'migrate_databases',
+ 'create_database', 'duplicate_database' ]:
passwd = params[0]
params = params[1:]
security.check_super(passwd)
- elif method in ['db_exist', 'list', 'list_lang', 'server_version']:
+ elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
# params = params
# No security check for these methods
pass
cr.execute("SELECT datname FROM pg_database WHERE datname = %s",
(name,))
if cr.fetchall():
- raise openerp.exceptions.Warning("database %r already exists!" % (name,))
+ raise openerp.exceptions.Warning(" %s database already exists!" % name )
else:
- cr.autocommit(True) # avoid transaction block
+ cr.autocommit(True) # avoid transaction block
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template))
def exp_create(db_name, demo, lang, user_password='admin'):
_logger.info('CREATE DATABASE %s', db_name.lower())
create_thread = threading.Thread(target=_initialize_db,
- args=(id, db_name, demo, lang, user_password))
+ args=(id, db_name, demo, lang, user_password))
create_thread.start()
self_actions[id]['thread'] = create_thread
return id
openerp.sql_db.close_db(db_original_name)
db = openerp.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
- cr.autocommit(True) # avoid transaction block
+ cr.autocommit(True) # avoid transaction block
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (db_name, db_original_name))
return True
def exp_get_progress(id):
if self_actions[id]['thread'].isAlive():
# return openerp.modules.init_progress[db_name]
- return min(self_actions[id].get('progress', 0), 0.95), []
+ return min(self_actions[id].get('progress', 0),0.95), []
else:
clean = self_actions[id]['clean']
if clean:
self_actions.pop(id)
return 1.0, users
else:
- a = self_actions.pop(id)
- exc, tb = a['exception'], a['traceback']
- raise Exception, exc, tb
+ e = self_actions[id]['exception'] # TODO this seems wrong: actions[id]['traceback'] is set, but not 'exception'.
+ self_actions.pop(id)
+ raise Exception, e
def exp_drop(db_name):
if db_name not in exp_list(True):
db = openerp.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
- cr.autocommit(True) # avoid transaction block
+ cr.autocommit(True) # avoid transaction block
# Try to terminate all other connections that might prevent
# dropping the database
try:
+
# PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
# http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
FROM pg_stat_activity
- WHERE datname = %%s AND
+ WHERE datname = %%s AND
%(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
(db_name,))
except Exception:
_logger.info('DROP DB: %s', db_name)
return True
-def _set_pg_password_in_environment(func):
+@contextlib.contextmanager
+def _set_pg_password_in_environment():
""" On systems where pg_restore/pg_dump require an explicit
password (i.e. when not connecting via unix sockets, and most
importantly on Windows), it is necessary to pass the PG user
password in the environment or in a special .pgpass file.
- This decorator handles setting
+ This context management method handles setting
:envvar:`PGPASSWORD` if it is not already
set, and removing it afterwards.
See also http://www.postgresql.org/docs/8.4/static/libpq-envars.html
-
+
.. note:: This is not thread-safe, and should never be enabled for
SaaS (giving SaaS users the super-admin password is not a good idea
anyway)
"""
- @wraps(func)
- def wrapper(*args, **kwargs):
- if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
- return func(*args, **kwargs)
- else:
- os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
- try:
- return func(*args, **kwargs)
- finally:
- del os.environ['PGPASSWORD']
- return wrapper
+ if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
+ yield
+ else:
+ os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
+ try:
+ yield
+ finally:
+ del os.environ['PGPASSWORD']
+
def exp_dump(db_name):
- with tempfile.TemporaryFile() as t:
- dump_db(db_name, t)
- t.seek(0)
- return t.read().encode('base64')
-
-@_set_pg_password_in_environment
-def dump_db(db, stream):
- """Dump database `db` into file-like object `stream`"""
- with openerp.tools.osutil.tempdir() as dump_dir:
- registry = openerp.modules.registry.RegistryManager.get(db)
- with registry.cursor() as cr:
- filestore = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
- if os.path.exists(filestore):
- shutil.copytree(filestore, os.path.join(dump_dir, 'filestore'))
-
- dump_file = os.path.join(dump_dir, 'dump.sql')
- cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file]
+ with _set_pg_password_in_environment():
+ cmd = ['pg_dump', '--format=c', '--no-owner']
if openerp.tools.config['db_user']:
cmd.append('--username=' + openerp.tools.config['db_user'])
if openerp.tools.config['db_host']:
cmd.append('--host=' + openerp.tools.config['db_host'])
if openerp.tools.config['db_port']:
cmd.append('--port=' + str(openerp.tools.config['db_port']))
- cmd.append(db)
-
- if openerp.tools.exec_pg_command(*cmd):
- _logger.error('DUMP DB: %s failed! Please verify the configuration of the database '
- 'password on the server. You may need to create a .pgpass file for '
- 'authentication, or specify `db_password` in the server configuration '
- 'file.', db)
- raise Exception("Couldn't dump database")
-
- openerp.tools.osutil.zip_dir(dump_dir, stream, include_dir=False)
-
- _logger.info('DUMP DB successful: %s', db)
+ cmd.append(db_name)
-def exp_restore(db_name, data, copy=False):
- data_file = tempfile.NamedTemporaryFile(delete=False)
- try:
- data_file.write(data.decode('base64'))
- data_file.close()
- restore_db(db_name, data_file.name, copy=copy)
- finally:
- os.unlink(data_file.name)
- return True
-
-@_set_pg_password_in_environment
-def restore_db(db, dump_file, copy=False):
- assert isinstance(db, basestring)
- if exp_db_exist(db):
- _logger.warning('RESTORE DB: %s already exists', db)
- raise Exception("Database already exists")
+ stdin, stdout = openerp.tools.exec_pg_command_pipe(*tuple(cmd))
+ stdin.close()
+ data = stdout.read()
+ res = stdout.close()
- _create_empty_database(db)
+ if not data or res:
+ _logger.error(
+ 'DUMP DB: %s failed! Please verify the configuration of the database password on the server. '
+ 'You may need to create a .pgpass file for authentication, or specify `db_password` in the '
+ 'server configuration file.\n %s', db_name, data)
+ raise Exception, "Couldn't dump database"
+ _logger.info('DUMP DB successful: %s', db_name)
- filestore_path = None
- with openerp.tools.osutil.tempdir() as dump_dir:
- if zipfile.is_zipfile(dump_file):
- # v8 format
- with zipfile.ZipFile(dump_file, 'r') as z:
- # only extract known members!
- filestore = [m for m in z.namelist() if m.startswith('filestore/')]
- z.extractall(dump_dir, ['dump.sql'] + filestore)
+ return base64.encodestring(data)
- if filestore:
- filestore_path = os.path.join(dump_dir, 'filestore')
+def exp_restore(db_name, data):
+ with _set_pg_password_in_environment():
+ if exp_db_exist(db_name):
+ _logger.warning('RESTORE DB: %s already exists', db_name)
+ raise Exception, "Database already exists"
- pg_cmd = 'psql'
- pg_args = ['-q', '-f', os.path.join(dump_dir, 'dump.sql')]
+ _create_empty_database(db_name)
- else:
- # <= 7.0 format (raw pg_dump output)
- pg_cmd = 'pg_restore'
- pg_args = ['--no-owner', dump_file]
-
- args = []
+ cmd = ['pg_restore', '--no-owner']
if openerp.tools.config['db_user']:
- args.append('--username=' + openerp.tools.config['db_user'])
+ cmd.append('--username=' + openerp.tools.config['db_user'])
if openerp.tools.config['db_host']:
- args.append('--host=' + openerp.tools.config['db_host'])
+ cmd.append('--host=' + openerp.tools.config['db_host'])
if openerp.tools.config['db_port']:
- args.append('--port=' + str(openerp.tools.config['db_port']))
- args.append('--dbname=' + db)
- pg_args = args + pg_args
-
- if openerp.tools.exec_pg_command(pg_cmd, *pg_args):
- raise Exception("Couldn't restore database")
-
- registry = openerp.modules.registry.RegistryManager.new(db)
- with registry.cursor() as cr:
- if copy:
- # if it's a copy of a database, force generation of a new dbuuid
- registry['ir.config_parameter'].init(cr, force=True)
- if filestore_path:
- filestore_dest = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
- shutil.move(filestore_path, filestore_dest)
-
- if openerp.tools.config['unaccent']:
- try:
- with cr.savepoint():
- cr.execute("CREATE EXTENSION unaccent")
- except psycopg2.Error:
- pass
-
- _logger.info('RESTORE DB: %s', db)
+ cmd.append('--port=' + str(openerp.tools.config['db_port']))
+ cmd.append('--dbname=' + db_name)
+ args2 = tuple(cmd)
+
+ buf=base64.decodestring(data)
+ if os.name == "nt":
+ tmpfile = (os.environ['TMP'] or 'C:\\') + os.tmpnam()
+ file(tmpfile, 'wb').write(buf)
+ args2=list(args2)
+ args2.append(tmpfile)
+ args2=tuple(args2)
+ stdin, stdout = openerp.tools.exec_pg_command_pipe(*args2)
+ if not os.name == "nt":
+ stdin.write(base64.decodestring(data))
+ stdin.close()
+ res = stdout.close()
+ if res:
+ raise Exception, "Couldn't restore database"
+ _logger.info('RESTORE DB: %s', db_name)
+
+ return True
def exp_rename(old_name, new_name):
openerp.modules.registry.RegistryManager.delete(old_name)
db = openerp.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
- cr.autocommit(True) # avoid transaction block
+ cr.autocommit(True) # avoid transaction block
try:
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
- _logger.info('RENAME DB: %s -> %s', old_name, new_name)
except Exception, e:
_logger.error('RENAME DB: %s -> %s failed:\n%s', old_name, new_name, e)
raise Exception("Couldn't rename database %s to %s: %s" % (old_name, new_name, e))
+ else:
+ fs = os.path.join(openerp.tools.config['root_path'], 'filestore')
+ if os.path.exists(os.path.join(fs, old_name)):
+ os.rename(os.path.join(fs, old_name), os.path.join(fs, new_name))
+
+ _logger.info('RENAME DB: %s -> %s', old_name, new_name)
return True
-@openerp.tools.mute_logger('openerp.sql_db')
def exp_db_exist(db_name):
## Not True: in fact, check if connection to database is possible. The database may exists
return bool(openerp.sql_db.db_connect(db_name))
import platform
import psutil
import random
-if os.name == 'posix':
- import resource
-else:
- resource = None
+import resource
import select
import signal
import socket
self.handler = EventHandler(self)
self.notifier = pyinotify.Notifier(self.wm, self.handler, timeout=0)
mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE # IN_MOVED_FROM, IN_MOVED_TO ?
- for path in openerp.modules.modules.ad_paths:
+ for path in openerp.tools.config.options["addons_path"].split(','):
_logger.info('Watching addons folder %s', path)
self.wm.add_watch(path, mask, rec=True)
def process_data(self, files):
xml_files = [i for i in files if i.endswith('.xml')]
+ addons_path = openerp.tools.config.options["addons_path"].split(',')
for i in xml_files:
- for path in openerp.modules.modules.ad_paths:
+ for path in addons_path:
if i.startswith(path):
# find out wich addons path the file belongs to
# and extract it's module name
_logger.info("Initiating shutdown")
_logger.info("Hit CTRL-C again or send a second signal to force the shutdown.")
- if self.httpd:
- self.httpd.shutdown()
- self.close_socket(self.httpd.socket)
+ self.httpd.shutdown()
+ self.close_socket(self.httpd.socket)
# Manually join() all threads before calling sys.exit() to allow a second signal
# to trigger _force_quit() in case some non-daemon threads won't exit cleanly.
raise
def process_limit(self):
- if resource is None:
- return
# If our parent changed sucide
if self.ppid != os.getppid():
_logger.info("Worker (%s) Parent changed", self.pid)
stream = openerp.modules.module.TestStream()
result = unittest2.TextTestRunner(verbosity=2, stream=stream).run(suite)
success = result.wasSuccessful()
- if hasattr(registry._assertion_report,'report_result'):
- registry._assertion_report.report_result(success)
+ registry._assertion_report.report_result(success)
if not success:
_logger.error('%s: at least one error occurred in a test', test_file)
# This also mimics SimpleXMLRPCDispatcher._marshaled_dispatch() for
# exception handling.
try:
- result = openerp.http.dispatch_rpc(service, method, params)
+ result = openerp.netsvc.dispatch_rpc(service, method, params)
response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False, encoding=None)
except Exception, e:
if string_faultcode:
def check(f):
@wraps(f)
def wrapper(self, *args, **kwargs):
- if self._closed:
+ if self.__closed:
msg = 'Unable to use a closed cursor.'
if self.__closer:
msg += ' It was closed at %s, line %s' % self.__closer
self.sql_log = _logger.isEnabledFor(logging.DEBUG)
self.sql_log_count = 0
- self._closed = True # avoid the call of close() (by __del__) if an exception
+ self.__closed = True # avoid the call of close() (by __del__) if an exception
# is raised by any of the following initialisations
self._pool = pool
self.dbname = dbname
self.__caller = frame_codeinfo(currentframe(),2)
else:
self.__caller = False
- self._closed = False # real initialisation value
+ self.__closed = False # real initialisation value
self.autocommit(False)
self.__closer = False
self.cache = {}
def __del__(self):
- if not self._closed and not self._cnx.closed:
+ if not self.__closed and not self._cnx.closed:
# Oops. 'self' has not been closed explicitly.
# The cursor will be deleted by the garbage collector,
# but the database connection is not put back into the connection
# collected as fast as they should). The problem is probably due in
# part because browse records keep a reference to the cursor.
del self._obj
- self._closed = True
+ self.__closed = True
# Clean the underlying connection.
self._cnx.rollback()
import threading
import time
import unittest2
-import urllib2
import xmlrpclib
-from datetime import datetime, timedelta
-
-import werkzeug
import openerp
cr._test_lock.acquire()
return cr
-def release_test_cursor(cr):
+def release_test_cursor(session_id):
if openerp.tools.config['test_enable']:
- if hasattr(cr, '_test_lock'):
+ cr = HTTP_SESSION.get(session_id)
+ if cr:
cr._test_lock.release()
return True
return False
class HttpCase(TransactionCase):
- """ Transactionnal HTTP TestCase with url_open and phantomjs helpers.
+ """ Transactionnal HTTP TestCase with a phantomjs helper.
"""
def __init__(self, methodName='runTest'):
self.cr._test_lock = threading.RLock()
HTTP_SESSION[self.session_id] = self.cr
+
def tearDown(self):
del HTTP_SESSION[self.session_id]
super(HttpCase, self).tearDown()
- def url_open(self, url, data=None, timeout=10):
- opener = urllib2.build_opener()
- opener.addheaders.append(('Cookie', 'session_id=%s' % self.session_id))
- if url.startswith('/'):
- url = "http://localhost:%s%s" % (PORT, url)
- return opener.open(url, data, timeout)
-
def phantom_poll(self, phantom, timeout):
""" Phantomjs Test protocol.
Other lines are relayed to the test log.
"""
- t0 = datetime.now()
- td = timedelta(seconds=timeout)
+ t0 = time.time()
buf = bytearray()
while True:
# timeout
- self.assertLess(datetime.now() - t0, td,
+ self.assertLess(time.time(), t0 + timeout,
"PhantomJS tests should take less than %s seconds" % timeout)
# read a byte
# OSError, and no errno/strerror/filename, only a pair of
# unnamed arguments (matching errno and strerror)
err, _ = e.args
- if err == errno.EINTR:
- continue
+ if err == errno.EINTR: continue
raise
if ready:
# process lines
if '\n' in buf:
line, buf = buf.split('\n', 1)
- line = str(line)
-
- # relay everything from console.log, even 'ok' or 'error...' lines
- _logger.info("phantomjs: %s", line)
+ line = str(line)
+ if 'CoreText' in line:
+ continue
if line == "ok":
break
if line.startswith("error"):
line_ = line[6:]
- # when error occurs the execution stack may be sent as as JSON
- try:
- line_ = json.loads(line_)
- except ValueError:
- pass
+ try: line_ = json.loads(line_)
+ except ValueError: pass
self.fail(line_ or "phantomjs test failed")
+ try: line = json.loads(line)
+ except ValueError: pass
+ _logger.info("phantomjs: %s", line)
+
def phantom_run(self, cmd, timeout):
- _logger.info('phantom_run executing %s', ' '.join(cmd))
+ _logger.debug('executing `%s`', ' '.join(cmd))
try:
phantom = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
# kill phantomjs if phantom.exit() wasn't called in the test
if phantom.poll() is None:
phantom.terminate()
- _logger.info("phantom_run execution finished")
def phantom_jsfile(self, jsfile, timeout=30, **kw):
options = {
function waitFor (ready, callback, timeout, timeoutMessageCallback) {
timeout = timeout || 10000;
- var start = new Date;
-
- (function waitLoop() {
- if(new Date - start > timeout) {
- error(timeoutMessageCallback ? timeoutMessageCallback() : "Timeout after "+timeout+" ms");
- } else if (ready()) {
- callback();
+ var start = new Date().getTime();
+ var condition = ready();
+ var interval = setInterval(function() {
+ if ((new Date().getTime() - start < timeout) && !condition ) {
+ condition = ready();
} else {
- setTimeout(waitLoop, 250);
+ if(!condition) {
+ var message = timeoutMessageCallback ? timeoutMessageCallback() : "Timeout after "+timeout+" ms";
+ console.log("Waiting for " + ready);
+ error(message);
+ } else {
+ clearInterval(interval);
+ callback();
+ }
}
- }());
+ }, 250);
}
function error(message) {
// ----------------------------------------------------
this.run = function(url_path, code, ready) {
if(self.options.login) {
- var qp = [];
+ qp = [];
qp.push('db=' + self.options.db);
qp.push('login=' + self.options.login);
qp.push('key=' + self.options.password);
qp.push('redirect=' + encodeURIComponent(url_path));
- url_path = "/login?" + qp.join('&');
+ var url_path = "/login?" + qp.join('&');
}
var url = self.origin + url_path;
self.page.open(url, function(status) {
console.log('loaded', url, status);
// process ready
waitFor(function() {
- console.log("PhantomTest.run: wait for condition: " + ready);
- return self.page.evaluate(function (ready) {
+ return self.page.evaluate(function (ready) {
var r = false;
try {
- console.log("page.evaluate eval expr:", ready);
r = !!eval(ready);
- } catch(ex) {
+ } catch(ex) {
+ console.log("waiting for " + ready);
}
- console.log("page.evaluate eval result:", r);
return r;
}, ready);
// run test
}, function() {
- console.log("PhantomTest.run: condition statified, executing: " + code);
self.page.evaluate(function (code) { return eval(code); }, code);
- console.log("PhantomTest.run: execution launched, waiting for console.log('ok')...");
});
}
});
import copy
import win32
-import appdirs
from config import config
from misc import *
from convert import *
from sql import *
from float_utils import *
from mail import *
-from debugger import *
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2005-2010 ActiveState Software Inc.
-# Copyright (c) 2013 Eddy Petrișor
-
-"""Utilities for determining application-specific dirs.
-
-See <http://github.com/ActiveState/appdirs> for details and usage.
-"""
-# Dev Notes:
-# - MSDN on where to store app data files:
-# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
-# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
-# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
-
-__version_info__ = (1, 3, 0)
-__version__ = '.'.join(map(str, __version_info__))
-
-
-import sys
-import os
-
-PY3 = sys.version_info[0] == 3
-
-if PY3:
- unicode = str
-
-
-
-def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
- r"""Return full path to the user-specific data dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "roaming" (boolean, default False) can be set True to use the Windows
- roaming appdata directory. That means that for users on a Windows
- network setup for roaming profiles, this user data will be
- sync'd on login. See
- <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
- for a discussion of issues.
-
- Typical user data directories are:
- Mac OS X: ~/Library/Application Support/<AppName>
- Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined
- Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
- Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>
- Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>
- Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName>
-
- For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
- That means, by deafult "~/.local/share/<AppName>".
- """
- if sys.platform == "win32":
- if appauthor is None:
- appauthor = appname
- const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
- path = os.path.normpath(_get_win_folder(const))
- if appname:
- path = os.path.join(path, appauthor, appname)
- elif sys.platform == 'darwin':
- path = os.path.expanduser('~/Library/Application Support/')
- if appname:
- path = os.path.join(path, appname)
- else:
- path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
- if appname:
- path = os.path.join(path, appname)
- if appname and version:
- path = os.path.join(path, version)
- return path
-
-
-def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
- """Return full path to the user-shared data dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "multipath" is an optional parameter only applicable to *nix
- which indicates that the entire list of data dirs should be
- returned. By default, the first item from XDG_DATA_DIRS is
- returned, or '/usr/local/share/<AppName>',
- if XDG_DATA_DIRS is not set
-
- Typical user data directories are:
- Mac OS X: /Library/Application Support/<AppName>
- Unix: /usr/local/share/<AppName> or /usr/share/<AppName>
- Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName>
- Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
- Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7.
-
- For Unix, this is using the $XDG_DATA_DIRS[0] default.
-
- WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
- """
- if sys.platform == "win32":
- if appauthor is None:
- appauthor = appname
- path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
- if appname:
- path = os.path.join(path, appauthor, appname)
- elif sys.platform == 'darwin':
- path = os.path.expanduser('/Library/Application Support')
- if appname:
- path = os.path.join(path, appname)
- else:
- # XDG default for $XDG_DATA_DIRS
- # only first, if multipath is False
- path = os.getenv('XDG_DATA_DIRS',
- os.pathsep.join(['/usr/local/share', '/usr/share']))
- pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
- if appname:
- if version:
- appname = os.path.join(appname, version)
- pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
-
- if multipath:
- path = os.pathsep.join(pathlist)
- else:
- path = pathlist[0]
- return path
-
- if appname and version:
- path = os.path.join(path, version)
- return path
-
-
-def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
- r"""Return full path to the user-specific config dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "roaming" (boolean, default False) can be set True to use the Windows
- roaming appdata directory. That means that for users on a Windows
- network setup for roaming profiles, this user data will be
- sync'd on login. See
- <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
- for a discussion of issues.
-
- Typical user data directories are:
- Mac OS X: same as user_data_dir
- Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined
- Win *: same as user_data_dir
-
- For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
- That means, by deafult "~/.local/share/<AppName>".
- """
- if sys.platform in [ "win32", "darwin" ]:
- path = user_data_dir(appname, appauthor, None, roaming)
- else:
- path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
- if appname:
- path = os.path.join(path, appname)
- if appname and version:
- path = os.path.join(path, version)
- return path
-
-
-def site_config_dir(appname=None, appauthor=None, version=None, multipath=False):
- """Return full path to the user-shared data dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "multipath" is an optional parameter only applicable to *nix
- which indicates that the entire list of config dirs should be
- returned. By default, the first item from XDG_CONFIG_DIRS is
- returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set
-
- Typical user data directories are:
- Mac OS X: same as site_data_dir
- Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in
- $XDG_CONFIG_DIRS
- Win *: same as site_data_dir
- Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
-
- For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False
-
- WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
- """
- if sys.platform in [ "win32", "darwin" ]:
- path = site_data_dir(appname, appauthor)
- if appname and version:
- path = os.path.join(path, version)
- else:
- # XDG default for $XDG_CONFIG_DIRS
- # only first, if multipath is False
- path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
- pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
- if appname:
- if version:
- appname = os.path.join(appname, version)
- pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
-
- if multipath:
- path = os.pathsep.join(pathlist)
- else:
- path = pathlist[0]
- return path
-
-def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
- r"""Return full path to the user-specific cache dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "opinion" (boolean) can be False to disable the appending of
- "Cache" to the base app data dir for Windows. See
- discussion below.
-
- Typical user cache directories are:
- Mac OS X: ~/Library/Caches/<AppName>
- Unix: ~/.cache/<AppName> (XDG default)
- Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache
- Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache
-
- On Windows the only suggestion in the MSDN docs is that local settings go in
- the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming
- app data dir (the default returned by `user_data_dir` above). Apps typically
- put cache data somewhere *under* the given dir here. Some examples:
- ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
- ...\Acme\SuperApp\Cache\1.0
- OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
- This can be disabled with the `opinion=False` option.
- """
- if sys.platform == "win32":
- if appauthor is None:
- appauthor = appname
- path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
- if appname:
- path = os.path.join(path, appauthor, appname)
- if opinion:
- path = os.path.join(path, "Cache")
- elif sys.platform == 'darwin':
- path = os.path.expanduser('~/Library/Caches')
- if appname:
- path = os.path.join(path, appname)
- else:
- path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
- if appname:
- path = os.path.join(path, appname)
- if appname and version:
- path = os.path.join(path, version)
- return path
-
-def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
- r"""Return full path to the user-specific log dir for this application.
-
- "appname" is the name of application.
- If None, just the system directory is returned.
- "appauthor" (only required and used on Windows) is the name of the
- appauthor or distributing body for this application. Typically
- it is the owning company name. This falls back to appname.
- "version" is an optional version path element to append to the
- path. You might want to use this if you want multiple versions
- of your app to be able to run independently. If used, this
- would typically be "<major>.<minor>".
- Only applied when appname is present.
- "opinion" (boolean) can be False to disable the appending of
- "Logs" to the base app data dir for Windows, and "log" to the
- base cache dir for Unix. See discussion below.
-
- Typical user cache directories are:
- Mac OS X: ~/Library/Logs/<AppName>
- Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined
- Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs
- Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs
-
- On Windows the only suggestion in the MSDN docs is that local settings
- go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in
- examples of what some windows apps use for a logs dir.)
-
- OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA`
- value for Windows and appends "log" to the user cache dir for Unix.
- This can be disabled with the `opinion=False` option.
- """
- if sys.platform == "darwin":
- path = os.path.join(
- os.path.expanduser('~/Library/Logs'),
- appname)
- elif sys.platform == "win32":
- path = user_data_dir(appname, appauthor, version); version=False
- if opinion:
- path = os.path.join(path, "Logs")
- else:
- path = user_cache_dir(appname, appauthor, version); version=False
- if opinion:
- path = os.path.join(path, "log")
- if appname and version:
- path = os.path.join(path, version)
- return path
-
-
-class AppDirs(object):
- """Convenience wrapper for getting application dirs."""
- def __init__(self, appname, appauthor=None, version=None,
- roaming=False, multipath=False):
- self.appname = appname
- self.appauthor = appauthor
- self.version = version
- self.roaming = roaming
- self.multipath = multipath
- @property
- def user_data_dir(self):
- return user_data_dir(self.appname, self.appauthor,
- version=self.version, roaming=self.roaming)
- @property
- def site_data_dir(self):
- return site_data_dir(self.appname, self.appauthor,
- version=self.version, multipath=self.multipath)
- @property
- def user_config_dir(self):
- return user_config_dir(self.appname, self.appauthor,
- version=self.version, roaming=self.roaming)
- @property
- def site_config_dir(self):
- return site_data_dir(self.appname, self.appauthor,
- version=self.version, multipath=self.multipath)
- @property
- def user_cache_dir(self):
- return user_cache_dir(self.appname, self.appauthor,
- version=self.version)
- @property
- def user_log_dir(self):
- return user_log_dir(self.appname, self.appauthor,
- version=self.version)
-
-
-
-
-#---- internal support stuff
-
-def _get_win_folder_from_registry(csidl_name):
- """This is a fallback technique at best. I'm not sure if using the
- registry for this guarantees us the correct answer for all CSIDL_*
- names.
- """
- import _winreg
-
- shell_folder_name = {
- "CSIDL_APPDATA": "AppData",
- "CSIDL_COMMON_APPDATA": "Common AppData",
- "CSIDL_LOCAL_APPDATA": "Local AppData",
- }[csidl_name]
-
- key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
- r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
- dir, type = _winreg.QueryValueEx(key, shell_folder_name)
- return dir
-
-def _get_win_folder_with_pywin32(csidl_name):
- from win32com.shell import shellcon, shell
- dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
- # Try to make this a unicode path because SHGetFolderPath does
- # not return unicode strings when there is unicode data in the
- # path.
- try:
- dir = unicode(dir)
-
- # Downgrade to short path name if have highbit chars. See
- # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
- has_high_char = False
- for c in dir:
- if ord(c) > 255:
- has_high_char = True
- break
- if has_high_char:
- try:
- import win32api
- dir = win32api.GetShortPathName(dir)
- except ImportError:
- pass
- except UnicodeError:
- pass
- return dir
-
-def _get_win_folder_with_ctypes(csidl_name):
- import ctypes
-
- csidl_const = {
- "CSIDL_APPDATA": 26,
- "CSIDL_COMMON_APPDATA": 35,
- "CSIDL_LOCAL_APPDATA": 28,
- }[csidl_name]
-
- buf = ctypes.create_unicode_buffer(1024)
- ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
-
- # Downgrade to short path name if have highbit chars. See
- # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
- has_high_char = False
- for c in buf:
- if ord(c) > 255:
- has_high_char = True
- break
- if has_high_char:
- buf2 = ctypes.create_unicode_buffer(1024)
- if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
- buf = buf2
-
- return buf.value
-
-if sys.platform == "win32":
- try:
- import win32com.shell
- _get_win_folder = _get_win_folder_with_pywin32
- except ImportError:
- try:
- import ctypes
- _get_win_folder = _get_win_folder_with_ctypes
- except ImportError:
- _get_win_folder = _get_win_folder_from_registry
-
-
-
-#---- self test code
-
-if __name__ == "__main__":
- appname = "MyApp"
- appauthor = "MyCompany"
-
- props = ("user_data_dir", "site_data_dir",
- "user_config_dir", "site_config_dir",
- "user_cache_dir", "user_log_dir")
-
- print("-- app dirs (with optional 'version')")
- dirs = AppDirs(appname, appauthor, version="1.0")
- for prop in props:
- print("%s: %s" % (prop, getattr(dirs, prop)))
-
- print("\n-- app dirs (without optional 'version')")
- dirs = AppDirs(appname, appauthor)
- for prop in props:
- print("%s: %s" % (prop, getattr(dirs, prop)))
-
- print("\n-- app dirs (without optional 'appauthor')")
- dirs = AppDirs(appname)
- for prop in props:
- print("%s: %s" % (prop, getattr(dirs, prop)))
-
-#openerp.loggers.handlers. -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
import openerp.loglevels as loglevels
import logging
import openerp.release as release
-import appdirs
class MyOption (optparse.Option, object):
""" optparse Option with two additional attributes.
DEFAULT_LOG_HANDLER = [':INFO']
-def _get_default_datadir():
- return appdirs.user_data_dir(appname='OpenERP', appauthor=release.author)
-
class configmanager(object):
def __init__(self, fname=None):
# Options not exposed on the command line. Command line options will be added
}
# Not exposed in the configuration file.
- self.blacklist_for_save = set([
- 'publisher_warranty_url', 'load_language', 'root_path',
- 'init', 'save', 'config', 'update', 'stop_after_init'
- ])
+ self.blacklist_for_save = set(
+ ['publisher_warranty_url', 'load_language', 'root_path',
+ 'init', 'save', 'config', 'update', 'stop_after_init'])
# dictionary mapping option destination (keys in self.options) to MyOptions.
self.casts = {}
self.config_file = fname
self.has_ssl = check_ssl()
- self._LOGLEVELS = dict([
- (getattr(loglevels, 'LOG_%s' % x), getattr(logging, x))
- for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET')
- ])
+ self._LOGLEVELS = dict([(getattr(loglevels, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET')])
version = "%s %s" % (release.description, release.version)
self.parser = parser = optparse.OptionParser(version=version, option_class=MyOption)
help="specify additional addons paths (separated by commas).",
action="callback", callback=self._check_addons_path, nargs=1, type="string")
group.add_option("--load", dest="server_wide_modules", help="Comma-separated list of server-wide modules default=web")
-
- group.add_option("-D", "--data-dir", dest="data_dir", my_default=_get_default_datadir(),
- help="Directory where to store OpenERP data")
parser.add_option_group(group)
# XML-RPC / HTTP
group.add_option("--logrotate", dest="logrotate", action="store_true", my_default=False, help="enable logfile rotation")
group.add_option("--syslog", action="store_true", dest="syslog", my_default=False, help="Send the log to the syslog server")
group.add_option('--log-handler', action="append", default=DEFAULT_LOG_HANDLER, my_default=DEFAULT_LOG_HANDLER, metavar="PREFIX:LEVEL", help='setup a handler at LEVEL for a given PREFIX. An empty PREFIX indicates the root logger. This option can be repeated. Example: "openerp.orm:DEBUG" or "werkzeug:CRITICAL" (default: ":INFO")')
- group.add_option('--log-request', action="append_const", dest="log_handler", const="openerp.http.rpc.request:DEBUG", help='shortcut for --log-handler=openerp.http.rpc.request:DEBUG')
- group.add_option('--log-response', action="append_const", dest="log_handler", const="openerp.http.rpc.response:DEBUG", help='shortcut for --log-handler=openerp.http.rpc.response:DEBUG')
- group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.http:DEBUG", help='shortcut for --log-handler=openerp.http:DEBUG')
+ group.add_option('--log-request', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.request:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.request:DEBUG')
+ group.add_option('--log-response', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.response:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.response:DEBUG')
+ group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.addons.web.http:DEBUG", help='shortcut for --log-handler=openerp.addons.web.http:DEBUG')
group.add_option('--log-sql', action="append_const", dest="log_handler", const="openerp.sql_db:DEBUG", help='shortcut for --log-handler=openerp.sql_db:DEBUG')
- group.add_option('--log-db', dest='log_db', help="Logging database", my_default=False)
# For backward-compatibility, map the old log levels to something
# quite close.
- levels = [
- 'info', 'debug_rpc', 'warn', 'test', 'critical',
- 'debug_sql', 'error', 'debug', 'debug_rpc_answer', 'notset'
- ]
- group.add_option('--log-level', dest='log_level', type='choice',
- choices=levels, my_default='info',
- help='specify the level of the logging. Accepted values: %s (deprecated option).' % (levels,))
+ levels = ['info', 'debug_rpc', 'warn', 'test', 'critical',
+ 'debug_sql', 'error', 'debug', 'debug_rpc_answer', 'notset']
+ group.add_option('--log-level', dest='log_level', type='choice', choices=levels,
+ my_default='info', help='specify the level of the logging. Accepted values: ' + str(levels) + ' (deprecated option).')
parser.add_option_group(group)
# Advanced options
group = optparse.OptionGroup(parser, "Advanced options")
- if os.name == 'posix':
- group.add_option('--auto-reload', dest='auto_reload', action='store_true', my_default=False, help='enable auto reload')
+ group.add_option('--auto-reload', dest='auto_reload', action='store_true', my_default=False, help='enable auto reload')
group.add_option('--debug', dest='debug_mode', action='store_true', my_default=False, help='enable debug mode')
group.add_option("--stop-after-init", action="store_true", dest="stop_after_init", my_default=False,
help="stop the server after its initialization")
help="Use the unaccent function provided by the database when available.")
parser.add_option_group(group)
- if os.name == 'posix':
- group = optparse.OptionGroup(parser, "Multiprocessing options")
- # TODO sensible default for the three following limits.
- group.add_option("--workers", dest="workers", my_default=0,
- help="Specify the number of workers, 0 disable prefork mode.",
- type="int")
- group.add_option("--limit-memory-soft", dest="limit_memory_soft", my_default=2048 * 1024 * 1024,
- help="Maximum allowed virtual memory per worker, when reached the worker be reset after the current request (default 671088640 aka 640MB).",
- type="int")
- group.add_option("--limit-memory-hard", dest="limit_memory_hard", my_default=2560 * 1024 * 1024,
- help="Maximum allowed virtual memory per worker, when reached, any memory allocation will fail (default 805306368 aka 768MB).",
- type="int")
- group.add_option("--limit-time-cpu", dest="limit_time_cpu", my_default=60,
- help="Maximum allowed CPU time per request (default 60).",
- type="int")
- group.add_option("--limit-time-real", dest="limit_time_real", my_default=120,
- help="Maximum allowed Real time per request (default 120).",
- type="int")
- group.add_option("--limit-request", dest="limit_request", my_default=8192,
- help="Maximum number of request to be processed per worker (default 8192).",
- type="int")
- parser.add_option_group(group)
+ group = optparse.OptionGroup(parser, "Multiprocessing options")
+ # TODO sensible default for the three following limits.
+ group.add_option("--workers", dest="workers", my_default=0,
+ help="Specify the number of workers, 0 disable prefork mode.",
+ type="int")
+ group.add_option("--limit-memory-soft", dest="limit_memory_soft", my_default=2048 * 1024 * 1024,
+ help="Maximum allowed virtual memory per worker, when reached the worker be reset after the current request (default 671088640 aka 640MB).",
+ type="int")
+ group.add_option("--limit-memory-hard", dest="limit_memory_hard", my_default=2560 * 1024 * 1024,
+ help="Maximum allowed virtual memory per worker, when reached, any memory allocation will fail (default 805306368 aka 768MB).",
+ type="int")
+ group.add_option("--limit-time-cpu", dest="limit_time_cpu", my_default=60,
+ help="Maximum allowed CPU time per request (default 60).",
+ type="int")
+ group.add_option("--limit-time-real", dest="limit_time_real", my_default=120,
+ help="Maximum allowed Real time per request (default 120).",
+ type="int")
+ group.add_option("--limit-request", dest="limit_request", my_default=8192,
+ help="Maximum number of request to be processed per worker (default 8192).",
+ type="int")
+ parser.add_option_group(group)
# Copy all optparse options (i.e. MyOption) into self.options.
for group in parser.option_groups:
# (../etc from the server)
# if the server is run by an unprivileged user, he has to specify location of a config file where he has the rights to write,
# else he won't be able to save the configurations, or even to start the server...
- # TODO use appdirs
if os.name == 'nt':
rcfilepath = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'openerp-server.conf')
else:
or os.environ.get('OPENERP_SERVER') or rcfilepath)
self.load()
+
# Verify that we want to log or not, if not the output will go to stdout
if self.options['logfile'] in ('None', 'False'):
self.options['logfile'] = False
'xmlrpc', 'syslog', 'without_demo', 'timezone',
'xmlrpcs_interface', 'xmlrpcs_port', 'xmlrpcs',
'static_http_enable', 'static_http_document_root', 'static_http_url_prefix',
- 'secure_cert_file', 'secure_pkey_file', 'dbfilter', 'log_handler', 'log_level', 'log_db'
+ 'secure_cert_file', 'secure_pkey_file', 'dbfilter', 'log_handler', 'log_level'
]
for arg in keys:
elif isinstance(self.options[arg], basestring) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
self.options[arg] = optparse.Option.TYPE_CHECKER[self.casts[arg].type](self.casts[arg], arg, self.options[arg])
+
if isinstance(self.options['log_handler'], basestring):
self.options['log_handler'] = self.options['log_handler'].split(',')
'list_db', 'xmlrpcs', 'proxy_mode',
'test_file', 'test_enable', 'test_commit', 'test_report_directory',
'osv_memory_count_limit', 'osv_memory_age_limit', 'max_cron_threads', 'unaccent',
- 'data_dir',
+ 'workers', 'limit_memory_hard', 'limit_memory_soft', 'limit_time_cpu', 'limit_time_real', 'limit_request', 'auto_reload'
]
- posix_keys = [
- 'auto_reload', 'workers',
- 'limit_memory_hard', 'limit_memory_soft',
- 'limit_time_cpu', 'limit_time_real', 'limit_request',
- ]
-
- if os.name == 'posix':
- keys += posix_keys
- else:
- self.options.update(dict.fromkeys(posix_keys, None))
-
- # Copy the command-line arguments...
for arg in keys:
+ # Copy the command-line argument...
if getattr(opt, arg) is not None:
self.options[arg] = getattr(opt, arg)
# ... or keep, but cast, the config file value.
def __getitem__(self, key):
return self.options[key]
- @property
- def addons_data_dir(self):
- d = os.path.join(self['data_dir'], 'addons', release.series)
- if not os.path.exists(d):
- os.makedirs(d, 0700)
- else:
- os.chmod(d, 0700)
- return d
-
- @property
- def session_dir(self):
- d = os.path.join(self['data_dir'], 'sessions', release.series)
- if not os.path.exists(d):
- os.makedirs(d, 0700)
- else:
- os.chmod(d, 0700)
- return d
-
config = configmanager()
+++ /dev/null
-# -*- coding: utf-8 -*-
-# Copyright: 2014 - OpenERP S.A. <http://openerp.com>
-import types
-
-def post_mortem(config, info):
- if config['debug_mode'] and isinstance(info[2], types.TracebackType):
- import pdb
- pdb.post_mortem(info[2])
# Image resizing
# ----------------------------------------
-def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype='PNG', avoid_if_small=False):
""" Function to resize an image. The image will be resized to the given
size, while keeping the aspect ratios, and holes in the image will be
filled with transparent background. The image will not be stretched if
height mean an automatically computed value based respectivelly
on height or width of the source image.
:param encoding: the output encoding
- :param filetype: the output filetype, by default the source image's
- :type filetype: str, any PIL image format (supported for creation)
+ :param filetype: the output filetype
:param avoid_if_small: do not resize if image height and width
are smaller than the expected size.
"""
return base64_source
image_stream = StringIO.StringIO(base64_source.decode(encoding))
image = Image.open(image_stream)
- # store filetype here, as Image.new below will lose image.format
- filetype = filetype or image.format
asked_width, asked_height = size
if asked_width is None:
image.save(background_stream, filetype)
return background_stream.getvalue().encode(encoding)
-def image_resize_image_big(base64_source, size=(1204, 1024), encoding='base64', filetype=None, avoid_if_small=True):
+def image_resize_image_big(base64_source, size=(1204, 1204), encoding='base64', filetype='PNG', avoid_if_small=True):
""" Wrapper on image_resize_image, to resize images larger than the standard
'big' image size: 1024x1024px.
:param size, encoding, filetype, avoid_if_small: refer to image_resize_image
"""
return image_resize_image(base64_source, size, encoding, filetype, avoid_if_small)
-def image_resize_image_medium(base64_source, size=(128, 128), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image_medium(base64_source, size=(128, 128), encoding='base64', filetype='PNG', avoid_if_small=False):
""" Wrapper on image_resize_image, to resize to the standard 'medium'
image size: 180x180.
:param size, encoding, filetype, avoid_if_small: refer to image_resize_image
"""
return image_resize_image(base64_source, size, encoding, filetype, avoid_if_small)
-def image_resize_image_small(base64_source, size=(64, 64), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image_small(base64_source, size=(64, 64), encoding='base64', filetype='PNG', avoid_if_small=False):
""" Wrapper on image_resize_image, to resize to the standard 'small' image
size: 50x50.
:param size, encoding, filetype, avoid_if_small: refer to image_resize_image
Some functions related to the os and os.path module
"""
-from contextlib import contextmanager
import os
from os.path import join as opj
-import shutil
-import tempfile
-import zipfile
if os.name == 'nt':
import ctypes
if not topdown:
yield dirpath, dirnames, filenames
-@contextmanager
-def tempdir():
- tmpdir = tempfile.mkdtemp()
- try:
- yield tmpdir
- finally:
- shutil.rmtree(tmpdir)
-
-def zip_dir(path, stream, include_dir=True): # TODO add ignore list
- path = os.path.normpath(path)
- len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
- if len_prefix:
- len_prefix += 1
-
- with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
- for dirpath, dirnames, filenames in os.walk(path):
- for fname in filenames:
- bname, ext = os.path.splitext(fname)
- ext = ext or bname
- if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
- path = os.path.normpath(os.path.join(dirpath, fname))
- if os.path.isfile(path):
- zipf.write(path, path[len_prefix:])
-
if os.name != 'nt':
getppid = os.getppid
# -*- coding: utf-8 -*-
##############################################################################
-# Copyright (C) 2004-2014 OpenERP s.a. (<http://www.openerp.com>).
+# Copyright (C) 2004-2012 OpenERP s.a. (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
'False': False,
'None': None,
'str': str,
- 'unicode': unicode,
'globals': locals,
'locals': locals,
'bool': bool,
- 'int': int,
- 'float': float,
- 'long': long,
- 'enumerate': enumerate,
'dict': dict,
'list': list,
'tuple': tuple,
'abs': abs,
'min': min,
'max': max,
- 'sum': sum,
'reduce': reduce,
'filter': filter,
'round': round,
'len': len,
- 'repr': repr,
'set': set,
- 'all': all,
- 'any': any,
- 'ord': ord,
- 'chr': chr,
- 'cmp': cmp,
- 'divmod': divmod,
- 'isinstance': isinstance,
+ 'repr': repr,
+ 'int': int,
+ 'float': float,
'range': range,
- 'xrange': xrange,
- 'zip': zip,
}
)
if locals_builtins:
row.setdefault('tnrs', []).append((type, name, res_id))
row.setdefault('comments', set()).update(comments)
- for src, row in sorted(grouped_rows.items()):
+ for src, row in grouped_rows.items():
if not lang:
# translation template, so no translation value
row['translation'] = ''
if model_obj._sql_constraints:
push_local_constraints(module, model_obj, 'sql_constraints')
+ def get_module_from_path(path, mod_paths=None):
+ if not mod_paths:
+ # First, construct a list of possible paths
+ def_path = os.path.abspath(os.path.join(config.config['root_path'], 'addons')) # default addons path (base)
+ ad_paths= map(lambda m: os.path.abspath(m.strip()),config.config['addons_path'].split(','))
+ mod_paths=[def_path]
+ for adp in ad_paths:
+ mod_paths.append(adp)
+ if not os.path.isabs(adp):
+ mod_paths.append(adp)
+ elif adp.startswith(def_path):
+ mod_paths.append(adp[len(def_path)+1:])
+ for mp in mod_paths:
+ if path.startswith(mp) and (os.path.dirname(path) != mp):
+ path = path[len(mp)+1:]
+ return path.split(os.path.sep)[0]
+ return 'base' # files that are not in a module are considered as being in 'base' module
modobj = registry['ir.module.module']
installed_modids = modobj.search(cr, uid, [('state', '=', 'installed')])
installed_modules = map(lambda m: m['name'], modobj.read(cr, uid, installed_modids, ['name']))
- path_list = list(openerp.modules.module.ad_paths)
+ root_path = os.path.join(config.config['root_path'], 'addons')
+
+ apaths = map(os.path.abspath, map(str.strip, config.config['addons_path'].split(',')))
+ if root_path in apaths:
+ path_list = apaths
+ else :
+ path_list = [root_path,] + apaths
+
# Also scan these non-addon paths
for bin_path in ['osv', 'report' ]:
path_list.append(os.path.join(config.config['root_path'], bin_path))
_logger.debug("Scanning modules at paths: ", path_list)
- mod_paths = list(path_list)
-
- def get_module_from_path(path):
- for mp in mod_paths:
- if path.startswith(mp) and (os.path.dirname(path) != mp):
- path = path[len(mp)+1:]
- return path.split(os.path.sep)[0]
- return 'base' # files that are not in a module are considered as being in 'base' module
+ mod_paths = []
def verified_module_filepaths(fname, path, root):
fabsolutepath = join(root, fname)
frelativepath = fabsolutepath[len(path):]
display_path = "addons%s" % frelativepath
- module = get_module_from_path(fabsolutepath)
+ module = get_module_from_path(fabsolutepath, mod_paths=mod_paths)
if ('all' in modules or module in modules) and module in installed_modules:
return module, fabsolutepath, frelativepath, display_path
return None, None, None, None
"skip_archive": 1,
"optimize": 0, # keep the assert running, because the integrated tests rely on them.
"dist_dir": 'dist',
- "packages": ["HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "jinja2", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "pytz", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
+ "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "jinja2", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "pytz", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
"excludes" : ["Tkconstants","Tkinter","tcl"],
}
}