diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 6921b36f91d..5c95b327605 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -24,6 +24,7 @@ "static/lib/jquery.ui.notify/js/jquery.notify.js", "static/lib/jquery.deferred-queue/jquery.deferred-queue.js", "static/lib/jquery.scrollTo/jquery.scrollTo-min.js", + "static/lib/jquery.tipTip/jquery.tipTip.js", "static/lib/json/json2.js", "static/lib/qweb/qweb2.js", "static/lib/underscore/underscore.js", @@ -50,6 +51,7 @@ "static/lib/jquery.superfish/css/superfish.css", "static/lib/jquery.ui/css/smoothness/jquery-ui-1.8.9.custom.css", "static/lib/jquery.ui.notify/css/ui.notify.css", + "static/lib/jquery.tipTip/tipTip.css", "static/src/css/base.css", "static/src/css/data_export.css", "static/src/css/data_import.css", diff --git a/addons/web/common/http.py b/addons/web/common/http.py index e23a0431a7c..69220eec2d7 100644 --- a/addons/web/common/http.py +++ b/addons/web/common/http.py @@ -403,7 +403,7 @@ class Root(object): request.parameter_storage_class = werkzeug.datastructures.ImmutableDict if request.path == '/': - params = urllib.urlencode(dict(request.args, debug='')) + params = urllib.urlencode(request.args) return werkzeug.utils.redirect(self.root + '?' + params, 301)( environ, start_response) elif request.path == '/mobile': diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 6f72d836ea4..6af0268b3bf 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -268,13 +268,18 @@ class Database(openerpweb.Controller): params['db_lang'], params['create_admin_pwd'] ) - + try: return req.session.proxy("db").create(*create_attrs) except xmlrpclib.Fault, e: - if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': - return {'error': e.faultCode, 'title': 'Create Database'} - return {'error': 'Could not create database !', 'title': 'Create Database'} + if e.faultCode and isinstance(e.faultCode, str)\ + and e.faultCode.split(':')[0] == 'AccessDenied': + return {'error': e.faultCode, 'title': 'Database creation error'} + return { + 'error': "Could not create database '%s': %s" % ( + params['db_name'], e.faultString), + 'title': 'Database creation error' + } @openerpweb.jsonrequest def drop(self, req, fields): @@ -307,7 +312,7 @@ class Database(openerpweb.Controller): @openerpweb.httprequest def restore(self, req, db_file, restore_pwd, new_db): try: - data = base64.b64encode(db_file.file.read()) + data = base64.b64encode(db_file.read()) req.session.proxy("db").restore(restore_pwd, new_db, data) return '' except xmlrpclib.Fault, e: @@ -338,7 +343,8 @@ class Session(openerpweb.Controller): "session_id": req.session_id, "uid": req.session._uid, "context": ctx, - "db": req.session._db + "db": req.session._db, + "login": req.session._login } @openerpweb.jsonrequest @@ -347,7 +353,8 @@ class Session(openerpweb.Controller): return { "uid": req.session._uid, "context": req.session.get_context() if req.session._uid else False, - "db": req.session._db + "db": req.session._db, + "login": req.session._login } @openerpweb.jsonrequest @@ -935,10 +942,12 @@ class View(openerpweb.Controller): domain = elem.get(el, '').strip() if domain: elem.set(el, parse_domain(domain, session)) + elem.set(el + '_string', domain) for el in ['context', 'default_get']: context_string = elem.get(el, '').strip() if context_string: elem.set(el, parse_context(context_string, session)) + elem.set(el + '_string', context_string) @openerpweb.jsonrequest def load(self, req, model, view_id, view_type, toolbar=False): @@ -1417,6 +1426,7 @@ class ExcelExport(Export): for cell_index, cell_value in enumerate(row): if isinstance(cell_value, basestring): cell_value = re.sub("\r", " ", cell_value) + if cell_value is False: cell_value = None worksheet.write(row_index + 1, cell_index, cell_value, style) fp = StringIO() diff --git a/addons/web/po/ar.po b/addons/web/po/ar.po index 4a6ebecff9f..34c7beccf4a 100644 --- a/addons/web/po/ar.po +++ b/addons/web/po/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-09 05:09+0000\n" -"X-Generator: Launchpad (build 14263)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:49+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/da.po b/addons/web/po/da.po index db03cc5e19b..d40db04e29e 100644 --- a/addons/web/po/da.po +++ b/addons/web/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-09 05:09+0000\n" -"X-Generator: Launchpad (build 14263)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:49+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/de.po b/addons/web/po/de.po index 0a26630321f..72778500484 100644 --- a/addons/web/po/de.po +++ b/addons/web/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/es.po b/addons/web/po/es.po index 9bd7071871b..e53b5e2631b 100644 --- a/addons/web/po/es.po +++ b/addons/web/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/es_EC.po b/addons/web/po/es_EC.po index 588408ba979..fc98c8bb536 100644 --- a/addons/web/po/es_EC.po +++ b/addons/web/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/et.po b/addons/web/po/et.po index 6b6da84f3a5..b9362cd0fdc 100644 --- a/addons/web/po/et.po +++ b/addons/web/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/fr.po b/addons/web/po/fr.po index df35344c558..fcbcce3b1a7 100644 --- a/addons/web/po/fr.po +++ b/addons/web/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/gl.po b/addons/web/po/gl.po index 34b2d50085f..7a8fefab03c 100644 --- a/addons/web/po/gl.po +++ b/addons/web/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/it.po b/addons/web/po/it.po index 647030fd4ea..a3899989d7e 100644 --- a/addons/web/po/it.po +++ b/addons/web/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/nl_BE.po b/addons/web/po/nl_BE.po index 3d649b59b9d..43f52ade62e 100644 --- a/addons/web/po/nl_BE.po +++ b/addons/web/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/pl.po b/addons/web/po/pl.po index fde2196a73e..56f004a0197 100644 --- a/addons/web/po/pl.po +++ b/addons/web/po/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-05 06:04+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/pt.po b/addons/web/po/pt.po new file mode 100644 index 00000000000..ca98e18bce9 --- /dev/null +++ b/addons/web/po/pt.po @@ -0,0 +1,688 @@ +# Portuguese translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-21 22:22+0000\n" +"Last-Translator: Daniel Reis \n" +"Language-Team: Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-11-22 05:13+0000\n" +"X-Generator: Launchpad (build 14299)\n" + +#: addons/web/static/src/js/view_form.js:355 +msgid "" +"Warning, the record has been modified, your changes will be discarded." +msgstr "" +"Atenção, o o registo foi modificado, as suas alterações serão descartadas." + +#: addons/web/static/src/js/view_form.js:1659 +msgid "   Search More..." +msgstr "" + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "" + +#: addons/web/static/src/js/views.js:568 +msgid "You must choose at least one record." +msgstr "Escolha pelo menos um registo." + +#: addons/web/static/src/js/views.js:569 +msgid "Warning" +msgstr "Aviso" + +#: addons/web/static/src/js/views.js:609 +msgid "Translations" +msgstr "Traduções" + +#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0 +msgid "Save" +msgstr "Guardar" + +#: addons/web/static/src/js/views.js:615 +msgid "Close" +msgstr "Fechar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "x" +msgstr "x" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{title}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{text}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Powered by" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "openerp.com" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Loading..." +msgstr "A carregar ..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create" +msgstr "Criar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Drop" +msgstr "Excluir" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Backup" +msgstr "Cópia de segurança" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Restore" +msgstr "Restaurar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password" +msgstr "Senha" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Back to Login" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CREATE DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New database name:" +msgstr "Nome da nova base de dados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Load Demonstration data:" +msgstr "Carregar dados de demonstração" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Default language:" +msgstr "Idioma predefinido:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Admin password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm password:" +msgstr "Confirmar senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "DROP DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database:" +msgstr "Base de dados:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master Password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "BACKUP DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "RESTORE DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "File:" +msgstr "Ficheiro:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CHANGE MASTER PASSWORD" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New master password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm new master password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "User:" +msgstr "Utilizador:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password:" +msgstr "Senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database" +msgstr "Base de dados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Login" +msgstr "Iniciar sessão" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Bad username or password" +msgstr "Nome de utilizador ou senha incorrectos" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"We think that daily job activities can be more intuitive, efficient, " +"automated, .. and even fun." +msgstr "" +"Pensamos que as atividades do trabalho diário pode ser mais intuitivas, " +"eficientes, automatizadas, ... e até mesmo divertidas." + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP's vision to be:" +msgstr "A visão do OpenERP é:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Full featured" +msgstr "Pleno de funcionalidade" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Today's enterprise challenges are multiple. We provide one module for each " +"need." +msgstr "" +"Os desafios atuais das empresas são múltiplos. Nós fornecemos um módulo para " +"cada necessidade." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open Source" +msgstr "Código aberto" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"To Build a great product, we rely on the knowledge of thousands of " +"contributors." +msgstr "" +"Para construir um grande produto, nós contamos com o conhecimento de " +"milhares de contribuidores." + +#: addons/web/static/src/xml/base.xml:0 +msgid "User Friendly" +msgstr "Amigável para o utilizador" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"In order to be productive, people need clean and easy to use interface." +msgstr "" +"Para serem produtivas, as pessoas precisam de uma interface simples e fácil " +"de usar." + +#: addons/web/static/src/xml/base.xml:0 +msgid "(" +msgstr "(" + +#: addons/web/static/src/xml/base.xml:0 +msgid ")" +msgstr ")" + +#: addons/web/static/src/xml/base.xml:0 +msgid "LOGOUT" +msgstr "SAIR" + +#: addons/web/static/src/xml/base.xml:0 +msgid "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_menu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_submenu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Hide this tip" +msgstr "Ocultar esta dica" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Disable all tips" +msgstr "Desativar todas as dicas" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View#" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields" +msgstr "Campos" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View labels" +msgstr "Ver etiquetas" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Sidebar Relates" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Field" +msgstr "Campo" + +#: addons/web/static/src/xml/base.xml:0 +msgid ":" +msgstr ":" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate view" +msgstr "Traduzir vista" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate sidebar" +msgstr "Traduzir barra lateral" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delete" +msgstr "Apagar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "First" +msgstr "Primeiro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<" +msgstr "<" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">" +msgstr ">" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Last" +msgstr "Último" + +#: addons/web/static/src/xml/base.xml:0 +msgid "♻" +msgstr "♻" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Edit" +msgstr "Gravar & Editar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create & Edit" +msgstr "Criar & Editar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New" +msgstr "Novo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Duplicate" +msgstr "Duplicar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Readonly/Editable" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<<" +msgstr "<<" + +#: addons/web/static/src/xml/base.xml:0 +msgid "0" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "/" +msgstr "/" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">>" +msgstr ">>" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add" +msgstr "Acrescentar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Unhandled widget" +msgstr "Widget não tratado" + +#: addons/web/static/src/xml/base.xml:0 +msgid "?" +msgstr "?" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#" +msgstr "#" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Done" +msgstr "Concluído" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open..." +msgstr "Abrir..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create..." +msgstr "Criar..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Search..." +msgstr "Procurar..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "..." +msgstr "..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Uploading ..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Select" +msgstr "Selecionar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save As" +msgstr "Guardar como" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Clear" +msgstr "Limpar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Advanced Filter" +msgstr "Filtro avançados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Filters --" +msgstr "-- Filtros --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Actions --" +msgstr "-- Ações --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save Filter" +msgstr "Guardar filtro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Manage Filters" +msgstr "Gerir filtros" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Filter Name:" +msgstr "Nome do filtro:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(Any existing filter with the same name will be replaced)" +msgstr "(filtros existentes com esse nome serão substituídos)" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Any of the following conditions must match" +msgstr "Deve satisfazer alguma das seguintes condições" + +#: addons/web/static/src/xml/base.xml:0 +msgid "All the following conditions must match" +msgstr "Deve satisfazer toas as seguintes condições" + +#: addons/web/static/src/xml/base.xml:0 +msgid "None of the following conditions must match" +msgstr "Não deve satisfazernenhuma das seguintes condições" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add condition" +msgstr "Acrescentar condição" + +#: addons/web/static/src/xml/base.xml:0 +msgid "and" +msgstr "e" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Cancel" +msgstr "Cancelar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & New" +msgstr "Guardar & Novo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Close" +msgstr "Guardar & Fechar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export" +msgstr "Exportar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"This wizard will export all data that matches the current search criteria to " +"a CSV file.\n" +" You can export all data or only the fields that can be " +"reimported after modification." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Type:" +msgstr "Tipo de exportação:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Compatible Export" +msgstr "Exportação compatível com importação" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export all Data" +msgstr "Exportar todos os dados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Formats" +msgstr "Formatos de exportação" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Available fields" +msgstr "Campos disponíveis" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields to export" +msgstr "Campos a exportar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save fields list" +msgstr "Gravar lista de campos" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove" +msgstr "Remover" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove All" +msgstr "Remover tudo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Name" +msgstr "Nome" + +#: addons/web/static/src/xml/base.xml:0 +msgid " " +msgstr " " + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save as:" +msgstr "Guardar como:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Ok" +msgstr "Ok" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Saved exports:" +msgstr "Exportações guardadas:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Old Password:" +msgstr "Senha antiga:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New Password:" +msgstr "Nova senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm Password:" +msgstr "Confirme a senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import" +msgstr "Importar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "1. Import a .CSV file" +msgstr "1. Importar um ficheiro .CSV" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Select a .CSV file to import. If you need a sample of file to import,\n" +" you should use the export tool with the \"Import Compatible\" option." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CSV File:" +msgstr "Ficheiro CSV:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "2. Check your file format" +msgstr "2. Verifique o formato do ficheiro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Options" +msgstr "Opções de importação" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Does your file have titles?" +msgstr "O ficheiro tem títulos?" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Separator:" +msgstr "Separador:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delimiter:" +msgstr "Delimitador:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Encoding:" +msgstr "Codificação:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "UTF-8" +msgstr "UTF-8" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Latin 1" +msgstr "Latin-1" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Lines to skip" +msgstr "Linhas a ignorar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "The import failed due to:" +msgstr "Importação falhou devido a:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Here is a preview of the file we could not import:" +msgstr "Previsão do ficheiro que não conseguiu ser importado:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP Web" +msgstr "OpenERP Web" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Version" +msgstr "Versão" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved." +msgstr "Copyright © 2011-HOJE OpenERP SA. Todos os direitos reservados." + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP is a trademark of the" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP SA Company" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Licenced under the terms of" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "GNU Affero General Public License" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "About OpenERP" +msgstr "Acerca do OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP" +msgstr "OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"is a free enterprise-scale software system that is designed to boost\n" +" productivity and profit through data integration. It connects, " +"improves and\n" +" manages business processes in areas such as sales, finance, " +"supply chain,\n" +" project management, production, services, CRM, etc..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"The system is platform-independent, and can be installed on Windows, Mac OS " +"X,\n" +" and various Linux and other Unix-based distributions. Its " +"architecture enables\n" +" new functionality to be rapidly created, modifications to be " +"made to a\n" +" production system and migration to a new version to be " +"straightforward." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Depending on your needs, OpenERP is available through a web or application " +"client." +msgstr "" +"Dependendo de suas necessidades, o OpenERP está disponível através da web ou " +"de uma aplicação cliente." diff --git a/addons/web/po/pt_BR.po b/addons/web/po/pt_BR.po new file mode 100644 index 00000000000..b80ea3a78bd --- /dev/null +++ b/addons/web/po/pt_BR.po @@ -0,0 +1,683 @@ +# Brazilian Portuguese translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-12 18:57+0000\n" +"Last-Translator: Cristiano Gavião \n" +"Language-Team: Brazilian Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" + +#: addons/web/static/src/js/view_form.js:355 +msgid "" +"Warning, the record has been modified, your changes will be discarded." +msgstr "Aviso, o registro foi modificado, suas alterações serão descartadas." + +#: addons/web/static/src/js/view_form.js:1659 +msgid "   Search More..." +msgstr "   Procurar Mais..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "" + +#: addons/web/static/src/js/views.js:568 +msgid "You must choose at least one record." +msgstr "" + +#: addons/web/static/src/js/views.js:569 +msgid "Warning" +msgstr "" + +#: addons/web/static/src/js/views.js:609 +msgid "Translations" +msgstr "" + +#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0 +msgid "Save" +msgstr "" + +#: addons/web/static/src/js/views.js:615 +msgid "Close" +msgstr "Fechar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "x" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{title}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{text}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Powered by" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "openerp.com" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Loading..." +msgstr "Carregando..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create" +msgstr "Criar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Drop" +msgstr "Soltar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Backup" +msgstr "Cópia de Segurança" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Restore" +msgstr "Restaurar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password" +msgstr "Senha" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Back to Login" +msgstr "Voltar ao Login" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CREATE DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master password:" +msgstr "Senha mestre" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New database name:" +msgstr "Nome da nova base de dados:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Load Demonstration data:" +msgstr "Carregar dados de demonstração:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Default language:" +msgstr "Idioma padrão:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Admin password:" +msgstr "Senha de Administrador" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm password:" +msgstr "Confirme a senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "DROP DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database:" +msgstr "Base de dados:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master Password:" +msgstr "Senha Mestre" + +#: addons/web/static/src/xml/base.xml:0 +msgid "BACKUP DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "RESTORE DATABASE" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "File:" +msgstr "Arquivo:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CHANGE MASTER PASSWORD" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New master password:" +msgstr "Nova senha mestre:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm new master password:" +msgstr "Confirme nova senha mestre" + +#: addons/web/static/src/xml/base.xml:0 +msgid "User:" +msgstr "Usuário:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password:" +msgstr "Senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database" +msgstr "Base de dados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Login" +msgstr "Autenticação" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Bad username or password" +msgstr "Nome de usuário ou senha inválido" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"We think that daily job activities can be more intuitive, efficient, " +"automated, .. and even fun." +msgstr "" +"Pensamos que as atividades de trabalho diário pode ser mais intuitivas, " +"eficiente, automatizadas .. e até mesmo divertidas." + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP's vision to be:" +msgstr "OpenERP vislumbra ser:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Full featured" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Today's enterprise challenges are multiple. We provide one module for each " +"need." +msgstr "" +"Os desafios atuais da empresa são múltiplos. Nós fornecemos um módulo para " +"cada necessidade." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open Source" +msgstr "Código Aberto" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"To Build a great product, we rely on the knowledge of thousands of " +"contributors." +msgstr "" +"Para construir um grande produto, contamos com o conhecimento de milhares de " +"contribuintes." + +#: addons/web/static/src/xml/base.xml:0 +msgid "User Friendly" +msgstr "Uso Amigável" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"In order to be productive, people need clean and easy to use interface." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ")" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "LOGOUT" +msgstr "DESCONECTAR" + +#: addons/web/static/src/xml/base.xml:0 +msgid "«" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_menu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_submenu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Hide this tip" +msgstr "Esconder dica" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Disable all tips" +msgstr "Desligar todas as dicas" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View#" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View labels" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Sidebar Relates" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Field" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ":" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate view" +msgstr "Visão de Tradução" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate sidebar" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delete" +msgstr "Excluir" + +#: addons/web/static/src/xml/base.xml:0 +msgid "First" +msgstr "Primeiro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Last" +msgstr "Último" + +#: addons/web/static/src/xml/base.xml:0 +msgid "♻" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Edit" +msgstr "Salvar & Editar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create & Edit" +msgstr "Criar & Editar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New" +msgstr "Novo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Duplicate" +msgstr "Duplicar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Readonly/Editable" +msgstr "Apenas Leitura/Editável" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<<" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "0" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "/" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">>" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add" +msgstr "Adicionar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Unhandled widget" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "?" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Done" +msgstr "Concluído" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open..." +msgstr "Abrir..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create..." +msgstr "Criar..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Search..." +msgstr "Pesquisar..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "..." +msgstr "..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Uploading ..." +msgstr "Transferindo ..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Select" +msgstr "Selecionar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save As" +msgstr "Salvar como" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Clear" +msgstr "Limpar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Advanced Filter" +msgstr "Filtro Avançado" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Filters --" +msgstr "-- Filtros --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Actions --" +msgstr "-- Ações --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save Filter" +msgstr "Salvar filtro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Manage Filters" +msgstr "Gerenciar Filtros" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Filter Name:" +msgstr "Nome do Filtro" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(Any existing filter with the same name will be replaced)" +msgstr "(Qualquer filtro existente com o mesmo nome será substituído)" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Any of the following conditions must match" +msgstr "Qualquer das seguintes condições deve ser verdadeira" + +#: addons/web/static/src/xml/base.xml:0 +msgid "All the following conditions must match" +msgstr "Todas as seguintes condições devem ser verdadeiras" + +#: addons/web/static/src/xml/base.xml:0 +msgid "None of the following conditions must match" +msgstr "Nenhuma das seguintes condições deve ser verdadeira" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add condition" +msgstr "Adicionar condição" + +#: addons/web/static/src/xml/base.xml:0 +msgid "and" +msgstr "e" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Cancel" +msgstr "Cancelar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & New" +msgstr "Salvar & Novo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Close" +msgstr "Salvar & Fechar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export" +msgstr "Exportar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"This wizard will export all data that matches the current search criteria to " +"a CSV file.\n" +" You can export all data or only the fields that can be " +"reimported after modification." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Type:" +msgstr "Tipo de Exportação:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Compatible Export" +msgstr "Importar Exportação Compatível" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export all Data" +msgstr "Exportar todos os Dados" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Formats" +msgstr "Formatos de Exportação" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Available fields" +msgstr "Campos Disponíveis" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields to export" +msgstr "Campos para exportar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save fields list" +msgstr "Salvar lista de campos" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove" +msgstr "Remover" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove All" +msgstr "Remover Tudo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Name" +msgstr "Nome" + +#: addons/web/static/src/xml/base.xml:0 +msgid " " +msgstr " " + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save as:" +msgstr "Salvar como:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Ok" +msgstr "Ok" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Saved exports:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Old Password:" +msgstr "Senha antiga" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New Password:" +msgstr "Nova Senha:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm Password:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import" +msgstr "Importar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "1. Import a .CSV file" +msgstr "Importar um arquivo CSV." + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Select a .CSV file to import. If you need a sample of file to import,\n" +" you should use the export tool with the \"Import Compatible\" option." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CSV File:" +msgstr "Arquivo CSV." + +#: addons/web/static/src/xml/base.xml:0 +msgid "2. Check your file format" +msgstr "Verifique seu formato de arquivo" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Options" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Does your file have titles?" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Separator:" +msgstr "Separador:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delimiter:" +msgstr "Delimitador:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Encoding:" +msgstr "Codificação:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "UTF-8" +msgstr "UTF-8" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Latin 1" +msgstr "Latin 1" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Lines to skip" +msgstr "Linhas para ignorar" + +#: addons/web/static/src/xml/base.xml:0 +msgid "The import failed due to:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Here is a preview of the file we could not import:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP Web" +msgstr "OpenERP Web" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Version" +msgstr "Versão" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP is a trademark of the" +msgstr "OpenERP é uma marca de" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP SA Company" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Licenced under the terms of" +msgstr "Licenciado sobre os termos de" + +#: addons/web/static/src/xml/base.xml:0 +msgid "GNU Affero General Public License" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "About OpenERP" +msgstr "Sobre OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP" +msgstr "OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"is a free enterprise-scale software system that is designed to boost\n" +" productivity and profit through data integration. It connects, " +"improves and\n" +" manages business processes in areas such as sales, finance, " +"supply chain,\n" +" project management, production, services, CRM, etc..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"The system is platform-independent, and can be installed on Windows, Mac OS " +"X,\n" +" and various Linux and other Unix-based distributions. Its " +"architecture enables\n" +" new functionality to be rapidly created, modifications to be " +"made to a\n" +" production system and migration to a new version to be " +"straightforward." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Depending on your needs, OpenERP is available through a web or application " +"client." +msgstr "" diff --git a/addons/web/po/sl.po b/addons/web/po/sl.po index 54349249817..585dae78293 100644 --- a/addons/web/po/sl.po +++ b/addons/web/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch new file mode 100644 index 00000000000..7af316b2f3f --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch @@ -0,0 +1,52 @@ +--- jquery.tipTip_old.js 2011-11-14 21:40:55.000000000 +0100 ++++ jquery.tipTip.js 2011-11-15 10:09:35.000000000 +0100 +@@ -31,7 +31,7 @@ + fadeIn: 200, + fadeOut: 200, + attribute: "title", +- content: false, // HTML or String to fill TipTIp with ++ content: false, // HTML String or function to fill TipTIp with + enter: function(){}, + exit: function(){} + }; +@@ -51,12 +51,7 @@ + + return this.each(function(){ + var org_elem = $(this); +- if(opts.content){ +- var org_title = opts.content; +- } else { +- var org_title = org_elem.attr(opts.attribute); +- } +- if(org_title != ""){ ++ if(opts.content || org_elem.attr(opts.attribute)){ + if(!opts.content){ + org_elem.removeAttr(opts.attribute); //remove original Attribute + } +@@ -99,6 +94,8 @@ + + function active_tiptip(){ + opts.enter.call(this); ++ var org_title = typeof opts.content === 'function' ? opts.content() : opts.content; ++ org_title = org_title || org_elem.attr(opts.attribute); + tiptip_content.html(org_title); + tiptip_holder.hide().removeAttr("class").css("margin","0"); + tiptip_arrow.removeAttr("style"); +@@ -176,8 +173,15 @@ + tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"}); + tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class); + +- if (timeout){ clearTimeout(timeout); } +- timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay); ++ if (timeout) { ++ clearTimeout(timeout); ++ } ++ timeout = setTimeout(function() { ++ tiptip_holder.stop(true,true); ++ if ($.contains(document.documentElement, org_elem[0])) { ++ tiptip_holder.fadeIn(opts.fadeIn); ++ } ++ }, opts.delay); + } + + function deactive_tiptip(){ diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js new file mode 100644 index 00000000000..0b3a24d4beb --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js @@ -0,0 +1,193 @@ + /* + * TipTip + * Copyright 2010 Drew Wilson + * www.drewwilson.com + * code.drewwilson.com/entry/tiptip-jquery-plugin + * + * Version 1.3 - Updated: Mar. 23, 2010 + * + * This Plug-In will create a custom tooltip to replace the default + * browser tooltip. It is extremely lightweight and very smart in + * that it detects the edges of the browser window and will make sure + * the tooltip stays within the current window size. As a result the + * tooltip will adjust itself to be displayed above, below, to the left + * or to the right depending on what is necessary to stay within the + * browser window. It is completely customizable as well via CSS. + * + * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($){ + $.fn.tipTip = function(options) { + var defaults = { + activation: "hover", + keepAlive: false, + maxWidth: "200px", + edgeOffset: 3, + defaultPosition: "bottom", + delay: 400, + fadeIn: 200, + fadeOut: 200, + attribute: "title", + content: false, // HTML String or function to fill TipTIp with + enter: function(){}, + exit: function(){} + }; + var opts = $.extend(defaults, options); + + // Setup tip tip elements and render them to the DOM + if($("#tiptip_holder").length <= 0){ + var tiptip_holder = $('
'); + var tiptip_content = $('
'); + var tiptip_arrow = $('
'); + $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('
'))); + } else { + var tiptip_holder = $("#tiptip_holder"); + var tiptip_content = $("#tiptip_content"); + var tiptip_arrow = $("#tiptip_arrow"); + } + + return this.each(function(){ + var org_elem = $(this); + if(opts.content || org_elem.attr(opts.attribute)){ + if(!opts.content){ + org_elem.removeAttr(opts.attribute); //remove original Attribute + } + var timeout = false; + + if(opts.activation == "hover"){ + org_elem.hover(function(){ + active_tiptip(); + }, function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } else if(opts.activation == "focus"){ + org_elem.focus(function(){ + active_tiptip(); + }).blur(function(){ + deactive_tiptip(); + }); + } else if(opts.activation == "click"){ + org_elem.click(function(){ + active_tiptip(); + return false; + }).hover(function(){},function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } + + function active_tiptip(){ + opts.enter.call(this); + var org_title = typeof opts.content === 'function' ? opts.content() : opts.content; + org_title = org_title || org_elem.attr(opts.attribute); + tiptip_content.html(org_title); + tiptip_holder.hide().removeAttr("class").css("margin","0"); + tiptip_arrow.removeAttr("style"); + + var top = parseInt(org_elem.offset()['top']); + var left = parseInt(org_elem.offset()['left']); + var org_width = parseInt(org_elem.outerWidth()); + var org_height = parseInt(org_elem.outerHeight()); + var tip_w = tiptip_holder.outerWidth(); + var tip_h = tiptip_holder.outerHeight(); + var w_compare = Math.round((org_width - tip_w) / 2); + var h_compare = Math.round((org_height - tip_h) / 2); + var marg_left = Math.round(left + w_compare); + var marg_top = Math.round(top + org_height + opts.edgeOffset); + var t_class = ""; + var arrow_top = ""; + var arrow_left = Math.round(tip_w - 12) / 2; + + if(opts.defaultPosition == "bottom"){ + t_class = "_bottom"; + } else if(opts.defaultPosition == "top"){ + t_class = "_top"; + } else if(opts.defaultPosition == "left"){ + t_class = "_left"; + } else if(opts.defaultPosition == "right"){ + t_class = "_right"; + } + + var right_compare = (w_compare + left) < parseInt($(window).scrollLeft()); + var left_compare = (tip_w + left) > parseInt($(window).width()); + + if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){ + t_class = "_right"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = -12; + marg_left = Math.round(left + org_width + opts.edgeOffset); + marg_top = Math.round(top + h_compare); + } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){ + t_class = "_left"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = Math.round(tip_w); + marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5)); + marg_top = Math.round(top + h_compare); + } + + var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop()); + var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0; + + if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_top"; + } else { + t_class = t_class+"_top"; + } + arrow_top = tip_h; + marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset)); + } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_bottom"; + } else { + t_class = t_class+"_bottom"; + } + arrow_top = -12; + marg_top = Math.round(top + org_height + opts.edgeOffset); + } + + if(t_class == "_right_top" || t_class == "_left_top"){ + marg_top = marg_top + 5; + } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){ + marg_top = marg_top - 5; + } + if(t_class == "_left_top" || t_class == "_left_bottom"){ + marg_left = marg_left + 5; + } + tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"}); + tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class); + + if (timeout){ clearTimeout(timeout); } + timeout = setTimeout(function() { + tiptip_holder.stop(true,true); + if ($.contains(document.documentElement, org_elem[0])) { + tiptip_holder.fadeIn(opts.fadeIn); + } + }, opts.delay); + } + + function deactive_tiptip(){ + opts.exit.call(this); + if (timeout){ clearTimeout(timeout); } + tiptip_holder.fadeOut(opts.fadeOut); + } + } + }); + } +})(jQuery); diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js b/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js new file mode 100644 index 00000000000..d2b460d1261 --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js @@ -0,0 +1,191 @@ + /* + * TipTip + * Copyright 2010 Drew Wilson + * www.drewwilson.com + * code.drewwilson.com/entry/tiptip-jquery-plugin + * + * Version 1.3 - Updated: Mar. 23, 2010 + * + * This Plug-In will create a custom tooltip to replace the default + * browser tooltip. It is extremely lightweight and very smart in + * that it detects the edges of the browser window and will make sure + * the tooltip stays within the current window size. As a result the + * tooltip will adjust itself to be displayed above, below, to the left + * or to the right depending on what is necessary to stay within the + * browser window. It is completely customizable as well via CSS. + * + * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($){ + $.fn.tipTip = function(options) { + var defaults = { + activation: "hover", + keepAlive: false, + maxWidth: "200px", + edgeOffset: 3, + defaultPosition: "bottom", + delay: 400, + fadeIn: 200, + fadeOut: 200, + attribute: "title", + content: false, // HTML or String to fill TipTIp with + enter: function(){}, + exit: function(){} + }; + var opts = $.extend(defaults, options); + + // Setup tip tip elements and render them to the DOM + if($("#tiptip_holder").length <= 0){ + var tiptip_holder = $('
'); + var tiptip_content = $('
'); + var tiptip_arrow = $('
'); + $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('
'))); + } else { + var tiptip_holder = $("#tiptip_holder"); + var tiptip_content = $("#tiptip_content"); + var tiptip_arrow = $("#tiptip_arrow"); + } + + return this.each(function(){ + var org_elem = $(this); + if(opts.content){ + var org_title = opts.content; + } else { + var org_title = org_elem.attr(opts.attribute); + } + if(org_title != ""){ + if(!opts.content){ + org_elem.removeAttr(opts.attribute); //remove original Attribute + } + var timeout = false; + + if(opts.activation == "hover"){ + org_elem.hover(function(){ + active_tiptip(); + }, function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } else if(opts.activation == "focus"){ + org_elem.focus(function(){ + active_tiptip(); + }).blur(function(){ + deactive_tiptip(); + }); + } else if(opts.activation == "click"){ + org_elem.click(function(){ + active_tiptip(); + return false; + }).hover(function(){},function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } + + function active_tiptip(){ + opts.enter.call(this); + tiptip_content.html(org_title); + tiptip_holder.hide().removeAttr("class").css("margin","0"); + tiptip_arrow.removeAttr("style"); + + var top = parseInt(org_elem.offset()['top']); + var left = parseInt(org_elem.offset()['left']); + var org_width = parseInt(org_elem.outerWidth()); + var org_height = parseInt(org_elem.outerHeight()); + var tip_w = tiptip_holder.outerWidth(); + var tip_h = tiptip_holder.outerHeight(); + var w_compare = Math.round((org_width - tip_w) / 2); + var h_compare = Math.round((org_height - tip_h) / 2); + var marg_left = Math.round(left + w_compare); + var marg_top = Math.round(top + org_height + opts.edgeOffset); + var t_class = ""; + var arrow_top = ""; + var arrow_left = Math.round(tip_w - 12) / 2; + + if(opts.defaultPosition == "bottom"){ + t_class = "_bottom"; + } else if(opts.defaultPosition == "top"){ + t_class = "_top"; + } else if(opts.defaultPosition == "left"){ + t_class = "_left"; + } else if(opts.defaultPosition == "right"){ + t_class = "_right"; + } + + var right_compare = (w_compare + left) < parseInt($(window).scrollLeft()); + var left_compare = (tip_w + left) > parseInt($(window).width()); + + if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){ + t_class = "_right"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = -12; + marg_left = Math.round(left + org_width + opts.edgeOffset); + marg_top = Math.round(top + h_compare); + } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){ + t_class = "_left"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = Math.round(tip_w); + marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5)); + marg_top = Math.round(top + h_compare); + } + + var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop()); + var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0; + + if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_top"; + } else { + t_class = t_class+"_top"; + } + arrow_top = tip_h; + marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset)); + } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_bottom"; + } else { + t_class = t_class+"_bottom"; + } + arrow_top = -12; + marg_top = Math.round(top + org_height + opts.edgeOffset); + } + + if(t_class == "_right_top" || t_class == "_left_top"){ + marg_top = marg_top + 5; + } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){ + marg_top = marg_top - 5; + } + if(t_class == "_left_top" || t_class == "_left_bottom"){ + marg_left = marg_left + 5; + } + tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"}); + tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class); + + if (timeout){ clearTimeout(timeout); } + timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay); + } + + function deactive_tiptip(){ + opts.exit.call(this); + if (timeout){ clearTimeout(timeout); } + tiptip_holder.fadeOut(opts.fadeOut); + } + } + }); + } +})(jQuery); diff --git a/addons/web/static/lib/jquery.tipTip/tipTip.css b/addons/web/static/lib/jquery.tipTip/tipTip.css new file mode 100644 index 00000000000..4fb95d37691 --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/tipTip.css @@ -0,0 +1,113 @@ +/* TipTip CSS - Version 1.2 */ + +#tiptip_holder { + display: none; + position: absolute; + top: 0; + left: 0; + z-index: 99999; +} + +#tiptip_holder.tip_top { + padding-bottom: 5px; +} + +#tiptip_holder.tip_bottom { + padding-top: 5px; +} + +#tiptip_holder.tip_right { + padding-left: 5px; +} + +#tiptip_holder.tip_left { + padding-right: 5px; +} + +#tiptip_content { + font-size: 11px; + color: #fff; + text-shadow: 0 0 2px #000; + padding: 4px 8px; + border: 1px solid rgba(255,255,255,0.25); + background-color: rgb(25,25,25); + background-color: rgba(25,25,25,0.92); + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000)); + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + box-shadow: 0 0 3px #555; + -webkit-box-shadow: 0 0 3px #555; + -moz-box-shadow: 0 0 3px #555; +} + +#tiptip_arrow, #tiptip_arrow_inner { + position: absolute; + border-color: transparent; + border-style: solid; + border-width: 6px; + height: 0; + width: 0; +} + +#tiptip_holder.tip_top #tiptip_arrow { + border-top-color: #fff; + border-top-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_bottom #tiptip_arrow { + border-bottom-color: #fff; + border-bottom-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_right #tiptip_arrow { + border-right-color: #fff; + border-right-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_left #tiptip_arrow { + border-left-color: #fff; + border-left-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_top #tiptip_arrow_inner { + margin-top: -7px; + margin-left: -6px; + border-top-color: rgb(25,25,25); + border-top-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_bottom #tiptip_arrow_inner { + margin-top: -5px; + margin-left: -6px; + border-bottom-color: rgb(25,25,25); + border-bottom-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_right #tiptip_arrow_inner { + margin-top: -6px; + margin-left: -5px; + border-right-color: rgb(25,25,25); + border-right-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_left #tiptip_arrow_inner { + margin-top: -6px; + margin-left: -7px; + border-left-color: rgb(25,25,25); + border-left-color: rgba(25,25,25,0.92); +} + +/* Webkit Hacks */ +@media screen and (-webkit-min-device-pixel-ratio:0) { + #tiptip_content { + padding: 4px 8px 5px 8px; + background-color: rgba(45,45,45,0.88); + } + #tiptip_holder.tip_bottom #tiptip_arrow_inner { + border-bottom-color: rgba(45,45,45,0.88); + } + #tiptip_holder.tip_top #tiptip_arrow_inner { + border-top-color: rgba(20,20,20,0.92); + } +} \ No newline at end of file diff --git a/addons/web/static/lib/qweb/qweb2.js b/addons/web/static/lib/qweb/qweb2.js index 34457ade4fd..a6a6da5a6d7 100644 --- a/addons/web/static/lib/qweb/qweb2.js +++ b/addons/web/static/lib/qweb/qweb2.js @@ -4,7 +4,7 @@ // TODO: t-set + t-value + children node == scoped variable ? var QWeb2 = { expressions_cache: {}, - RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','), + RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','), ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,escf,raw,rawf,js,debug,log'.split(','), WORD_REPLACEMENT: { 'and': '&&', diff --git a/addons/web/static/lib/underscore/underscore-min.js b/addons/web/static/lib/underscore/underscore-min.js new file mode 100644 index 00000000000..fadc96ecacb --- /dev/null +++ b/addons/web/static/lib/underscore/underscore-min.js @@ -0,0 +1,30 @@ +// Underscore.js 1.2.2 +// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(b.isFunction(a.isEqual))return a.isEqual(c);if(b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return String(a)==String(c);case "[object Number]":return a=+a,c=+c,a!=a?c!=c:a==0?1/a==1/c:a==c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, +h)&&!f--)break;g=!f}}d.pop();return g}var s=this,F=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,H=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&define.amd? +define("underscore",function(){return b}):s._=b;b.VERSION="1.2.2";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,c){var b=e(a,c);(d[b]||(d[b]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e< +f;){var g=e+f>>1;d(a[g])=0})})};b.difference=function(a,c){return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=H||function(a){if(a!== +Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)? +a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=l.call(arguments)=="[object Arguments]"?function(a){return l.call(a)=="[object Arguments]"}: +function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null}; +b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),function(c){I(c,b[c]=a[c])})};var J=0;b.uniqueId=function(a){var b=J++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g, +interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g, +"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e(a,b)}};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var u=function(a,c){return c?b(a).chain():a},I=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);G.call(a,this._wrapped);return u(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped, +arguments);return u(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return u(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/addons/web/static/lib/underscore/underscore.js b/addons/web/static/lib/underscore/underscore.js index 4f56013259b..5579c07d3d3 100644 --- a/addons/web/static/lib/underscore/underscore.js +++ b/addons/web/static/lib/underscore/underscore.js @@ -1,4 +1,4 @@ -// Underscore.js 1.1.7 +// Underscore.js 1.2.2 // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. // Underscore is freely distributable under the MIT license. // Portions of Underscore are inspired or borrowed from Prototype, @@ -48,19 +48,26 @@ // Create a safe reference to the Underscore object for use below. var _ = function(obj) { return new wrapper(obj); }; - // Export the Underscore object for **CommonJS**, with backwards-compatibility - // for the old `require()` API. If we're not in CommonJS, add `_` to the - // global object. - if (typeof module !== 'undefined' && module.exports) { - module.exports = _; - _._ = _; + // Export the Underscore object for **Node.js** and **"CommonJS"**, with + // backwards-compatibility for the old `require()` API. If we're not in + // CommonJS, add `_` to the global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore', function() { + return _; + }); } else { // Exported as a string, for Closure Compiler "advanced" mode. root['_'] = _; } // Current version. - _.VERSION = '1.1.7'; + _.VERSION = '1.2.2'; // Collection Functions // -------------------- @@ -187,7 +194,7 @@ if (obj == null) return result; if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); each(obj, function(value, index, list) { - if (result |= iterator.call(context, value, index, list)) return breaker; + if (result || (result = iterator.call(context, value, index, list))) return breaker; }); return !!result; }; @@ -198,8 +205,8 @@ var found = false; if (obj == null) return found; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; - any(obj, function(value) { - if (found = value === target) return true; + found = any(obj, function(value) { + return value === target; }); return found; }; @@ -220,6 +227,7 @@ // Return the maximum element or (element-based computation). _.max = function(obj, iterator, context) { if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; var result = {computed : -Infinity}; each(obj, function(value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; @@ -231,6 +239,7 @@ // Return the minimum element (or element-based computation). _.min = function(obj, iterator, context) { if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; var result = {computed : Infinity}; each(obj, function(value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; @@ -239,6 +248,21 @@ return result.value; }; + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + // Sort the object's values by a criterion produced by an iterator. _.sortBy = function(obj, iterator, context) { return _.pluck(_.map(obj, function(value, index, list) { @@ -252,9 +276,11 @@ }), 'value'); }; - // Groups the object's values by a criterion produced by an iterator - _.groupBy = function(obj, iterator) { + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; each(obj, function(value, index) { var key = iterator(value, index); (result[key] || (result[key] = [])).push(value); @@ -298,6 +324,24 @@ return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; }; + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + // Returns everything but the first entry of the array. Aliased as `tail`. // Especially useful on the arguments object. Passing an **index** will return // the rest of the values in the array from that index onward. The **guard** @@ -306,20 +350,15 @@ return slice.call(array, (index == null) || guard ? 1 : index); }; - // Get the last element of an array. - _.last = function(array) { - return array[array.length - 1]; - }; - // Trim out all falsy values from an array. _.compact = function(array) { return _.filter(array, function(value){ return !!value; }); }; // Return a completely flattened version of an array. - _.flatten = function(array) { + _.flatten = function(array, shallow) { return _.reduce(array, function(memo, value) { - if (_.isArray(value)) return memo.concat(_.flatten(value)); + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); memo[memo.length] = value; return memo; }, []); @@ -333,17 +372,23 @@ // 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`. - _.uniq = _.unique = function(array, isSorted) { - return _.reduce(array, function(memo, el, i) { - if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el; + _.uniq = _.unique = function(array, isSorted, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } return memo; }, []); + return result; }; // Produce an array that contains the union: each distinct element from all of // the passed-in arrays. _.union = function() { - return _.uniq(_.flatten(arguments)); + return _.uniq(_.flatten(arguments, true)); }; // Produce an array that contains every item shared between all the @@ -391,7 +436,6 @@ return -1; }; - // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. _.lastIndexOf = function(array, item) { if (array == null) return -1; @@ -426,15 +470,25 @@ // Function (ahem) Functions // ------------------ + // Reusable constructor function for prototype setting. + var ctor = function(){}; + // Create a function bound to a given object (assigning `this`, and arguments, // optionally). Binding with arguments is also known as `curry`. // Delegates to **ECMAScript 5**'s native `Function.bind` if available. // We check for `func.bind` first, to fail fast when `func` is undefined. - _.bind = function(func, obj) { + _.bind = function bind(func, context) { + var bound, args; if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - var args = slice.call(arguments, 2); - return function() { - return func.apply(obj, args.concat(slice.call(arguments))); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; }; }; @@ -470,31 +524,43 @@ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); }; - // Internal function used to implement `_.throttle` and `_.debounce`. - var limit = function(func, wait, debounce) { - var timeout; - return function() { - var context = this, args = arguments; - var throttler = function() { - timeout = null; - func.apply(context, args); - }; - if (debounce) clearTimeout(timeout); - if (debounce || !timeout) timeout = setTimeout(throttler, wait); - }; - }; - // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. _.throttle = function(func, wait) { - return limit(func, wait, false); + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; }; // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. _.debounce = function(func, wait) { - return limit(func, wait, true); + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; }; // Returns a function that will be executed at most one time, no matter how @@ -533,12 +599,12 @@ // Returns a function that will only be executed after being called N times. _.after = function(times, func) { + if (times <= 0) return func(); return function() { if (--times < 1) { return func.apply(this, arguments); } }; }; - // Object Functions // ---------------- @@ -588,6 +654,7 @@ // Create a (shallow-cloned) duplicate of an object. _.clone = function(obj) { + if (!_.isObject(obj)) return obj; return _.isArray(obj) ? obj.slice() : _.extend({}, obj); }; @@ -599,47 +666,103 @@ return obj; }; - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - // Check object identity. - if (a === b) return true; - // Different types? - var atype = typeof(a), btype = typeof(b); - if (atype != btype) return false; - // Basic equality test (watch out for coercions). - if (a == b) return true; - // One is falsy and the other truthy. - if ((!a && b) || (a && !b)) return false; + // Internal recursive comparison function. + function eq(a, b, stack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; // Unwrap any wrapped objects. if (a._chain) a = a._wrapped; if (b._chain) b = b._wrapped; - // One of them implements an isEqual()? - if (a.isEqual) return a.isEqual(b); - if (b.isEqual) return b.isEqual(a); - // Check dates' integer values. - if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime(); - // Both are NaN? - if (_.isNaN(a) && _.isNaN(b)) return false; - // Compare regular expressions. - if (_.isRegExp(a) && _.isRegExp(b)) - return a.source === b.source && - a.global === b.global && - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline; - // If a is not an object by this point, we can't handle it. - if (atype !== 'object') return false; - // Check for different array lengths before comparing contents. - if (a.length && (a.length !== b.length)) return false; - // Nothing else worked, deep compare the contents. - var aKeys = _.keys(a), bKeys = _.keys(b); - // Different object sizes? - if (aKeys.length != bKeys.length) return false; - // Recursive comparison of contents. - for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false; - return true; + // Invoke a custom `isEqual` method if one is provided. + if (_.isFunction(a.isEqual)) return a.isEqual(b); + if (_.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return String(a) == String(b); + case '[object Number]': + a = +a; + b = +b; + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != a ? b != b : (a == 0 ? 1 / a == 1 / b : a == b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ("constructor" in a != "constructor" in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (hasOwnProperty.call(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, []); }; - // Is a given array or object empty? + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. _.isEmpty = function(obj) { if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; @@ -654,7 +777,7 @@ // Is a given value an array? // Delegates to ECMA5's native Array.isArray _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; + return toString.call(obj) == '[object Array]'; }; // Is a given variable an object? @@ -663,44 +786,50 @@ }; // Is a given variable an arguments object? - _.isArguments = function(obj) { - return !!(obj && hasOwnProperty.call(obj, 'callee')); - }; + if (toString.call(arguments) == '[object Arguments]') { + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + } else { + _.isArguments = function(obj) { + return !!(obj && hasOwnProperty.call(obj, 'callee')); + }; + } // Is a given value a function? _.isFunction = function(obj) { - return !!(obj && obj.constructor && obj.call && obj.apply); + return toString.call(obj) == '[object Function]'; }; // Is a given value a string? _.isString = function(obj) { - return !!(obj === '' || (obj && obj.charCodeAt && obj.substr)); + return toString.call(obj) == '[object String]'; }; // Is a given value a number? _.isNumber = function(obj) { - return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed)); + return toString.call(obj) == '[object Number]'; }; - // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript - // that does not equal itself. + // Is the given value `NaN`? _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. return obj !== obj; }; // Is a given value a boolean? _.isBoolean = function(obj) { - return obj === true || obj === false; + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; }; // Is a given value a date? _.isDate = function(obj) { - return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear); + return toString.call(obj) == '[object Date]'; }; // Is the given value a regular expression? _.isRegExp = function(obj) { - return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false)); + return toString.call(obj) == '[object RegExp]'; }; // Is a given value equal to null? @@ -733,6 +862,11 @@ for (var i = 0; i < n; i++) iterator.call(context, i); }; + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + // Add your own custom functions to the Underscore object, ensuring that // they're correctly added to the OOP wrapper as well. _.mixin = function(obj) { @@ -753,7 +887,8 @@ // following template settings to use alternative delimiters. _.templateSettings = { evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g }; // JavaScript micro-templating, similar to John Resig's implementation. @@ -765,19 +900,22 @@ 'with(obj||{}){__p.push(\'' + str.replace(/\\/g, '\\\\') .replace(/'/g, "\\'") + .replace(c.escape, function(match, code) { + return "',_.escape(" + code.replace(/\\'/g, "'") + "),'"; + }) .replace(c.interpolate, function(match, code) { return "'," + code.replace(/\\'/g, "'") + ",'"; }) .replace(c.evaluate || null, function(match, code) { return "');" + code.replace(/\\'/g, "'") - .replace(/[\r\n\t]/g, ' ') + "__p.push('"; + .replace(/[\r\n\t]/g, ' ') + ";__p.push('"; }) .replace(/\r/g, '\\r') .replace(/\n/g, '\\n') .replace(/\t/g, '\\t') + "');}return __p.join('');"; - var func = new Function('obj', tmpl); - return data ? func(data) : func; + var func = new Function('obj', '_', tmpl); + return data ? func(data, _) : function(data) { return func(data, _) }; }; // The OOP Wrapper @@ -836,4 +974,4 @@ return this._wrapped; }; -})(); +}).call(this); diff --git a/addons/web/static/lib/underscore/underscore.string.js b/addons/web/static/lib/underscore/underscore.string.js index d15c1f1f7ce..99966c3f475 100644 --- a/addons/web/static/lib/underscore/underscore.string.js +++ b/addons/web/static/lib/underscore/underscore.string.js @@ -1,20 +1,14 @@ // Underscore.string // (c) 2010 Esa-Matti Suuronen // Underscore.strings is freely distributable under the terms of the MIT license. -// Documentation: https://github.com/edtsech/underscore.string +// Documentation: https://github.com/epeli/underscore.string // Some code is borrowed from MooTools and Alexandru Marasteanu. -// Version 1.1.6 - +// Version 1.2.0 (function(root){ 'use strict'; - if (typeof _ != 'undefined') { - var _reverse = _().reverse, - _include = _.include; - } - // Defining helper functions. var nativeTrim = String.prototype.trim; @@ -22,7 +16,7 @@ var parseNumber = function(source) { return source * 1 || 0; }; var strRepeat = function(i, m) { - for (var o = []; m > 0; o[--m] = i); + for (var o = []; m > 0; o[--m] = i) {} return o.join(''); }; @@ -174,6 +168,8 @@ var _s = { + VERSION: '1.2.0', + isBlank: sArgs(function(str){ return (/^\s*$/).test(str); }), @@ -235,18 +231,10 @@ return arr.join(''); }), - includes: sArgs(function(str, needle){ + include: sArgs(function(str, needle){ return str.indexOf(needle) !== -1; }), - include: function(obj, needle) { - if (!_include || (/string|number/).test(typeof obj)) { - return this.includes(obj, needle); - } else { - return _include(obj, needle); - } - }, - join: sArgs(function(sep) { var args = slice(arguments); return args.join(args.shift()); @@ -256,13 +244,9 @@ return str.split("\n"); }), - reverse: function(obj){ - if (!_reverse || (/string|number/).test(typeof obj)) { - return Array.prototype.reverse.apply(String(obj).split('')).join(''); - } else { - return _reverse.call(_(obj)); - } - }, + reverse: sArgs(function(str){ + return Array.prototype.reverse.apply(String(str).split('')).join(''); + }), splice: sArgs(function(str, i, howmany, substr){ var arr = str.split(''); @@ -309,6 +293,10 @@ return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/^([A-Z]+)/, '-$1').replace(/\_|\s+/g, '-').toLowerCase(); }, + humanize: function(str){ + return _s.capitalize(this.underscored(str).replace(/_id$/,'').replace(/_/g, ' ')); + }, + trim: sArgs(function(str, characters){ if (!characters && nativeTrim) { return nativeTrim.call(str); @@ -333,6 +321,27 @@ return str.length > length ? str.slice(0,length) + truncateStr : str; }), + /** + * _s.prune: a more elegant version of truncate + * prune extra chars, never leaving a half-chopped word. + * @author github.com/sergiokas + */ + prune: sArgs(function(str, length, pruneStr){ + pruneStr = pruneStr || '...'; + length = parseNumber(length); + var pruned = ''; + + // Check if we're in the middle of a word + if( str.substring(length-1, length+1).search(/^\w\w$/) === 0 ) + pruned = _s.rtrim(str.slice(0,length).replace(/([\W][\w]*)$/,'')); + else + pruned = _s.rtrim(str.slice(0,length)); + + pruned = pruned.replace(/\W+$/,''); + + return (pruned.length+pruneStr.length>str.length) ? str : pruned + pruneStr; + }), + words: function(str, delimiter) { return String(str).split(delimiter || " "); }, @@ -409,31 +418,51 @@ strLeftBack: sArgs(function(sourceStr, sep){ var pos = sourceStr.lastIndexOf(sep); return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr; - }) + }), + + exports: function() { + var result = {}; + + for (var prop in this) { + if (!this.hasOwnProperty(prop) || prop == 'include' || prop == 'contains' || prop == 'reverse') continue; + result[prop] = this[prop]; + } + + return result; + } }; // Aliases - _s.strip = _s.trim; - _s.lstrip = _s.ltrim; - _s.rstrip = _s.rtrim; - _s.center = _s.lrpad; - _s.ljust = _s.lpad; - _s.rjust = _s.rpad; + _s.strip = _s.trim; + _s.lstrip = _s.ltrim; + _s.rstrip = _s.rtrim; + _s.center = _s.lrpad; + _s.ljust = _s.lpad; + _s.rjust = _s.rpad; + _s.contains = _s.include; // CommonJS module is defined - if (typeof module !== 'undefined' && module.exports) { - // Export module - module.exports = _s; + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + // Export module + module.exports = _s; + } + exports._s = _s; // Integrate with Underscore.js } else if (typeof root._ !== 'undefined') { - root._.mixin(_s); + // root._.mixin(_s); + root._.string = _s; + root._.str = root._.string; // Or define it } else { - root._ = _s; + root._ = { + string: _s, + str: _s + }; } }(this || window)); diff --git a/addons/web/static/lib/underscore/underscore.string.min.js b/addons/web/static/lib/underscore/underscore.string.min.js new file mode 100644 index 00000000000..dfc1b46b082 --- /dev/null +++ b/addons/web/static/lib/underscore/underscore.string.min.js @@ -0,0 +1,14 @@ +(function(k){var o=String.prototype.trim,l=function(a,b){for(var c=[];b>0;c[--b]=a);return c.join("")},d=function(a){return function(){for(var b=Array.prototype.slice.call(arguments),c=0;c=0?"+"+f:f;i=g[4]?g[4]=="0"?"0":g[4].charAt(1):" ";k=g[6]-String(f).length;i=g[6]?l(i,k):"";j.push(g[5]?f+i:i+f)}return j.join("")};b.cache= +{};b.parse=function(a){for(var b=[],e=[],d=0;a;){if((b=/^[^\x25]+/.exec(a))!==null)e.push(b[0]);else if((b=/^\x25{2}/.exec(a))!==null)e.push("%");else if((b=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(a))!==null){if(b[2]){d|=1;var f=[],j=b[2],h=[];if((h=/^([a-z_][a-z_\d]*)/i.exec(j))!==null)for(f.push(h[1]);(j=j.substring(h[0].length))!=="";)if((h=/^\.([a-z_][a-z_\d]*)/i.exec(j))!==null)f.push(h[1]);else if((h=/^\[(\d+)\]/.exec(j))!==null)f.push(h[1]); +else throw"[_.sprintf] huh?";else throw"[_.sprintf] huh?";b[2]=f}else d|=2;if(d===3)throw"[_.sprintf] mixing positional and named placeholders is not (yet) supported";e.push(b)}else throw"[_.sprintf] huh?";a=a.substring(b[0].length)}return e};return b}(),e={VERSION:"1.2.0",isBlank:d(function(a){return/^\s*$/.test(a)}),stripTags:d(function(a){return a.replace(/<\/?[^>]+>/ig,"")}),capitalize:d(function(a){return a.charAt(0).toUpperCase()+a.substring(1).toLowerCase()}),chop:d(function(a,b){for(var b= +b*1||0||a.length,c=[],e=0;e=0&&c++,d=d+(e>=0?e:0)+b.length;return c}),chars:d(function(a){return a.split("")}),escapeHTML:d(function(a){return a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}),unescapeHTML:d(function(a){return a.replace(/</g,"<").replace(/>/g, +">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}),escapeRegExp:d(function(a){return a.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1")}),insert:d(function(a,b,c){a=a.split("");a.splice(b*1||0,0,c);return a.join("")}),include:d(function(a,b){return a.indexOf(b)!==-1}),join:d(function(a){var b=Array.prototype.slice.call(arguments);return b.join(b.shift())}),lines:d(function(a){return a.split("\n")}),reverse:d(function(a){return Array.prototype.reverse.apply(String(a).split("")).join("")}), +splice:d(function(a,b,c,e){a=a.split("");a.splice(b*1||0,c*1||0,e);return a.join("")}),startsWith:d(function(a,b){return a.length>=b.length&&a.substring(0,b.length)===b}),endsWith:d(function(a,b){return a.length>=b.length&&a.substring(a.length-b.length)===b}),succ:d(function(a){var b=a.split("");b.splice(a.length-1,1,String.fromCharCode(a.charCodeAt(a.length-1)+1));return b.join("")}),titleize:d(function(a){for(var a=a.split(" "),b,c=0;cb?a.slice(0,b)+(c||"..."):a}),prune:d(function(a,b,c){var c=c||"...",b=b*1||0,d="",d=a.substring(b- +1,b+1).search(/^\w\w$/)===0?e.rtrim(a.slice(0,b).replace(/([\W][\w]*)$/,"")):e.rtrim(a.slice(0,b)),d=d.replace(/\W+$/,"");return d.length+c.length>a.length?a:d+c}),words:function(a,b){return String(a).split(b||" ")},pad:d(function(a,b,c,e){var d="",d=0,b=b*1||0;c?c.length>1&&(c=c.charAt(0)):c=" ";switch(e){case "right":d=b-a.length;d=l(c,d);a+=d;break;case "both":d=b-a.length;d={left:l(c,Math.ceil(d/2)),right:l(c,Math.floor(d/2))};a=d.left+a+d.right;break;default:d=b-a.length,d=l(c,d),a=d+a}return a}), +lpad:function(a,b,c){return e.pad(a,b,c)},rpad:function(a,b,c){return e.pad(a,b,c,"right")},lrpad:function(a,b,c){return e.pad(a,b,c,"both")},sprintf:m,vsprintf:function(a,b){b.unshift(a);return m.apply(null,b)},toNumber:function(a,b){var c;c=(a*1||0).toFixed(b*1||0)*1||0;return!(c===0&&a!=="0"&&a!==0)?c:Number.NaN},strRight:d(function(a,b){var c=!b?-1:a.indexOf(b);return c!=-1?a.slice(c+b.length,a.length):a}),strRightBack:d(function(a,b){var c=!b?-1:a.lastIndexOf(b);return c!=-1?a.slice(c+b.length, +a.length):a}),strLeft:d(function(a,b){var c=!b?-1:a.indexOf(b);return c!=-1?a.slice(0,c):a}),strLeftBack:d(function(a,b){var c=a.lastIndexOf(b);return c!=-1?a.slice(0,c):a}),exports:function(){var a={},b;for(b in this)if(this.hasOwnProperty(b)&&!(b=="include"||b=="contains"||b=="reverse"))a[b]=this[b];return a}};e.strip=e.trim;e.lstrip=e.ltrim;e.rstrip=e.rtrim;e.center=e.lrpad;e.ljust=e.lpad;e.rjust=e.rpad;e.contains=e.include;if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)module.exports= +e;exports._s=e}else typeof k._!=="undefined"?(k._.string=e,k._.str=k._.string):k._={string:e,str:e}})(this||window); diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 01f4b11f4d3..cad536c0f1f 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -26,7 +26,7 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio margin: 0; } -.openerp .oe-number { +.openerp .oe-listview .oe-number { text-align: right !important; } .openerp .oe_hide { @@ -713,7 +713,26 @@ label.error { .openerp .oe-listview th { vertical-align: middle; text-align: left; + padding: 1px 2px; } +.openerp .oe-listview th.oe-record-selector, +.openerp .oe-listview td.oe-button, +.openerp .oe-listview td.oe-record-delete { + padding: 0 1px; +} + +/* Could use :not selectors if they were supported by MSIE8... */ +.openerp .oe-listview tbody td { + border-left: 1px solid #dadada; +} +.openerp .oe-listview tbody td:first-child, +.openerp .oe-listview tbody td.oe-button, +.openerp .oe-listview tbody td.oe-button+td, +.openerp .oe-listview tbody th.oe-record-selector+td, +.openerp .oe-listview tbody td.oe-record-delete { + border-left: none; +} + .openerp .oe-listview td.oe-record-delete { text-align: right; } @@ -790,33 +809,33 @@ label.error { also on the first and last children of the first and last row */ .openerp .oe-listview table.oe-listview-content { - -webkit-border-radius: 7px; - -moz-border-radius: 7px; - border-radius: 7px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } .openerp .oe-listview table.oe-listview-content thead tr:first-child th:first-child { - -webkit-border-top-left-radius: 7px; - -moz-border-radius-topleft: 7px; - border-top-left-radius: 7px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; } .openerp .oe-listview table.oe-listview-content thead tr:first-child th:last-child { - -webkit-border-top-right-radius: 7px; - -moz-border-radius-topright: 7px; - border-top-right-radius: 7px; + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; } .openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:first-child, .openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:first-child, .openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child { - -webkit-border-bottom-left-radius: 7px; - -moz-border-radius-bottomleft: 7px; - border-bottom-left-radius: 7px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; } .openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:last-child, .openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:last-child, .openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 7px; - -moz-border-radius-bottomright: 7px; - border-bottom-right-radius: 7px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; } /* Notebook */ @@ -825,6 +844,9 @@ label.error { background: none; border-width: 0; } +.openerp .oe_form_notebook .ui-tabs-panel { + padding: 4px; +} .openerp .oe_form_notebook ul.ui-tabs-nav { padding-left: 0; background: transparent; @@ -852,6 +874,17 @@ label.error { .openerp table.oe_frame { color: #4c4c4c; } +.openerp fieldset.oe_group_box { + border: 1px solid #AAAAAA; + moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + background: #F9F9F9; + padding: 4px; +} +.openerp fieldset.oe_group_box legend { + font-weight: bold; +} .openerp td.oe_form_frame_cell { padding: 2px; position: relative; @@ -875,6 +908,22 @@ label.error { .openerp label.oe_label_help { cursor: help; } +.openerp #tiptip_content { + font-size: 12px; +} +.openerp .oe_tooltip_string { + color: #FD5; + font-weight: bold; + font-size: 13px; +} +.openerp .oe_tooltip_technical { + padding: 0 0 4px 0; + margin: 5px 0 0 15px; + list-style: circle; +} +.openerp .oe_tooltip_technical_title { + font-weight: bold; +} .openerp .oe_forms label.oe_label, .openerp .oe_forms label.oe_label_help { margin: 3px 0 0 10px; @@ -918,20 +967,25 @@ label.error { .openerp .oe_forms textarea { resize:vertical; } -.openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .button { +.openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .oe_button { height: 22px; } .openerp .oe_forms input.field_datetime { min-width: 11em; } -.openerp .oe_forms.oe_frame .oe_datepicker_root { - width: 100%; -} -.openerp .oe_forms .button { +.openerp .oe_forms .oe_button { color: #4c4c4c; white-space: nowrap; + min-width: 100%; + width: 100%; } -.openerp .oe_forms .button span { +@-moz-document url-prefix() { + /* Strange firefox behaviour on width: 100% + white-space: nowrap */ + .openerp .oe_forms .oe_button { + width: auto; + } +} +.openerp .oe_forms .oe_button span { position: relative; vertical-align: top; } @@ -940,13 +994,20 @@ label.error { cursor: pointer; right: 5px; top: 3px; + z-index: 2; +} +.openerp .oe_datepicker_container { + position: absolute; + top: 0; + right: 0; + display: none; } .openerp .oe_datepicker_root { position: relative; display: inline-block; } -.openerp .oe_datepicker_root input[type="text"] { - min-width: 160px; +.openerp .oe_forms.oe_frame .oe_datepicker_root { + width: 100%; } .openerp .oe_input_icon_disabled { position: absolute; @@ -954,7 +1015,7 @@ label.error { opacity: 0.5; filter:alpha(opacity=50); right: 5px; - top: 5px; + top: 3px; } .openerp img.oe_field_translate { margin-left: -21px; @@ -1249,6 +1310,14 @@ label.error { background: 1px 3px url(/web/static/src/img/icons/gtk-print.png) no-repeat; } +.openerp .oe-running-kitten { + display: none; +} + +.openerp.kitten-mode-activated .oe-running-kitten { + display: inherit; +} + .openerp.kitten-mode-activated .main_table { background: url(http://placekitten.com/g/1500/800) repeat; } diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 25b73ee59d5..f10ee9376f6 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -158,7 +158,7 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ }, on_managed_error: function(error) { $('
' + QWeb.render('DialogWarning', {error: error}) + '
').dialog({ - title: "OpenERP " + _.capitalize(error.type), + title: "OpenERP " + _.str.capitalize(error.type), buttons: { Ok: function() { $(this).dialog("close"); @@ -168,7 +168,7 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ }, on_traceback: function(error) { var dialog = new openerp.web.Dialog(this, { - title: "OpenERP " + _.capitalize(error.type), + title: "OpenERP " + _.str.capitalize(error.type), autoOpen: true, width: '90%', height: '90%', @@ -184,7 +184,8 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ } }); -openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{ +openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{ + template: 'Loading', /** * @constructs openerp.web.Loading * @extends openerp.web.Widget @@ -192,8 +193,8 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# * @param parent * @param element_id */ - init: function(parent, element_id) { - this._super(parent, element_id); + init: function(parent) { + this._super(parent); this.count = 0; this.blocked_ui = false; this.session.on_rpc_request.add_first(this.on_rpc_event, 1); @@ -210,12 +211,13 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# } this.count += increment; - if (this.count) { + if (this.count > 0) { //this.$element.html(QWeb.render("Loading", {})); this.$element.html("Loading ("+this.count+")"); this.$element.show(); this.widget_parent.$element.addClass('loading'); } else { + this.count = 0; clearTimeout(this.long_running_timer); // Don't unblock if blocked by somebody else if (self.blocked_ui) { @@ -242,10 +244,8 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database this.$option_id = $('#' + option_id); }, start: function() { + this._super(); this.$element.html(QWeb.render("Database", this)); - this.$element.closest(".openerp") - .removeClass("login-mode") - .addClass("database_block"); var self = this; var fetch_db = this.rpc("/web/database/get_list", {}, function(result) { @@ -266,23 +266,30 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database this.$element.find('#db-restore').click(this.do_restore); this.$element.find('#db-change-password').click(this.do_change_password); this.$element.find('#back-to-login').click(function() { - self.stop(); + self.hide(); }); }, stop: function () { + this.hide(); this.$option_id.empty(); this.$element .find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login') .unbind('click') .end() - .closest(".openerp") - .addClass("login-mode") - .removeClass("database_block") - .end() .empty(); this._super(); }, + show: function () { + this.$element.closest(".openerp") + .removeClass("login-mode") + .addClass("database_block"); + }, + hide: function () { + this.$element.closest(".openerp") + .addClass("login-mode") + .removeClass("database_block") + }, /** * Converts a .serializeArray() result into a dict. Does not bother folding * multiple identical keys into an array, last key wins. @@ -368,6 +375,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database } self.db_list.push(self.to_object(fields)['db_name']); self.db_list.sort(); + self.widget_parent.set_db_list(self.db_list); var form_obj = self.to_object(fields); self.wait_for_newdb(result, { password: form_obj['super_admin_pwd'], @@ -397,6 +405,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database } $db_list.find(':selected').remove(); self.db_list.splice(_.indexOf(self.db_list, db, true), 1); + self.widget_parent.set_db_list(self.db_list); self.do_notify("Dropping database", "The database '" + db + "' has been dropped"); }); } @@ -529,16 +538,16 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ var self = this; this.database = new openerp.web.Database( this, "oe_database", "oe_db_options"); + this.database.start(); this.$element.find('#oe-db-config').click(function() { - self.database.start(); + self.database.show(); }); this.$element.find("form").submit(this.on_submit); this.rpc("/web/database/get_list", {}, function(result) { - var tpl = openerp.web.qweb.render('Login_dblist', {db_list: result.db_list, selected_db: self.selected_db}); - self.$element.find("input[name=db]").replaceWith(tpl) + self.set_db_list(result.db_list); }, function(error, event) { if (error.data.fault_code === 'AccessDenied') { @@ -547,6 +556,15 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ }); }, + stop: function () { + this.database.stop(); + this._super(); + }, + set_db_list: function (list) { + this.$element.find("[name=db]").replaceWith( + openerp.web.qweb.render('Login_dblist', { + db_list: list, selected_db: this.selected_db})) + }, on_login_invalid: function() { this.$element.closest(".openerp").addClass("login-mode"); }, @@ -966,7 +984,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie this.$element.html(QWeb.render("Interface", params)); this.notification = new openerp.web.Notification(this); - this.loading = new openerp.web.Loading(this,"oe_loading"); + this.loading = new openerp.web.Loading(this); this.crashmanager = new openerp.web.CrashManager(); this.header = new openerp.web.Header(this); @@ -990,6 +1008,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie start: function() { this._super.apply(this, arguments); this.notification.prependTo(this.$element); + this.loading.appendTo($('#oe_loading')); this.header.appendTo($("#oe_header")); this.session.start(); this.login.appendTo($('#oe_login')); @@ -1095,7 +1114,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie this.action_manager.do_action(action); }, do_about: function() { - }, + } }); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 1929c573e42..d271fbc430e 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -125,7 +125,11 @@ openerp.web.callback = function(obj, method) { callback.callback_chain.splice(i, 1); i -= 1; } - r = c.callback.apply(c.self, c.args.concat(args)); + var result = c.callback.apply(c.self, c.args.concat(args)); + if (c.callback === method) { + // return the result of the original method + r = result; + } // TODO special value to stop the chain // openerp.web.callback_stop } @@ -354,6 +358,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. this.debug = (window.location.search.indexOf('?debug') !== -1); this.session_id = false; this.uid = false; + this.username = false; this.user_context= {}; this.db = false; this.module_list = []; @@ -484,10 +489,13 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; var params = { db: db, login: login, password: password }; return this.rpc("/web/session/login", params, function(result) { - self.session_id = result.session_id; - self.uid = result.uid; - self.user_context = result.context; - self.db = result.db; + _.extend(self, { + session_id: result.session_id, + uid: result.uid, + user_context: result.context, + db: result.db, + username: result.login + }); self.session_save(); self.on_session_valid(); return true; @@ -501,13 +509,24 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; this.session_id = this.get_cookie('session_id'); return this.rpc("/web/session/get_session_info", {}).then(function(result) { - self.uid = result.uid; - self.user_context = result.context; - self.db = result.db; - if (self.uid) - self.on_session_valid(); - else - self.on_session_invalid(); + // If immediately follows a login (triggered by trying to restore + // an invalid session or no session at all), refresh session data + // (should not change, but just in case...) but should not call + // on_session_valid again as it triggers reloading the menu + var already_logged = self.uid; + _.extend(self, { + uid: result.uid, + user_context: result.context, + db: result.db, + username: result.login + }); + if (!already_logged) { + if (self.uid) { + self.on_session_valid(); + } else { + self.on_session_invalid(); + } + } }, function() { self.on_session_invalid(); }); @@ -716,7 +735,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. if (parseInt(cookie_val, 10) !== token) { continue; } // clear cookie - document.cookie = _.sprintf("%s=;expires=%s;path=/", + document.cookie = _.str.sprintf("%s=;expires=%s;path=/", cookie_name, new Date().toGMTString()); if (options.success) { options.success(); } complete(); @@ -798,7 +817,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W */ tag_name: 'div', /** - * Construct the widget and set its parent if a parent is given. + * Constructs the widget and sets its parent if a parent is given. * * @constructs openerp.web.Widget * @extends openerp.web.CallbackEnabled @@ -830,7 +849,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W this.widget_is_stopped = false; }, /** - * Render the current widget and appends it to the given jQuery object or Widget. + * Renders the current widget and appends it to the given jQuery object or Widget. * * @param target A jQuery object or a Widget instance. */ @@ -841,7 +860,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W }, target); }, /** - * Render the current widget and prepends it to the given jQuery object or Widget. + * Renders the current widget and prepends it to the given jQuery object or Widget. * * @param target A jQuery object or a Widget instance. */ @@ -852,7 +871,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W }, target); }, /** - * Render the current widget and inserts it after to the given jQuery object or Widget. + * Renders the current widget and inserts it after to the given jQuery object or Widget. * * @param target A jQuery object or a Widget instance. */ @@ -863,7 +882,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W }, target); }, /** - * Render the current widget and inserts it before to the given jQuery object or Widget. + * Renders the current widget and inserts it before to the given jQuery object or Widget. * * @param target A jQuery object or a Widget instance. */ @@ -873,6 +892,16 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W self.$element.insertBefore(t); }, target); }, + /** + * Renders the current widget and replaces the given jQuery object. + * + * @param target A jQuery object or a Widget instance. + */ + replace: function(target) { + return this._render_and_insert(_.bind(function(t) { + this.$element.replaceAll(t); + }, this), target); + }, _render_and_insert: function(insertion, target) { this.render_element(); if (target instanceof openerp.web.Widget) @@ -887,8 +916,11 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W */ render_element: function() { var rendered = this.render(); - if (rendered || rendered === "") - this.$element = $(rendered); + if (rendered) { + var elem = $(rendered); + this.$element.replaceWith(elem); + this.$element = elem; + } return this; }, /** @@ -900,7 +932,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W render: function (additional) { if (this.template) return openerp.web.qweb.render(this.template, _.extend({widget: this}, additional || {})); - return false; + return null; }, /** * Method called after rendering. Mostly used to bind actions, perform asynchronous @@ -912,16 +944,10 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W * @returns {jQuery.Deferred} */ start: function() { - /* The default implementation is only useful for retro-compatibility, it is - not necessary to call it using _super() when using Widget for new components. */ - if (!this.$element) { - var tmp = document.getElementById(this.element_id); - this.$element = tmp ? $(tmp) : undefined; - } return $.Deferred().done().promise(); }, /** - * Destroys the current widget, also destroy all its children before destroying itself. + * Destroys the current widget, also destroys all its children before destroying itself. */ stop: function() { _.each(_.clone(this.widget_children), function(el) { @@ -937,7 +963,7 @@ openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.W this.widget_is_stopped = true; }, /** - * Inform the action manager to do an action. Of course, this suppose that + * Informs the action manager to do an action. This supposes that * the action manager can be found amongst the ancestors of the current widget. * If that's not the case this method will simply return `false`. */ @@ -996,7 +1022,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we this.parameters = {"direction": 'ltr', "date_format": '%m/%d/%Y', "time_format": '%H:%M:%S', - "grouping": "[]", + "grouping": [], "decimal_point": ".", "thousands_sep": ","}; }, @@ -1012,6 +1038,8 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we }); if (translation_bundle.lang_parameters) { this.parameters = translation_bundle.lang_parameters; + this.parameters.grouping = py.eval( + this.parameters.grouping).toJSON(); } }, add_module_translation: function(mod) { @@ -1056,7 +1084,7 @@ openerp.web.qweb.format_text_node = function(s) { if (translation && translation.value === 'off') { return s; } - var ts = _.trim(s); + var ts = _.str.trim(s); if (ts.length === 0) { return s; } diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index f4509c82a81..1f2520ee774 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -119,17 +119,18 @@ openerp.web.ContainerDataGroup = openerp.web.DataGroup.extend( /** @lends opener aggregates[key] = value || 0; }); + var group_size = fixed_group[field_name + '_count'] || fixed_group.__count || 0; + var leaf_group = fixed_group.__context.group_by.length === 0; return { __context: fixed_group.__context, __domain: fixed_group.__domain, grouped_on: field_name, // if terminal group (or no group) and group_by_no_leaf => use group.__count - length: fixed_group[field_name + '_count'] || fixed_group.__count, + length: group_size, value: fixed_group[field_name], - - openable: !(this.context['group_by_no_leaf'] - && fixed_group.__context.group_by.length === 0), + // A group is openable if it's not a leaf in group_by_no_leaf mode + openable: !(leaf_group && this.context['group_by_no_leaf']), aggregates: aggregates }; @@ -315,7 +316,7 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet def.reject(); } else { fields = fields || false; - return this.read_ids([this.ids[this.index]], fields).then(function(records) { + this.read_ids([this.ids[this.index]], fields).then(function(records) { def.resolve(records[0]); }, function() { def.reject.apply(def, arguments); @@ -729,6 +730,19 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ return_records(); } return completion.promise(); + }, + call_button: function (method, args, callback, error_callback) { + var id = args[0][0], index; + for(var i=0, len=this.cache.length; i} indices + * @param {String} separator + * @returns {String} + */ +openerp.web.intersperse = function (str, indices, separator) { + separator = separator || ''; + var result = [], last = str.length; + + for(var i=0; i stop + break; + } else if (section === 0) { + // repeat previous section forever + //noinspection AssignmentToForLoopParameterJS + section = indices[--i]; + } + result.push(str.substring(last-section, last)); + last -= section; + } + + var s = str.substring(0, last); + if (s) { result.push(s); } + return result.reverse().join(separator); +}; +/** + * Insert "thousands" separators in the provided number (which is actually + * a string) + * + * @param {String} num + * @returns {String} + */ +openerp.web.insert_thousand_seps = function (num) { + var negative = num[0] === '-'; + num = (negative ? num.slice(1) : num); + return (negative ? '-' : '') + openerp.web.intersperse( + num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep); +}; /** * Formats a single atomic value based on a field descriptor * @@ -16,25 +76,34 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { if (typeof value === 'number' && isNaN(value)) { value = false; } + //noinspection FallthroughInSwitchStatementJS switch (value) { + case '': + if (descriptor.type === 'char') { + return ''; + } + console.warn('Field', descriptor, 'had an empty string as value, treating as false...'); case false: case Infinity: case -Infinity: return value_if_empty === undefined ? '' : value_if_empty; } + var l10n = _t.database.parameters; switch (descriptor.widget || descriptor.type) { case 'integer': - return _.sprintf('%d', value); + return openerp.web.insert_thousand_seps( + _.str.sprintf('%d', value)); case 'float': var precision = descriptor.digits ? descriptor.digits[1] : 2; - return _.sprintf('%.' + precision + 'f', value) - .replace('.', openerp.web._t.database.parameters.decimal_point); + var formatted = _.str.sprintf('%.' + precision + 'f', value).split('.'); + formatted[0] = openerp.web.insert_thousand_seps(formatted[0]); + return formatted.join(l10n.decimal_point); case 'float_time': - return _.sprintf("%02d:%02d", + return _.str.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); case 'progressbar': - return _.sprintf( + return _.str.sprintf( '%.2f%%', value, value); case 'many2one': @@ -43,29 +112,17 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { case 'datetime': if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - try { - return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, - Date.CultureInfo.formatPatterns.longTime)); - } catch (e) { - return value.format("%m/%d/%Y %H:%M:%S"); - } - return value; + + return value.format(l10n.date_format + + ' ' + l10n.time_format); case 'date': if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - try { - return value.toString(Date.CultureInfo.formatPatterns.shortDate); - } catch (e) { - return value.format("%m/%d/%Y"); - } + return value.format(l10n.date_format); case 'time': if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - try { - return value.toString(Date.CultureInfo.formatPatterns.longTime); - } catch (e) { - return value.format("%H:%M:%S"); - } + return value.format(l10n.time_format); case 'selection': // Each choice is [value, label] var result = _(descriptor.selection).detect(function (choice) { @@ -79,6 +136,8 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { }; openerp.web.parse_value = function (value, descriptor, value_if_empty) { + var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format), + time_pattern = Date.normalizeFormat(_t.database.parameters.time_format); switch (value) { case false: case "": @@ -93,7 +152,7 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { } while(tmp !== value); tmp = Number(value); if (isNaN(tmp)) - throw value + " is not a correct integer"; + throw new Error(value + " is not a correct integer"); return tmp; case 'float': var tmp = Number(value); @@ -107,42 +166,42 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { } while(tmp !== tmp2); tmp = Number(tmp); if (isNaN(tmp)) - throw value + " is not a correct float"; + throw new Error(value + " is not a correct float"); return tmp; case 'float_time': - var tmp = value.split(":"); - if (tmp.length != 2) - throw value + " is not a correct float_time"; - var tmp1 = openerp.web.parse_value(tmp[0], {type: "integer"}); - var tmp2 = openerp.web.parse_value(tmp[1], {type: "integer"}); - return tmp1 + (tmp2 / 60); + var float_time_pair = value.split(":"); + if (float_time_pair.length != 2) + return openerp.web.parse_value(value, {type: "float"}); + var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"}); + var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"}); + return hours + (minutes / 60); case 'progressbar': return openerp.web.parse_value(value, {type: "float"}); case 'datetime': - var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, - Date.CultureInfo.formatPatterns.longTime)); - if (tmp !== null) - return openerp.web.datetime_to_str(tmp); - tmp = Date.parse(value); - if (tmp !== null) - return openerp.web.datetime_to_str(tmp); - throw value + " is not a valid datetime"; + var datetime = Date.parseExact( + value, (date_pattern + ' ' + time_pattern)); + if (datetime !== null) + return openerp.web.datetime_to_str(datetime); + datetime = Date.parse(value); + if (datetime !== null) + return openerp.web.datetime_to_str(datetime); + throw new Error(value + " is not a valid datetime"); case 'date': - var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.shortDate); - if (tmp !== null) - return openerp.web.date_to_str(tmp); - tmp = Date.parse(value); - if (tmp !== null) - return openerp.web.date_to_str(tmp); - throw value + " is not a valid date"; + var date = Date.parseExact(value, date_pattern); + if (date !== null) + return openerp.web.date_to_str(date); + date = Date.parse(value); + if (date !== null) + return openerp.web.date_to_str(date); + throw new Error(value + " is not a valid date"); case 'time': - var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.longTime); - if (tmp !== null) - return openerp.web.time_to_str(tmp); - tmp = Date.parse(value); - if (tmp !== null) - return openerp.web.time_to_str(tmp); - throw value + " is not a valid time"; + var time = Date.parseExact(value, time_pattern); + if (time !== null) + return openerp.web.time_to_str(time); + time = Date.parse(value); + if (time !== null) + return openerp.web.time_to_str(time); + throw new Error(value + " is not a valid time"); } return value; }; @@ -157,7 +216,7 @@ openerp.web.auto_str_to_date = function(value, type) { try { return openerp.web.str_to_time(value); } catch(e) {} - throw "'" + value + "' is not a valid date, datetime nor time" + throw new Error("'" + value + "' is not a valid date, datetime nor time"); }; openerp.web.auto_date_to_str = function(value, type) { @@ -169,7 +228,7 @@ openerp.web.auto_date_to_str = function(value, type) { case 'time': return openerp.web.time_to_str(value); default: - throw type + " is not convertible to date, datetime nor time" + throw new Error(type + " is not convertible to date, datetime nor time"); } }; diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 18e035a40b8..f95801975b5 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -1,5 +1,6 @@ openerp.web.search = function(openerp) { -var QWeb = openerp.web.qweb; +var QWeb = openerp.web.qweb, + _t = openerp.web._t; openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.SearchView# */{ template: "EmptyComponent", @@ -40,7 +41,11 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search if (this.headless) { this.ready.resolve(); } else { - this.rpc("/web/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded); + this.rpc("/web/searchview/load", { + model: this.model, + view_id: this.view_id, + context: this.dataset.get_context() + }, this.on_loaded); } return this.ready.promise(); }, @@ -134,6 +139,12 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search } }, on_loaded: function(data) { + if (data.fields_view.type !== 'search' || + data.fields_view.arch.tag !== 'search') { + throw new Error(_.str.sprintf( + "Got non-search view after asking for a search view: type %s, arch root %s", + data.fields_view.type, data.fields_view.arch.tag)); + } var self = this, lines = this.make_widgets( data.fields_view['arch'].children, @@ -211,12 +222,12 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search var $dial = $(dial_html); $dial.dialog({ modal: true, - title: "Filter Entry", - buttons: { - Cancel: function() { + title: _t("Filter Entry"), + buttons: [ + {text: _t("Cancel"), click: function() { $(this).dialog("close"); - }, - OK: function() { + }}, + {text: _t("OK"), click: function() { $(this).dialog("close"); var name = $(this).find("input").val(); self.rpc('/web/searchview/save_filter', { @@ -227,8 +238,8 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search }).then(function() { self.reload_managed_filters(); }); - } - } + }} + ] }); } else { // manage_filters select.val("_filters"); @@ -337,7 +348,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search * @param {Array} errors a never-empty array of error objects */ on_invalid: function (errors) { - this.do_notify("Invalid Search", "triggered from search view"); + this.do_notify(_t("Invalid Search"), _t("triggered from search view")); }, do_clear: function () { this.$element.find('.filter_label, .filter_icon').removeClass('enabled'); @@ -349,7 +360,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search this.$element.find('table:last').hide(); $('.searchview_extended_groups_list').empty(); - setTimeout(this.on_clear); + setTimeout(this.on_clear, 0); }, /** * Triggered when the search view gets cleared @@ -418,8 +429,10 @@ openerp.web.search.Invalid = openerp.web.Class.extend( /** @lends openerp.web.se this.message = message; }, toString: function () { - return ('Incorrect value for field ' + this.field + - ': [' + this.value + '] is ' + this.message); + return _.str.sprintf( + _t("Incorrect value for field %(fieldname)s: [%(value)s] is %(message)s"), + {fieldname: this.field, value: this.value, message: this.message} + ); } }); openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.search.Widget# */{ @@ -738,7 +751,7 @@ openerp.web.search.NumberField = openerp.web.search.Field.extend(/** @lends open * @extends openerp.web.search.NumberField */ openerp.web.search.IntegerField = openerp.web.search.NumberField.extend(/** @lends openerp.web.search.IntegerField# */{ - error_message: "not a valid integer", + error_message: _t("not a valid integer"), parse: function (value) { try { return openerp.web.parse_value(value, {'widget': 'integer'}); @@ -752,7 +765,7 @@ openerp.web.search.IntegerField = openerp.web.search.NumberField.extend(/** @len * @extends openerp.web.search.NumberField */ openerp.web.search.FloatField = openerp.web.search.NumberField.extend(/** @lends openerp.web.search.FloatField# */{ - error_message: "not a valid number", + error_message: _t("not a valid number"), parse: function (value) { try { return openerp.web.parse_value(value, {'widget': 'float'}); @@ -963,15 +976,18 @@ openerp.web.search.ExtendedSearch = openerp.web.OldWidget.extend({ this.check_last_element(); }, start: function () { - this._super(); - if (!this.$element) { - return; // not a logical state but sometimes it happens - } + this.$element = $("#" + this.element_id); this.$element.closest("table.oe-searchview-render-line").css("display", "none"); var self = this; this.rpc("/web/searchview/fields_get", {"model": this.model}, function(data) { self.fields = data.fields; + if (!('id' in self.fields)) { + self.fields.id = { + string: 'ID', + type: 'id' + } + } openerp.web.search.add_expand_listener(self.$element); self.$element.find('.searchview_extended_add_group').click(function (e) { self.add_group(); @@ -1028,7 +1044,7 @@ openerp.web.search.ExtendedSearchGroup = openerp.web.OldWidget.extend({ prop.start(); }, start: function () { - this._super(); + this.$element = $("#" + this.element_id); var _this = this; this.add_prop(); this.$element.find('.searchview_extended_add_proposition').click(function () { @@ -1080,7 +1096,7 @@ openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/** this.value = null; }, start: function () { - this._super(); + this.$element = $("#" + this.element_id); this.select_field(this.fields.length > 0 ? this.fields[0] : null); var _this = this; this.$element.find(".searchview_extended_prop_field").change(function() { @@ -1156,33 +1172,38 @@ openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/** } }); -openerp.web.search.ExtendedSearchProposition.Char = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Field = openerp.web.OldWidget.extend({ + start: function () { + this.$element = $("#" + this.element_id); + } +}); +openerp.web.search.ExtendedSearchProposition.Char = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.char', identifier_prefix: 'extended-search-proposition-char', operators: [ - {value: "ilike", text: "contains"}, - {value: "not ilike", text: "doesn't contain"}, - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} + {value: "ilike", text: _t("contains")}, + {value: "not ilike", text: _t("doesn't contain")}, + {value: "=", text: _t("is equal to")}, + {value: "!=", text: _t("is not equal to")}, + {value: ">", text: _t("greater than")}, + {value: "<", text: _t("less than")}, + {value: ">=", text: _t("greater or equal than")}, + {value: "<=", text: _t("less or equal than")} ], get_value: function() { return this.$element.val(); } }); -openerp.web.search.ExtendedSearchProposition.DateTime = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.DateTime = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.empty', identifier_prefix: 'extended-search-proposition-datetime', operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} + {value: "=", text: _t("is equal to")}, + {value: "!=", text: _t("is not equal to")}, + {value: ">", text: _t("greater than")}, + {value: "<", text: _t("less than")}, + {value: ">=", text: _t("greater or equal than")}, + {value: "<=", text: _t("less or equal than")} ], get_value: function() { return this.datewidget.get_value(); @@ -1193,16 +1214,16 @@ openerp.web.search.ExtendedSearchProposition.DateTime = openerp.web.OldWidget.ex this.datewidget.prependTo(this.$element); } }); -openerp.web.search.ExtendedSearchProposition.Date = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Date = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.empty', identifier_prefix: 'extended-search-proposition-date', operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} + {value: "=", text: _t("is equal to")}, + {value: "!=", text: _t("is not equal to")}, + {value: ">", text: _t("greater than")}, + {value: "<", text: _t("less than")}, + {value: ">=", text: _t("greater or equal than")}, + {value: "<=", text: _t("less or equal than")} ], get_value: function() { return this.datewidget.get_value(); @@ -1213,16 +1234,16 @@ openerp.web.search.ExtendedSearchProposition.Date = openerp.web.OldWidget.extend this.datewidget.prependTo(this.$element); } }); -openerp.web.search.ExtendedSearchProposition.Integer = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Integer = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.integer', identifier_prefix: 'extended-search-proposition-integer', operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} + {value: "=", text: _t("is equal to")}, + {value: "!=", text: _t("is not equal to")}, + {value: ">", text: _t("greater than")}, + {value: "<", text: _t("less than")}, + {value: ">=", text: _t("greater or equal than")}, + {value: "<=", text: _t("less or equal than")} ], get_value: function() { try { @@ -1232,16 +1253,19 @@ openerp.web.search.ExtendedSearchProposition.Integer = openerp.web.OldWidget.ext } } }); -openerp.web.search.ExtendedSearchProposition.Float = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Id = openerp.web.search.ExtendedSearchProposition.Integer.extend({ + operators: [{value: "=", text: _t("is")}] +}); +openerp.web.search.ExtendedSearchProposition.Float = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.float', identifier_prefix: 'extended-search-proposition-float', operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} + {value: "=", text: _t("is equal to")}, + {value: "!=", text: _t("is not equal to")}, + {value: ">", text: _t("greater than")}, + {value: "<", text: _t("less than")}, + {value: ">=", text: _t("greater or equal than")}, + {value: "<=", text: _t("less or equal than")} ], get_value: function() { try { @@ -1251,12 +1275,12 @@ openerp.web.search.ExtendedSearchProposition.Float = openerp.web.OldWidget.exten } } }); -openerp.web.search.ExtendedSearchProposition.Selection = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Selection = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.selection', identifier_prefix: 'extended-search-proposition-selection', operators: [ - {value: "=", text: "is"}, - {value: "!=", text: "is not"} + {value: "=", text: _t("is")}, + {value: "!=", text: _t("is not")} ], set_field: function(field) { this.field = field; @@ -1265,12 +1289,12 @@ openerp.web.search.ExtendedSearchProposition.Selection = openerp.web.OldWidget.e return this.$element.val(); } }); -openerp.web.search.ExtendedSearchProposition.Boolean = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition.Boolean = openerp.web.search.ExtendedSearchProposition.Field.extend({ template: 'SearchView.extended_search.proposition.boolean', identifier_prefix: 'extended-search-proposition-boolean', operators: [ - {value: "=", text: "is true"}, - {value: "!=", text: "is false"} + {value: "=", text: _t("is true")}, + {value: "!=", text: _t("is false")} ], get_value: function() { return true; @@ -1289,7 +1313,9 @@ openerp.web.search.custom_filters = new openerp.web.Registry({ 'integer': 'openerp.web.search.ExtendedSearchProposition.Integer', 'float': 'openerp.web.search.ExtendedSearchProposition.Float', 'boolean': 'openerp.web.search.ExtendedSearchProposition.Boolean', - 'selection': 'openerp.web.search.ExtendedSearchProposition.Selection' + 'selection': 'openerp.web.search.ExtendedSearchProposition.Selection', + + 'id': 'openerp.web.search.ExtendedSearchProposition.Id' }); }; diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js index 71cda6fcc47..9f649b313df 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -1,13 +1,16 @@ openerp.web.view_editor = function(openerp) { +var _t = openerp.web._t; var QWeb = openerp.web.qweb; openerp.web.ViewEditor = openerp.web.Widget.extend({ init: function(parent, element_id, dataset, view, options) { this._super(parent); this.element_id = element_id this.parent = parent - this.dataset = dataset; + this.dataset = new openerp.web.DataSetSearch(this, 'ir.ui.view', null, null), this.model = dataset.model; - this.xml_id = 0; + this.xml_element_id = 0; + this.property = openerp.web.ViewEditor.property_widget; + this.one_object = false; }, start: function() { this.init_view_editor(); @@ -15,23 +18,24 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ init_view_editor: function() { var self = this; var action = { - name:'ViewEditor', - context:this.session.user_context, - domain: [["model", "=", this.dataset.model]], - res_model : 'ir.ui.view', - views : [[false, 'list']], + name: _.str.sprintf("Manage Views (%s)", this.model), + context: this.session.user_context, + domain: [["model", "=", this.model]], + res_model: 'ir.ui.view', + views: [[false, 'list']], type: 'ir.actions.act_window', target: "current", - limit : 80, - auto_search : true, + limit: this.dataset.limit || 80, + auto_search: true, flags: { sidebar: false, deletable: false, views_switcher: false, - action_buttons:false, - search_view:false, - pager:false, - radio: true + action_buttons: false, + search_view: false, + pager: false, + radio: true, + select_view_id: self.parent.fields_view.view_id }, }; this.view_edit_dialog = new openerp.web.Dialog(this, { @@ -41,207 +45,308 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ height: 500, buttons: { "Create": function(){ - //to do + self.on_create_view(); }, "Edit": function(){ - self.xml_id=0; - self.get_data(); + self.xml_element_id = 0; + self.get_arch(); + }, + "Remove": function(){ + self.do_delete_view(); }, "Close": function(){ self.view_edit_dialog.close(); } }, - }); - this.view_edit_dialog.start().open(); - var action_manager = new openerp.web.ActionManager(this); - action_manager.appendTo(this.view_edit_dialog); - action_manager.do_action(action); - }, - check_attr: function(xml, tag, level) { - var obj = {'child_id': [], 'id': this.xml_id++, 'level': level+1, 'att_list': [], 'name': ""}; - var render_name = "<" + tag; - obj.att_list.push(tag); - $(xml).each(function() { - _.each(this.attributes, function(attrs){ - if (tag != 'button') { - if (attrs.nodeName == "string" || attrs.nodeName == "name" || attrs.nodeName == "index") { - render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"' ; + }).start().open(); + this.main_view_id = this.parent.fields_view.view_id; + this.action_manager = new openerp.web.ActionManager(this); + this.action_manager.appendTo(this.view_edit_dialog); + $.when(this.action_manager.do_action(action)).then(function() { + var viewmanager = self.action_manager.inner_viewmanager, + controller = viewmanager.views[viewmanager.active_view].controller; + controller.on_loaded.add_last(function(){ + $(controller.groups).bind({ + 'selected': function(e, ids, records) { + self.main_view_id = ids[0]; } - } else { - if (attrs.nodeName == "name") { - render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"'; - } - } - obj.att_list.push( [attrs.nodeName,attrs.nodeValue] ); + }) }); - render_name+= ">"; }); - obj.name = render_name; - return obj; }, - save_object: function(val, parent_list, child_obj_list) { + on_create_view: function() { var self = this; - var check_id = parent_list[0]; - var p_list = parent_list.slice(1); - if (val.child_id.length != 0) { - _.each(val.child_id, function(val, key) { - if (val.id == check_id) { - if (p_list.length!=0) { - self.save_object(val, p_list, child_obj_list); - } else { - val.child_id = child_obj_list; - return false; + this.create_view_dialog = new openerp.web.Dialog(this, { + modal: true, + title: _.str.sprintf("Create a view (%s)", self.model), + width: 500, + height: 400, + buttons: { + "Save": function(){ + var view_values = {}; + var warn = false; + _.each(self.create_view_widget, function(widget) { + if (widget.is_invalid) { + warn = true; + return false; + }; + if (widget.dirty && !widget.is_invalid) { + view_values[widget.name] = widget.get_value(); + } + }); + if (warn) { + self.on_valid_create_view(self.create_view_widget); + } else { + $.when(self.do_save_view(view_values)).then(function() { + self.create_view_dialog.close(); + var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller; + controller.reload_content(); + }); + } + }, + "Cancel": function(){ + self.create_view_dialog.close(); } } + }); + this.create_view_dialog.start().open(); + var view_widget = [{'name': 'view_name', 'string':'View Name', 'type': 'char', 'required': true, 'value' : this.model + '.custom_' + Math.round(Math.random() * 1000)}, + {'name': 'view_type', 'string': 'View Type', 'type': 'selection', 'required': true, 'value': 'Form', 'selection': [['',''],['tree', 'Tree'],['form', 'Form'],['graph', 'Graph'],['calendar', 'Calender']]}, + {'name': 'proirity', 'string': 'Priority', 'type': 'float', 'required': true, 'value':'16'}]; + this.create_view_dialog.$element.append('
'); + this.create_view_widget = []; + _.each(view_widget, function(widget) { + var type_widget = new (self.property.get_any([widget.type])) (self.create_view_dialog, widget); + self.create_view_dialog.$element.find('table[id=create_view]').append('' + widget.string + ':' + type_widget.render()+''); + var value = null; + if (widget.value) { + value = widget.value; + type_widget.dirty = true; + } + type_widget.start(); + type_widget.set_value(value) + self.create_view_widget.push(type_widget); + }); + }, + do_save_view: function(values) { + def = $.Deferred(); + var field_dataset = new openerp.web.DataSetSearch(this, this.model, null, null); + var model_dataset = new openerp.web.DataSetSearch(this, 'ir.model', null, null); + var view_string = "", field_name = false, self = this; + field_dataset.call( 'fields_get', [], function(fields) { + _.each(['name', 'x_name'], function(value) { + if (_.include(_.keys(fields), value)) { + field_name = value; + return false; + } }); - } else { - val.child_id = child_obj_list; + if (field_name) { + model_dataset.read_slice(['name','field_id'], {"domain": [['model','=',self.model]]}, function(records) { + if (records) {view_string = records[0].name;} + var arch = _.str.sprintf("\n<%s string='%s'>\n\t\n", values.view_type, view_string, field_name, values.view_type); + var vals = {'model': self.model, 'name': values.view_name, 'priority': values.priority, 'type': values.view_type, 'arch': arch}; + self.dataset.create(vals, function(suc) { + def.resolve(); + }); + }); + } + }); + return def.promise(); + }, + on_valid_create_view: function(widgets) { + var msg = "
    "; + _.each(widgets, function(widget) { + if (widget.is_invalid) { + msg += "
  • " + widget.name + "
  • "; + } + }); + msg += "
"; + this.do_warn("The following fields are invalid :", msg); + }, + add_node_name : function(node) { + if(node.tagName.toLowerCase() == "button" || node.tagName.toLowerCase() == "field"){ + return (node.getAttribute('name'))? + _.str.sprintf( "<%s name='%s'>",node.tagName.toLowerCase(), node.getAttribute('name')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); + }else if(node.tagName.toLowerCase() == "group"){ + return (node.getAttribute('string'))? + _.str.sprintf( "<%s>",node.getAttribute('string')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); + }else{ + return (node.getAttribute('string'))? + _.str.sprintf( "<%s string='%s'>",node.tagName.toLowerCase(), node.getAttribute('string')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); } }, - xml_node_create: function(xml, root, parent_list, parent_id, main_object){ + do_delete_view: function() { + if (confirm(_t("Do you really want to remove this view?"))) { + var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller; + this.dataset.unlink([this.main_view_id]).then(function() { + controller.reload_content(); + this.main_view_id = self.parent.fields_view.view_id; + }); + } + }, + create_View_Node: function(node){ + ViewNode = { + 'level': ($(node).parents()).length + 1, + 'id': this.xml_element_id += 1, + 'att_list': [], + 'name': this.add_node_name(node), + 'child_id': [] + } + ViewNode.att_list.push(node.tagName.toLowerCase()); + _.each(node.attributes, function(att) { + ViewNode.att_list.push([att.nodeName, att.nodeValue]); + }); + return ViewNode; + }, + append_child_object: function(main_object, parent_id, child_obj_list) { + var self = this; + if (main_object.id == parent_id) { + main_object.child_id = child_obj_list; + return main_object; + } else { + _.each(main_object.child_id, function(child_object) { + self.append_child_object(child_object, parent_id, child_obj_list); + }); + } + }, + convert_arch_to_obj: function(xml_Node, main_object, parent_id) { var self = this; var child_obj_list = []; - var children_list = $(xml).filter(root).children(); - var parents = $(children_list[0]).parents().get(); - _.each(children_list, function (child_node) { - child_obj_list.push(self.check_attr(child_node,child_node.tagName.toLowerCase(),parents.length)); + _.each(xml_Node, function(element) { + child_obj_list.push(self.create_View_Node(element)); }); - if (children_list.length != 0) { - if (parents.length <= parent_list.length) { - parent_list.splice(parents.length - 1); + this.append_child_object(main_object, parent_id, child_obj_list); + var obj_xml_list = _.zip(xml_Node, child_obj_list); + _.each(obj_xml_list, function(node) { + var children = _.filter(node[0].childNodes, function(child) { + return child.nodeType == 1; + }); + if (children) { + self.convert_arch_to_obj(children, main_object, node[1].id); } - parent_list.push(parent_id); - self.save_object(main_object[0], parent_list.slice(1), child_obj_list); - } - for (var i = 0; i < children_list.length; i++) { - self.xml_node_create - (children_list[i], children_list[i].tagName.toLowerCase(), - parent_list, child_obj_list[i].id, main_object); - } + }); return main_object; }, parse_xml: function(arch, view_id) { - var root = $(arch).filter(":first")[0]; - var tag = root.tagName.toLowerCase(); - var obj ={'child_id':[],'id':this.xml_id++,'level':0,'att_list':[],'name':""}; - var root_object = this.check_attr(root,tag,0); - obj.child_id = this.xml_node_create(arch, tag, [], this.xml_id-1, [root_object], []) - return [obj]; + main_object = { + 'level': 0, + 'id': this.xml_element_id +=1, + 'att_list': [], + 'name': _.str.sprintf("", view_id), + 'child_id': [] + }; + var xml_arch = QWeb.load_xml(arch); + return [this.convert_arch_to_obj(xml_arch.childNodes, main_object, this.xml_element_id)]; }, - get_data: function() { + get_arch: function() { var self = this; var view_arch_list = []; - self.main_view_id =((this.view_edit_dialog.$element.find("input[name='radiogroup']:checked").parent()).parent()).attr('data-id'); - var ve_dataset = new openerp.web.DataSet(this, 'ir.ui.view'); - ve_dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type'], function (arch) { - one_object = self.parse_xml(arch[0].arch,self.main_view_id); - self.main_view_type = arch[0].type - view_arch_list.push({"view_id" : self.main_view_id, "arch" : arch[0].arch}); - dataset = new openerp.web.DataSetSearch(self, 'ir.ui.view', null, null); - dataset.read_slice([], {domain : [['inherit_id','=', parseInt(self.main_view_id)]]}, function (result) { - _.each(result, function(res) { - view_arch_list.push({"view_id":res.id,"arch":res.arch}); - self.inherit_view(one_object, res); - }); - return self.edit_view({"main_object": one_object, - "parent_child_id": self.parent_child_list(one_object, []), - "arch": view_arch_list}); - }); - }); - }, - parent_child_list : function(one_object, p_list) { - var self = this; - _.each(one_object , function(element){ - if(element.child_id.length != 0){ - p_list.push({"key":element.id,"value":_.pluck(element.child_id, 'id')}); - self.parent_child_list(element.child_id, p_list); - } - }); - return p_list; - }, - inherit_view : function(one_object, result) { - var self = this; - var root = $(result.arch).filter('*'); - var xml_list = []; - if (root[0].tagName.toLowerCase() == "data") { - xml_list = $(root[0]).children(); - } else { - xml_list.push(root[0]); - } - _.each(xml_list , function(xml){ - var parent_id; - var check_list = []; - var xpath_object = self.parse_xml(xml,result.id); - if (xml.tagName.toLowerCase() == "xpath" ) { - var part_expr = _.without($(xml).attr('expr').split("/"),""); - _.each(part_expr,function(part){ - check_list.push(_.without($.trim(part.replace(/[^a-zA-Z 0-9 _]+/g,'!')).split("!"),"")); + this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type'], function(arch) { + if (arch.length) { + var arch_object = self.parse_xml(arch[0].arch, self.main_view_id); + self.main_view_type = arch[0].type == 'tree'? 'list': arch[0].type; + view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch}); + self.dataset.read_slice([], {domain: [['inherit_id','=', parseInt(self.main_view_id)]]}, function(result) { + _.each(result, function(res) { + view_arch_list.push({"view_id": res.id, "arch": res.arch}); + self.inherit_view(arch_object, res); + }); + return self.edit_view({"main_object": arch_object, + "parent_child_id": self.parent_child_list(arch_object, []), + "arch": view_arch_list}); }); } else { - var temp = []; - _.each(xpath_object[0].child_id[0].att_list, function(list){ - if(!_.include(list, "position")){ - temp.push(list); - } - }); - check_list = [_.flatten(temp)]; + self.do_warn("Please select view in list :"); } - self.full_path_search(check_list ,one_object ,xpath_object); }); }, - full_path_search: function(check_list ,val ,xpath_object) { + parent_child_list : function(one_object, parent_list) { var self = this; - if(xpath_object.length!=0){ - var check = check_list[0]; - var obj; + _.each(one_object , function(element) { + if (element.child_id.length != 0) { + parent_list.push({"key": element.id, "value": _.pluck(element.child_id, 'id')}); + self.parent_child_list(element.child_id, parent_list); + } + }); + return parent_list; + }, + inherit_view : function(arch_object, result) { + var self = this, xml_list = [], xml_arch = QWeb.load_xml(result.arch); + if (xml_arch.childNodes[0].tagName == "data") { + xml_list = _.filter(xml_arch.childNodes[0].childNodes, function(child) { + return child.nodeType == 1; + }); + } else { + xml_list.push( xml_arch.childNodes[0]); + } + _.each(xml_list, function(xml) { + var expr_to_list = [], xpath_arch_object = self.parse_xml(QWeb.tools.xml_node_to_string(xml), result.id); + if (xml.tagName == "xpath") { + var part_expr = _.without(xml.getAttribute('expr').split("/"), ""); + _.each(part_expr, function(part) { + expr_to_list.push(_.without($.trim(part.replace(/[^a-zA-Z 0-9 _]+/g,'!')).split("!"), "")); + }); + } else { + var temp = _.reject(xpath_arch_object[0].child_id[0].att_list, function(list) { + return list instanceof Array? _.include(list, "position"): false; + }); + expr_to_list = [_.flatten(temp)]; + } + self.inherit_apply(expr_to_list, arch_object ,xpath_arch_object); + }); + }, + inherit_apply: function(expr_list ,arch_object ,xpath_arch_object) { + var self = this; + if (xpath_arch_object.length) { + var check = expr_list[0], obj = false; switch (check.length) { case 2: - if(parseInt(check[1])){ - var list_1 = _.select(val,function(element){ - var main_list = _.flatten(element.att_list); - return _.include(main_list, check[0]); + if (parseInt(check[1])) { + //for field[3] + var temp_list = _.select(arch_object, function(element) { + return _.include(_.flatten(element.att_list), check[0]); }); - obj = val[_.indexOf(val,list_1[parseInt(check[1])-1])]; + obj = arch_object[_.indexOf(arch_object, temp_list[parseInt(check[1]) - 1])]; } else { - obj = _.detect(val, function(element){ - var main_list = _.flatten(element.att_list); - return _.include(main_list, check[0]); + //for notebook[last()] + obj = _.detect(arch_object, function(element) { + return _.include(_.flatten(element.att_list), check[0]); }); } break; case 3: - obj = _.detect(val,function(element){ - var main_list = _.flatten(element.att_list); - check = _.uniq(check); - var insert = _.intersection(main_list,check); - if(insert.length == check.length ){return element;} + //for field[@name='type'] + obj = _.detect(arch_object, function(element){ + if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == check.length) { + return element; + } }); break; case 1: - var list_1 = _.select(val,function(element){ - var main_list = _.flatten(element.att_list); - return _.include(main_list, check[0]); + //for /form/notebook + var temp_list = _.select(arch_object, function(element) { + return _.include(_.flatten(element.att_list), check[0]); }); - if(list_1.length != 0){ - (check_list.length == 1)? obj = list_1[0] : check_list.shift(); + if (temp_list.length != 0) { + expr_list.length == 1 ? obj = temp_list[0] : expr_list.shift(); } break; } - if(obj) { - check_list.shift(); - if (check_list.length !=0){ - self.full_path_search(check_list ,obj.child_id ,xpath_object); + if (obj) { + expr_list.shift(); + if (expr_list.length) { + self.inherit_apply(expr_list, obj.child_id, xpath_arch_object); } else { - var level = obj.level+1; - self.increase_level(xpath_object[0], level) - obj.child_id.push(xpath_object[0]); - xpath_object.pop(); - return; + self.increase_level(xpath_arch_object[0], obj.level + 1); + obj.child_id.push(xpath_arch_object[0]); + xpath_arch_object.pop(); } - } - else { - _.each(val,function(element){ - self.full_path_search(check_list ,element.child_id ,xpath_object); + } else { + _.each(arch_object, function(element) { + self.inherit_apply(expr_list, element.child_id, xpath_arch_object); }); } } @@ -253,30 +358,39 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ self.increase_level(val, level + 1); }); }, + do_select_row: function(row_id) { + this.edit_xml_dialog.$element.find("tr[id^='viewedit-']").removeClass('ui-selected'); + this.edit_xml_dialog.$element.find("tr[id=viewedit-" + row_id + "]").addClass('ui-selected'); + }, + do_parent_img_hide_show: function(img) { + if ($(img).attr('src') == '/web/static/src/img/collapse.gif') { + $(img).attr('src', '/web/static/src/img/expand.gif'); + this.on_expand(img); + } else { + $(img).attr('src', '/web/static/src/img/collapse.gif'); + this.on_collapse(img); + } + }, edit_view: function(one_object) { var self = this; - this.edit_xml_dialog = new openerp.web.Dialog(this,{ + this.one_object = one_object; + this.edit_xml_dialog = new openerp.web.Dialog(this, { modal: true, - title: 'View Editor', + title: _.str.sprintf("View Editor %d - %s", self.main_view_id, self.model), width: 750, height: 500, buttons: { - "Inherited View": function(){ - //todo - }, - "Preview": function(){ + "Preview": function() { var action = { - context:self.session.user_context, - res_model : self.model, - views : [[self.main_view_id, self.main_view_type]], + context: self.session.user_context, + res_model: self.model, + views: [[self.main_view_id, self.main_view_type]], type: 'ir.actions.act_window', target: "new", flags: { sidebar: false, views_switcher: false, - action_buttons:false, - search_view:false, - pager:false, + action_buttons: false, }, }; var action_manager = new openerp.web.ActionManager(self); @@ -286,231 +400,765 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ self.edit_xml_dialog.close(); } } + }).start().open(); + var no_property_att = []; + _.each(_PROPERTIES, function(val, key) { + if (! val.length) no_property_att.push(key); }); - this.edit_xml_dialog.start().open(); - this.edit_xml_dialog.$element.html(QWeb.render('view_editor', { - 'data': one_object['main_object'], - })); + this.edit_xml_dialog.$element.html(QWeb.render('view_editor', {'data': one_object['main_object'], 'no_properties': no_property_att})); this.edit_xml_dialog.$element.find("tr[id^='viewedit-']").click(function() { - self.edit_xml_dialog.$element.find("tr[id^='viewedit-']").removeClass('ui-selected'); - $(this).addClass('ui-selected'); + self.do_select_row(this.id.split('-')[1]); }); this.edit_xml_dialog.$element.find("img[id^='parentimg-']").click(function() { - if ($(this).attr('src') == '/web/static/src/img/collapse.gif') { - $(this).attr('src', '/web/static/src/img/expand.gif'); - self.on_expand(this); - } else { - $(this).attr('src', '/web/static/src/img/collapse.gif'); - var id = this.id.split('-')[1]; - self.on_collapse(this,one_object['parent_child_id'], one_object['main_object']); - } + self.do_parent_img_hide_show(this); }); this.edit_xml_dialog.$element.find("img[id^='side-']").click(function() { - var side = $(this).closest("tr[id^='viewedit-']") - var id_tr = (side.attr('id')).split('-')[1]; - var img = side.find("img[id='parentimg-"+id_tr+"']").attr('src'); ; - var level = parseInt(side.attr('level')); - var list_shift =[]; - var last_tr; - var cur_tr = side; - list_shift.push(side); - var next_tr; - var ls = side; - var view_id; - var view_xml_id; - while(1){ - ls = ls.prev(); - if((self.edit_xml_dialog.$element.find(ls).find('a').text()).search("view_id") != -1 - && parseInt(ls.attr('level')) < level){ - view_id = parseInt(($(ls).find('a').text()).replace(/[^0-9]+/g,'')); - view_xml_id = (ls.attr('id')).split('-')[1]; + self.on_select_img(this); + }); + }, + on_select_img: function(element_img) { + var self = this; + var side = $(element_img).closest("tr[id^='viewedit-']"); + this.one_object.clicked_tr_id = parseInt((side.attr('id')).split('-')[1]); + this.one_object.clicked_tr_level = parseInt(side.attr('level')); + var img = side.find("img[id='parentimg-" + this.one_object.clicked_tr_id + "']").attr('src'); + var view_id = 0, view_xml_id = 0, view_find = side; + //for view id finding + var min_level = this.one_object.clicked_tr_id; + if (($(side).find('a').text()).search("view_id") != -1) { + view_id = parseInt(($(view_find).find('a').text()).replace(/[^0-9]+/g, '')); + view_xml_id = (view_find.attr('id')).split('-')[1]; + this.one_object.clicked_tr_id += 1; + this.one_object.clicked_tr_level += 1; + }else{ + while (1) { + view_find = view_find.prev(); + if (view_find.length == 0 || + (self.edit_xml_dialog.$element.find(view_find).find('a').text()).search("view_id") != -1 + && parseInt(view_find.attr('level')) < min_level ) { + view_id = parseInt(($(view_find).find('a').text()).replace(/[^0-9]+/g, '')); + view_xml_id = parseInt((view_find.attr('id')).split('-')[1]); break; } + if (view_find.attr('level') < min_level) { + min_level = parseInt(view_find.attr('level')); + } } - switch (this.id) { - case "side-add": - break; - case "side-remove": - break; - case "side-edit": - break; - case "side-up": - while (1) { - var prev_tr = cur_tr.prev(); - if(level >= parseInt(prev_tr.attr('level')) || prev_tr.length == 0) { - last_tr = prev_tr; - break; - } - cur_tr = prev_tr; - } - if (img) { - while (1) { - next_tr = side.next(); - if ( parseInt(next_tr.attr('level')) <= level || next_tr.length == 0) { - break; - } else { - list_shift.push(next_tr); - side = next_tr; - } - } - } - if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == level && - (self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") == -1) { - _.each(list_shift, function(rec) { - $(last_tr).before(rec); - }); - self.save_move_arch(one_object, view_id, view_xml_id, id_tr, level, "up"); - } + } + this.one_object.clicked_tr_view = [view_id, view_xml_id]; + switch (element_img.id) { + case "side-add": + self.do_node_add(side); + break; + case "side-remove": + if (confirm(_t("Do you really want to remove this node?"))) { + self.do_save_update_arch("remove_node"); + } + break; + case "side-edit": + self.do_node_edit(side); + break; + case "side-up": + self.do_node_up(side, img); break; case "side-down": - if (img) { - while (1) { - next_tr = cur_tr.next(); - if ( parseInt(next_tr.attr('level')) <= level || next_tr.length == 0) { - last_tr = next_tr; - break; - } else { - list_shift.push(next_tr); - cur_tr = next_tr; - } - } - } - else { - last_tr = cur_tr.next(); - } - if((self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") != -1){ - return; - } - if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == level) { - var last_tr_id = (last_tr.attr('id')).split('-')[1]; - img = last_tr.find("img[id='parentimg-" + last_tr_id + "']").attr('src'); - if (img) { - self.edit_xml_dialog.$element.find("img[id='parentimg-" + last_tr_id + "']"). - attr('src', '/web/static/src/img/expand.gif'); - while (1) { - var next_tr = last_tr.next(); - if (next_tr.attr('level') <= level || next_tr.length == 0) break; - next_tr.hide(); - last_tr = next_tr; - } - } - list_shift.reverse(); - _.each(list_shift, function(rec) { - $(last_tr).after(rec); - }); - self.save_move_arch(one_object, view_id, view_xml_id, id_tr, level, "down"); - } + self.do_node_down(side, img); break; - } + } + }, + do_node_add: function(side){ + var self = this; + var tr = $(side).find('a').text(); + var parent_tr = ($(side).prevAll("tr[level=" + String(this.one_object.clicked_tr_level - 1) + "]"))[0]; + var field_dataset = new openerp.web.DataSetSearch(this, this.model, null, null); + parent_tr = $(parent_tr).find('a').text(); + field_dataset.call( 'fields_get', [], function(result) { + var fields = _.keys(result); + fields.push(" "),fields.sort(); + var property_to_check = []; + _.each([tr, parent_tr],function(element) { + property_to_check.push( + _.detect(_.keys(_CHILDREN),function(res){ + return _.str.include(element, res); + })); + }); + self.on_add_node(property_to_check, fields); }); }, - save_move_arch: function(one_object, view_id, view_xml_id, id_tr, level, move_direct){ + do_node_edit: function(side) { var self = this; - var arch = _.detect(one_object['arch'],function(element){ - return element.view_id == view_id; - }); - var obj = self.get_view_object(view_xml_id, one_object['main_object'], []); - if(($(arch.arch).filter("data")).length != 0 && view_xml_id != 0){ + var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []); + if (result.length && result[0] && result[0].att_list) { + var properties = _PROPERTIES[result[0].att_list[0]]; + self.on_edit_node(properties); + } + }, + do_node_down: function(cur_tr, img) { + var self = this, next_tr, last_tr, tr_to_move = []; + tr_to_move.push(cur_tr); + if (img) { + while (1) { + next_tr = cur_tr.next(); + if ( parseInt(next_tr.attr('level')) <= this.one_object.clicked_tr_level || next_tr.length == 0) { + last_tr = next_tr; + break; + } else { + tr_to_move.push(next_tr); + cur_tr = next_tr; + } + } + } else { + last_tr = cur_tr.next(); + } + if ((self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") != -1) { + return false; + } + if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == this.one_object.clicked_tr_level) { + var last_tr_id = (last_tr.attr('id')).split('-')[1]; + img = last_tr.find("img[id='parentimg-" + last_tr_id + "']").attr('src'); + if (img) { + self.edit_xml_dialog.$element.find("img[id='parentimg-" + last_tr_id + "']"). + attr('src', '/web/static/src/img/expand.gif'); + while (1) { + var next_tr = last_tr.next(); + if (next_tr.attr('level') <= this.one_object.clicked_tr_level || next_tr.length == 0) break; + next_tr.hide(); + last_tr = next_tr; + } + } + tr_to_move.reverse(); + _.each(tr_to_move, function(rec) { + $(last_tr).after(rec); + }); + self.do_save_update_arch("down"); + } + }, + do_node_up: function(cur_tr, img) { + var self = this, side = cur_tr, tr_to_move = []; + tr_to_move.push(side); + while (1) { + var prev_tr = cur_tr.prev(); + if (this.one_object.clicked_tr_level >= parseInt(prev_tr.attr('level')) || prev_tr.length == 0) { + last_tr = prev_tr; + break; + } + cur_tr = prev_tr; + } + if (img) { + self.edit_xml_dialog.$element.find("img[id='parentimg-" + this.one_object.clicked_tr_id + "']"). + attr('src', '/web/static/src/img/expand.gif'); + while (1) { + next_tr = side.next(); + if (parseInt(next_tr.attr('level')) <= this.one_object.clicked_tr_level || next_tr.length == 0) { + break; + } else { + next_tr.hide(); + tr_to_move.push(next_tr); + side = next_tr; + } + } + } + if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == this.one_object.clicked_tr_level && + (self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") == -1) { + _.each(tr_to_move, function(rec) { + $(last_tr).before(rec); + }); + self.do_save_update_arch("up"); + } + }, + do_save_update_arch: function(move_direct, update_values) { + var self = this; + var arch = _.detect(self.one_object['arch'], function(element) + {return element.view_id == self.one_object.clicked_tr_view[0]}); + var obj = self.get_object_by_id(this.one_object.clicked_tr_view[1],this.one_object['main_object'], []); + //for finding xpath tag from inherit view + var xml_arch = QWeb.load_xml(arch.arch); + if (xml_arch.childNodes[0].tagName == "data") { var check_list = _.flatten(obj[0].child_id[0].att_list); - arch.arch = _.detect($(arch.arch).children(), function(xml_child){ - var temp_obj = self.check_attr(xml_child, xml_child.tagName.toLowerCase()); - var main_list = _.flatten(temp_obj.att_list); - check_list = _.uniq(check_list); - var insert = _.intersection(main_list,check_list); - if(insert.length == check_list.length ){return xml_child;} + var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) { + return child.nodeType == 1; + }); + 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 == check_list.length ) {return xml_child;} }); } - return self.get_node(arch.arch, obj[0].child_id[0], parseInt(id_tr), [], parseInt(level), - parseInt(view_id), arch, move_direct); + arch_to_pass = _.filter($(arch.arch), function (child) { + return child.nodeType == 1; + }); + return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],[], move_direct, update_values,arch); }, - - get_view_object: function(view_xml_id, one_object,result){ + get_object_by_id: function(id, one_object, result) { var self = this; - if(result.length==0){ - var check = _.detect(one_object , function(obj){ - return view_xml_id==obj.id; + if (result.length == 0 ) { + var check = _.detect(one_object , function(obj) { + return id == obj.id; }); - if(check){result.push(check);}; - _.each(one_object, function(obj){ - self.get_view_object(view_xml_id, obj.child_id, result); + if (check) {result.push(check);}; + _.each(one_object, function(obj) { + self.get_object_by_id(id,obj.child_id, result); }); } return result; }, - get_node: function(arch1, obj, id, child_list, level, view_id, arch, move_direct){ + create_clone: function(clone, new_node_obj, position){ var self = this; - var children_list = $(arch1).children(); - var list_obj_xml = _.zip(children_list,obj.child_id); - if (id) { - if (obj.id == id) { - var id; - var parent = $(arch1).parents(); - var index = _.indexOf(child_list, obj) - var re_insert_obj = child_list.splice(index, 1); + clone.find('a').text(new_node_obj.name); + ($(clone.find('a').parent()).siblings('td')).css( "padding-left", 20 * new_node_obj.level); + clone.attr("id", "viewedit-" + new_node_obj.id); + clone.attr("level", new_node_obj.level); + clone.find("img[id^='parentimg-']").remove(); + clone.bind("click",function(){ + self.do_select_row(this.id.split('-')[1]); + }); + clone.find("img[id^='side-']").click(function() { + self.on_select_img(this); + }); + return clone; + }, + do_save_xml: function(arch1, obj, child_list, move_direct, update_values, arch){ + var self = this, children_list = $(arch1).children(), list_obj_xml = _.zip(children_list, obj.child_id); + if (this.one_object.clicked_tr_id) { + if (obj.id == this.one_object.clicked_tr_id) { + var parent = false, index = _.indexOf(child_list, obj); if (move_direct == "down") { var next = $(arch1).next(); $(next).after(arch1); + var re_insert_obj = child_list.splice(index, 1); child_list.splice(index+1, 0, re_insert_obj[0]); - } else { + parent = $(arch1).parents(); + } else if (move_direct == "up") { var prev = $(arch1).prev(); $(prev).before(arch1); + var re_insert_obj = child_list.splice(index, 1); child_list.splice(index-1, 0, re_insert_obj[0]); + parent = $(arch1).parents(); + } else if (move_direct == "update_node") { + _.each(update_values, function(val){ + if (val[1]) $(arch1)[0].setAttribute(val[0], val[1]); + else $(arch1)[0].removeAttribute(val[0]); + }); + var new_obj = self.create_View_Node(arch1); + new_obj.id = obj.id,new_obj.child_id = obj.child_id; + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+this.one_object.clicked_tr_id+"']"). + find('a').text(new_obj.name); + child_list.splice(index, 1, new_obj); + parent = $(arch1).parents(); + } else if(move_direct == "add_node") { + var tr_click = self.edit_xml_dialog.$element.find("tr[id='viewedit-"+self.one_object.clicked_tr_id+"']"), + temp_xml = QWeb.load_xml(update_values[0]), + object_xml = self.create_View_Node(temp_xml.childNodes[0]); + (update_values[1] == "Inside")? object_xml.level = obj.level + 1:object_xml.level = obj.level; + var clone = self.create_clone(tr_click.clone(),object_xml), + after_append = _.detect(self.one_object['parent_child_id'],function(ele){ + return self.one_object.clicked_tr_id == ele.key; + }); + after_append = (after_append)?_.last(after_append.value):self.one_object.clicked_tr_id; + switch (update_values[1]) { + case "After": + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+after_append+"']").after(clone); + $(arch1).after(update_values[0]); + child_list.splice(index + 1, 0, object_xml); + break; + case "Before": + tr_click.before(clone); + $(arch1).before(update_values[0]); + child_list.splice(index - 1, 0, object_xml); + break; + case "Inside": + if (tr_click.find("img[id^='parentimg-']").length == 0) { + ($(tr_click.find('a').parent()).siblings('td')) + .append($('').attr('src', '/web/static/src/img/collapse.gif'). + attr('id','parentimg-'+ self.one_object.clicked_tr_id).click(function(){ + self.do_parent_img_hide_show(this); + })); + } + $(arch1).append(update_values[0]); + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+after_append+"']").after(clone); + obj.child_id.push(object_xml); + break; + } + self.edit_xml_dialog.$element. + find("tr[id='viewedit-" + object_xml.id + "']").removeClass('ui-selected'); + parent = $(arch1).parents(); + } else if (move_direct == "remove_node") { + parent = $(arch1).parents(); + if (parent.length == 0 || (parent[0].tagName.toLowerCase() == "data")) { + self.one_object.clicked_tr_id = self.one_object.clicked_tr_id -1; + self.one_object.clicked_tr_level = self.one_object.clicked_tr_level - 1; + (parent.length == 0)?parent.push("remove_view"):false; + } + $(arch1).remove(); + child_list.splice(index,1); + var cur_tr = self.edit_xml_dialog.$element. + find("tr[id='viewedit-" + self.one_object.clicked_tr_id + "']"); + _.each(self.get_list_tr(cur_tr,self.one_object.clicked_tr_level), function(tr_element){ + tr_element.remove(); + }); + cur_tr.remove(); + var parent_img = _.detect(self.one_object['parent_child_id'],function(element){ + return _.include(element.value, self.one_object.clicked_tr_id); + }); + if(parent_img.value.length == 1){ + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+parent_img.key+"']"). + find("img[id^='parentimg-']").remove(); + } + self.one_object['parent_child_id'] = self.parent_child_list(self.one_object['main_object'],[]); } - parent = parent[parent.length-1]; - var convert_to_utf = self.xml2Str(parent); - if (convert_to_utf) { + var convert_to_utf = (parent.length != 0)? parent[parent.length-1]: arch1; + if (convert_to_utf != "remove_view") { + convert_to_utf = QWeb.tools.xml_node_to_string(convert_to_utf); convert_to_utf = convert_to_utf.replace('xmlns="http://www.w3.org/1999/xhtml"', ""); convert_to_utf = '' + convert_to_utf; arch.arch = convert_to_utf; - dataset = new openerp.web.DataSet(this, 'ir.ui.view'); - dataset.write(parseInt(view_id),{"arch":convert_to_utf}, function(r) { - }); + this.dataset.write(this.one_object.clicked_tr_view[0] ,{"arch":convert_to_utf}, function(r) {}); + } else { + this.dataset.unlink([this.one_object.clicked_tr_view[0]],function(res) {}); + } + if(move_direct == "add_node"){ + self.add_node_dialog.close(); + self.on_select_img(clone.find("img[id='side-edit']")[0]); + self.one_object['parent_child_id'] = self.parent_child_list(self.one_object['main_object'],[]); } } - if (obj.level <= level) { + if (obj.level <= this.one_object.clicked_tr_level) { _.each(list_obj_xml, function(child_node) { - self.get_node(child_node[0], child_node[1], id, obj.child_id, level, view_id, arch, move_direct); + self.do_save_xml(child_node[0], child_node[1], obj.child_id, move_direct, update_values, arch); }); } } }, - xml2Str: function(xmlNode) { - try { - return (new XMLSerializer()).serializeToString(xmlNode); - } - catch (e) { - try { - return xmlNode.xml; - } - catch (e) { - return false; - } - } - - }, on_expand: function(expand_img){ var level = parseInt($(expand_img).closest("tr[id^='viewedit-']").attr('level')); var cur_tr = $(expand_img).closest("tr[id^='viewedit-']"); + _.each(this.get_list_tr(cur_tr,level), function(tr_element){ + tr_element.hide(); + }); + }, + get_list_tr: function(cur_tr,level){ + tr_list = []; while (1) { var nxt_tr = cur_tr.next(); - if (parseInt(nxt_tr.attr('level')) > level){ + if (parseInt(nxt_tr.attr('level')) > level) { cur_tr = nxt_tr; - nxt_tr.hide(); - } else return nxt_tr; + tr_list.push(nxt_tr); + } else return tr_list; } }, - on_collapse: function(collapse_img, parent_child_id, id, main_object) { - var self = this; - var id = collapse_img.id.split('-')[1]; - var datas = _.detect(parent_child_id,function(res) { + on_collapse: function(collapse_img) { + var self = this, id = collapse_img.id.split('-')[1]; + var datas = _.detect(self.one_object['parent_child_id'] , function(res) { return res.key == id; }); - _.each(datas.value, function(rec) { - var tr = self.edit_xml_dialog.$element.find("tr[id='viewedit-"+rec+"']"); - tr.find("img[id='parentimg-"+rec+"']").attr('src','/web/static/src/img/expand.gif'); + _.each(datas.value, function (rec) { + var tr = self.edit_xml_dialog.$element.find("tr[id='viewedit-" + rec + "']"); + tr.find("img[id='parentimg-" + rec + "']").attr('src', '/web/static/src/img/expand.gif'); tr.show(); }); + }, + on_edit_node: function(properties){ + var self = this; + this.edit_node_dialog = new openerp.web.Dialog(this,{ + modal: true, + title: 'Properties', + width: 500, + height: 400, + buttons: { + "Update": function(){ + var warn = false, update_values = []; + _.each(self.edit_widget, function(widget) { + if (widget.is_invalid) { + warn = true; + return false; + }; + if (widget.dirty && !widget.is_invalid) { + update_values.push([widget.name, widget.get_value()]); + } + }); + if (warn) { + self.on_valid_create_view(self.edit_widget); + } else { + self.do_save_update_arch("update_node", update_values); + self.edit_node_dialog.close(); + } + }, + "Cancel": function(){ + self.edit_node_dialog.close(); + } + } + }); + this.edit_node_dialog.start().open(); + var _PROPERTIES_ATTRIBUTES = { + 'name' : {'name':'name', 'string': 'Name', 'type': 'char'}, + 'string' : {'name':'string', 'string': 'String', 'type': 'char'}, + 'required' : {'name':'required', 'string': 'Required', 'type': 'boolean'}, + 'readonly' : {'name':'readonly', 'string': 'Readonly', 'type': 'boolean'}, + 'domain' : {'name':'domain', 'string': 'Domain', 'type': 'char'}, + 'context' : {'name':'context', 'string': 'Context', 'type': 'char'}, + 'limit' : {'name':'limit', 'string': 'Limit', 'type': 'float'}, + 'min_rows' : {'name':'min_rows', 'string': 'Minimum rows', 'type': 'float'}, + 'date_start' : {'name':'date_start', 'string': 'Start date', 'type': 'char'}, + 'date_delay' : {'name':'date_delay', 'string': 'Delay date', 'type': 'char'}, + 'day_length' : {'name':'day_length', 'string': 'Day length', 'type': 'char'}, + 'mode' : {'name':'mode', 'string': 'Mode', 'type': 'char'}, + 'align' : {'name':'align', 'string': 'Alignment ', 'type': 'selection', 'selection': [['', ''], ['0.0', 'Left'], ['0.5', 'Center'], ['1.0', 'Right']]}, + 'icon' : {'name':'icon', 'string': 'Icon', 'type': 'selection', 'selection': _ICONS}, + 'type' : {'name':'type', 'string': 'Type', 'type': 'selection', 'selection': [['', ''], ['action', 'Action'], ['object', 'Object'], ['workflow', 'Workflow'], ['server_action', 'Server Action']]}, + 'special' : {'name':'special', 'string': 'Special', 'type': 'selection', 'selection': [['',''],['save', 'Save Button'], ['cancel', 'Cancel Button'], ['open', 'Open Button']]}, + 'target' : {'name':'target', 'string': 'Target', 'type': 'selection', 'selection': [['', ''], ['new', 'New Window']]}, + 'confirm' : {'name':'confirm', 'string': 'Confirm', 'type': 'char'}, + 'style' : {'name':'style', 'string': 'Style', 'type': 'selection', 'selection':[["",""],["1", "1"],["1-1", "1-1"],["1-2", "1-2"],["2-1", "2-1"],["1-1-1", "1-1-1"]]}, + 'filename' : {'name':'filename', 'string': 'File Name', 'type': 'char'}, + 'width' : {'name':'width', 'string': 'Width', 'type': 'float'}, + 'height' : {'name':'height', 'string': 'Height', 'type': 'float'}, + 'attrs' : {'name':'attrs', 'string': 'Attrs', 'type': 'char'}, + 'col' : {'name':'col', 'string': 'col', 'type': 'float'}, + 'link' : {'name':'link', 'string': 'Link', 'type': 'char'}, + 'position' : {'name':'position', 'string': 'Position', 'type': 'selection', 'selection': [['',''],['after', 'After'],['before', 'Before'],['inside', 'Inside'],['replace', 'Replace']]}, + 'states' : {'name':'states', 'string': 'states', 'type': 'char'}, + 'eval' : {'name':'eval', 'string': 'Eval', 'type': 'char'}, + 'ref' : {'name':'ref', 'string': 'Ref', 'type': 'char'}, + 'on_change' : {'name':'on_change', 'string': 'On change', 'type': 'char'}, + 'nolabel' : {'name':'nolabel', 'string': 'No label', 'type': 'boolean'}, + 'completion' : {'name':'completion', 'string': 'Completion', 'type': 'boolean'}, + 'colspan' : {'name':'colspan', 'string': 'Colspan', 'type': 'float'}, + 'widget' : {'name':'widget', 'string': 'widget', 'type': 'selection'}, + 'colors' : {'name':'colors', 'string': 'Colors', 'type': 'char'}, + 'editable' : {'name':'editable', 'string': 'Editable', 'type': 'selection', 'selection': [["",""],["top","Top"],["bottom", "Bottom"]]}, + 'groups' : {'name':'groups', 'string': 'Groups', 'type': 'seleciton_multi'}, + }; + var arch_val = self.get_object_by_id(this.one_object.clicked_tr_id,this.one_object['main_object'], []); + this.edit_node_dialog.$element.append('
'); + this.edit_widget = []; + self.ready = $.when(self.on_groups(properties)).then(function () { + _PROPERTIES_ATTRIBUTES['groups']['selection'] = self.groups; + var values = _.keys( openerp.web.form.widgets.map); + values.push(''); + values.sort(); + _PROPERTIES_ATTRIBUTES['widget']['selection'] = values; + var widgets = _.filter(_PROPERTIES_ATTRIBUTES, function(property){ return _.include(properties, property.name)}) + _.each(widgets, function(widget) { + var type_widget = new (self.property.get_any([widget.type])) (self.edit_node_dialog, widget); + var value = _.detect(arch_val[0]['att_list'],function(res) { + return res instanceof Array? _.include(res, widget.name): false; + }); + value = value instanceof Array ? value[1] : value; + self.edit_node_dialog.$element.find('table[id=rec_table]').append('' + widget.string + ':' + type_widget.render() + ''); + type_widget.start(); + type_widget.set_value(value); + self.edit_widget.push(type_widget); + }); + }); + }, + //for getting groups + on_groups: function(properties){ + var self = this, + def = $.Deferred(); + if (!_.include(properties, 'groups')) { + self.groups = false; + def.resolve(); + } + var group_ids = [], group_names = {}, groups = []; + var res_groups = new openerp.web.DataSetSearch(this,'res.groups', null, null), + model_data = new openerp.web.DataSetSearch(self,'ir.model.data', null, null); + res_groups + .read_slice([], {}) + .done(function(res_grp) { + _.each(res_grp,function(res){ + var key = res.id; + group_names[key]=res.name; + group_ids.push(res.id); + }); + model_data + .read_slice([],{domain:[['res_id', 'in', group_ids],['model','=','res.groups']]}) + .done(function(model_grp) { + _.each(model_grp, function(res_group) { + groups.push([res_group.module + "." + res_group.name,group_names[res_group.res_id]]); + }); + self.groups = groups; + def.resolve(); + }); + }) + return def.promise(); + }, + 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': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}]; + this.add_widget = []; + this.add_node_dialog = new openerp.web.Dialog(this,{ + modal: true, + title: 'Properties', + width: 450, + height: 190, + buttons: { + "Update": function(){ + var check_add_node = true, values = {}; + _.each(self.add_widget, function(widget) { + values[widget.name] = widget.get_value() || false; + }); + (values.position == "Inside")? + check_add_node =(_.include(_CHILDREN[properties[0]],values.node_type))?true:false: + check_add_node =(_.include(_CHILDREN[properties[1]],values.node_type))?true:false; + if(values.node_type == "field" && check_add_node ) + {check_add_node = (values.field_value != " ")?true:false; + } + if(check_add_node){ + var tag = (values.node_type == "field")? + _.str.sprintf("<%s name='%s'> ",values.node_type,values.field_value,values.node_type): + _.str.sprintf("<%s> ",values.node_type,values.node_type); + self.do_save_update_arch("add_node", [tag, values.position]); + }else{alert("Can't Update View");} + }, + "Cancel": function(){ + self.add_node_dialog.close(); + } + } + }).start().open(); + this.add_node_dialog.$element.append('
'); + var table_selector = self.add_node_dialog.$element.find('table[id=rec_table] tbody'); + _.each(render_list, function(node) { + type_widget = new (self.property.get_any([node.type])) (self.add_node_dialog, node); + if (node.name == "position") { + table_selector.append('' + node.string + '' + type_widget.render() + ''); + } else { + table_selector.append('' + node.string + '' + type_widget.render() ); + if (node.name == "field_value") { + table_selector.append(' '); + } + } + type_widget.start(); + type_widget.set_value(node.value); + self.add_widget.push(type_widget); + }); + table_selector.find("td[id^=]").attr("width","100px"); + self.add_node_dialog.$element.find('#new_field').click(function() { + model_data = new openerp.web.DataSetSearch(self,'ir.model', null, null); + model_data.read_slice([], {domain: [['model','=', self.model]]}, function(result) { + self.render_new_field(result[0].id); + }); + }); + }, + render_new_field :function(id){ + var self = this; + var action = { + context: {'default_model_id': id, 'manual':true}, + res_model: "ir.model.fields", + views: [[false, 'form']], + type: 'ir.actions.act_window', + target: "new", + flags: { + action_buttons: true, + } + } + var action_manager = new openerp.web.ActionManager(self); + $.when(action_manager.do_action(action)).then(function() { + var controller = action_manager.dialog_viewmanager.views['form'].controller; + controller.do_set_readonly.add_last(function(){ + action_manager.stop(); + new_fields_name = new openerp.web.DataSetSearch(self,'ir.model.fields', null, null); + new_fields_name.read_ids([controller.datarecord.id], ['name'], function(result) { + self.add_node_dialog.$element.find('select[id=field_value]').append($("").attr("value", result[0].name).text(result[0].name)); + _.detect(self.add_widget,function(widget){ + widget.name == "field_value"? widget.selection.push(result[0].name): false; + }); + }); + }); + }); } +}); +openerp.web.ViewEditor.Field = openerp.web.Class.extend({ + init: function(view, widget) { + this.$element = view.$element; + this.dirty = false; + this.name = widget.name; + this.selection = widget.selection || []; + this.required = widget.required || false; + this.string = widget.string || ""; + this.type = widget.type; + this.is_invalid = false; + }, + start: function () { + this.update_dom(); + }, + update_dom: function() { + this.$element.find("td[id=" + this.name + "]").toggleClass('invalid', this.is_invalid); + this.$element.find("td[id=" + this.name + "]").toggleClass('required', this.required); + }, + on_ui_change: function() { + this.validate(); + this.dirty = true; + this.update_dom(); + }, + validate: function() { + this.is_invalid = false; + try { + var value = openerp.web.parse_value(this.get_value(), this, ''); + this.is_invalid = this.required && value === ''; + } catch(e) { + this.is_invalid = true; + } + }, + render: function() { + return _.str.sprintf("%s", this.name, QWeb.render(this.template, {widget: this})) + }, +}); +openerp.web.ViewEditor.FieldBoolean = openerp.web.ViewEditor.Field.extend({ + template : "vieweditor_boolean", + start: function() { + var self = this; + this._super(); + this.$element.find("input[id="+ self.name+"]").change(function() { + self.on_ui_change(); + }); + }, + set_value: function(value) { + if (value) { + this.$element.find("input[id=" + this.name+ "]").attr('checked', true); + } + }, + get_value: function() { + return this.$element.find("input[id=" + this.name + "]").is(':checked')? "1" : null; + } +}); +openerp.web.ViewEditor.FieldChar = openerp.web.ViewEditor.Field.extend({ + template : "vieweditor_char", + start: function () { + var self = this; + this._super(); + this.$element.find("input[id="+ this.name+"]").css('width','100%').change(function() { + self.on_ui_change(); + }); + }, + set_value: function(value) { + this.$element.find("input[id=" + this.name + "]").val(value); + }, + get_value: function() { + return this.$element.find("input[id=" + this.name + "]").val(); + } +}); +openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ + template : "vieweditor_selection", + start: function () { + var self = this; + this._super(); + this.$element.find("select[id=" + this.name + "]").css('width', '100%').change(function() { + self.on_ui_change(); + if (self.name == "node_type") { + if (self.get_value() == "field") { + self.$element.find('#new_field').show(); + self.$element.find("select[id=field_value]").show(); + } else { + self.$element.find('#new_field').hide(); + self.$element.find("select[id=field_value]").hide(); + } + } + }); + }, + set_value: function(value) { + var index = 0; + value = value === null? false: value; + for (var i = 0, ii = this.selection.length; i < ii; i++) { + if ((this.selection[i] instanceof Array && this.selection[i][1] === value) || this.selection[i] === value) index = i; + } + this.$element.find("select[id=" + this.name + "]")[0].selectedIndex = index; + }, + get_value: function() { + return this.$element.find("select[id=" + this.name + "]").val(); + } +}); +openerp.web.ViewEditor.FieldSelectMulti = openerp.web.ViewEditor.FieldSelect.extend({ + start: function () { + this._super(); + this.$element.find("select[id=" + this.name + "]").css('height', '100px').attr("multiple", true); + }, + set_value: function(value) { + var self = this; + self.$element.find("#groups option").attr("selected",false); + if (!value) return false; + _.each(this.selection, function(item) { + if (_.include(value.split(','), item[0])) { + self.$element.find("select[id="+self.name+"] option[value='" + item[0] +"']").attr("selected",1) + } + }); + } +}); +openerp.web.ViewEditor.FieldFloat = openerp.web.ViewEditor.FieldChar.extend({ +}); +var _PROPERTIES = { + 'field' : ['name', 'string', 'required', 'readonly', 'domain', 'context', 'nolabel', 'completion', + 'colspan', 'widget', 'eval', 'ref', 'on_change', 'attrs', 'groups'], + 'form' : ['string', 'col', 'link'], + 'notebook' : ['colspan', 'position', 'groups'], + 'page' : ['string', 'states', 'attrs', 'groups'], + 'group' : ['string', 'col', 'colspan', 'states', 'attrs', 'groups'], + 'image' : ['filename', 'width', 'height', 'groups'], + 'separator' : ['string', 'colspan', 'groups'], + 'label': ['string', 'align', 'colspan', 'groups'], + 'button': ['name', 'string', 'icon', 'type', 'states', 'readonly', 'special', 'target', 'confirm', 'context', 'attrs', 'colspan', 'groups'], + 'newline' : [], + 'board': ['style'], + 'column' : [], + 'action' : ['name', 'string', 'colspan', 'groups'], + 'tree' : ['string', 'colors', 'editable', 'link', 'limit', 'min_rows'], + 'graph' : ['string', 'type'], + 'calendar' : ['string', 'date_start', 'date_stop', 'date_delay', 'day_length', 'color', 'mode'], +}; +var _CHILDREN = { + 'form': ['notebook', 'group', 'field', 'label', 'button','board', 'newline', 'separator'], + 'tree': ['field'], + 'graph': ['field'], + 'calendar': ['field'], + 'notebook': ['page'], + 'page': ['notebook', 'group', 'field', 'label', 'button', 'newline', 'separator'], + 'group': ['field', 'label', 'button', 'separator', 'newline'], + 'board': ['column'], + 'action': [], + 'field': ['form', 'tree', 'graph'], + 'label': [], + 'button' : [], + 'newline': [], + 'separator': [], +}; +var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD', + 'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER', + 'STOCK_CONNECT', 'STOCK_CONVERT', 'STOCK_COPY', 'STOCK_CUT', 'STOCK_DELETE', + 'STOCK_DIALOG_AUTHENTICATION', 'STOCK_DIALOG_ERROR', 'STOCK_DIALOG_INFO', + 'STOCK_DIALOG_QUESTION', 'STOCK_DIALOG_WARNING', 'STOCK_DIRECTORY', 'STOCK_DISCONNECT', + 'STOCK_DND', 'STOCK_DND_MULTIPLE', 'STOCK_EDIT', 'STOCK_EXECUTE', 'STOCK_FILE', + 'STOCK_FIND', 'STOCK_FIND_AND_REPLACE', 'STOCK_FLOPPY', 'STOCK_GOTO_BOTTOM', + 'STOCK_GOTO_FIRST', 'STOCK_GOTO_LAST', 'STOCK_GOTO_TOP', 'STOCK_GO_BACK', + 'STOCK_GO_DOWN', 'STOCK_GO_FORWARD', 'STOCK_GO_UP', 'STOCK_HARDDISK', + 'STOCK_HELP', 'STOCK_HOME', 'STOCK_INDENT', 'STOCK_INDEX', 'STOCK_ITALIC', + 'STOCK_JUMP_TO', 'STOCK_JUSTIFY_CENTER', 'STOCK_JUSTIFY_FILL', + 'STOCK_JUSTIFY_LEFT', 'STOCK_JUSTIFY_RIGHT', 'STOCK_MEDIA_FORWARD', + 'STOCK_MEDIA_NEXT', 'STOCK_MEDIA_PAUSE', 'STOCK_MEDIA_PLAY', + 'STOCK_MEDIA_PREVIOUS', 'STOCK_MEDIA_RECORD', 'STOCK_MEDIA_REWIND', + 'STOCK_MEDIA_STOP', 'STOCK_MISSING_IMAGE', 'STOCK_NETWORK', 'STOCK_NEW', + 'STOCK_NO', 'STOCK_OK', 'STOCK_OPEN', 'STOCK_PASTE', 'STOCK_PREFERENCES', + 'STOCK_PRINT', 'STOCK_PRINT_PREVIEW', 'STOCK_PROPERTIES', 'STOCK_QUIT', + 'STOCK_REDO', 'STOCK_REFRESH', 'STOCK_REMOVE', 'STOCK_REVERT_TO_SAVED', + 'STOCK_SAVE', 'STOCK_SAVE_AS', 'STOCK_SELECT_COLOR', 'STOCK_SELECT_FONT', + 'STOCK_SORT_ASCENDING', 'STOCK_SORT_DESCENDING', 'STOCK_SPELL_CHECK', + 'STOCK_STOP', 'STOCK_STRIKETHROUGH', 'STOCK_UNDELETE', 'STOCK_UNDERLINE', + 'STOCK_UNDO', 'STOCK_UNINDENT', 'STOCK_YES', 'STOCK_ZOOM_100', + 'STOCK_ZOOM_FIT', 'STOCK_ZOOM_IN', 'STOCK_ZOOM_OUT', + 'terp-account', 'terp-crm', 'terp-mrp', 'terp-product', 'terp-purchase', + 'terp-sale', 'terp-tools', 'terp-administration', 'terp-hr', 'terp-partner', + 'terp-project', 'terp-report', 'terp-stock', 'terp-calendar', 'terp-graph' +]; +openerp.web.ViewEditor.property_widget = new openerp.web.Registry({ + 'boolean' : 'openerp.web.ViewEditor.FieldBoolean', + 'seleciton_multi' : 'openerp.web.ViewEditor.FieldSelectMulti', + 'selection' : 'openerp.web.ViewEditor.FieldSelect', + 'char' : 'openerp.web.ViewEditor.FieldChar', + 'float' : 'openerp.web.ViewEditor.FieldFloat', }); }; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 15790d3c1c0..ced99bea7c2 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -35,7 +35,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.fields = {}; this.datarecord = {}; this.show_invalid = true; - this.dirty_for_user = false; this.default_focus_field = null; this.default_focus_button = null; this.registry = this.readonly ? openerp.web.form.readonly : openerp.web.form.widgets; @@ -108,7 +107,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.$form_header.find('button.oe_form_button_delete').click(this.on_button_delete); this.$form_header.find('button.oe_form_button_toggle').click(this.on_toggle_readonly); - if (this.options.sidebar && this.options.sidebar_id) { + if (!this.sidebar && this.options.sidebar && this.options.sidebar_id) { this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id); this.sidebar.start(); this.sidebar.do_unfold(); @@ -141,7 +140,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# // null index means we should start a new record promise = this.on_button_new(); } else { - promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); + promise = this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_record_loaded); } this.$element.show(); if (this.sidebar) { @@ -156,6 +155,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } }, on_record_loaded: function(record) { + var self = this, + deferred_stack = $.Deferred.queue(); if (!record) { throw("Form: No record received"); } @@ -172,35 +173,42 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } this.$form_header.find('.oe_form_on_readonly').toggle(this.readonly); this.$form_header.find('.oe_form_on_editable').toggle(!this.readonly); - this.dirty_for_user = false; this.datarecord = record; - for (var f in this.fields) { - var field = this.fields[f]; - field.dirty = false; - field.set_value(this.datarecord[f] || false); - field.validate(); - } - if (!record.id) { - // New record: Second pass in order to trigger the onchanges - this.show_invalid = false; - for (var f in record) { - var field = this.fields[f]; - if (field) { - field.dirty = true; - this.do_onchange(field); + + _(this.fields).each(function (field, f) { + field.reset(); + var result = field.set_value(self.datarecord[f] || false); + if (result && _.isFunction(result.promise)) { + deferred_stack.push(result); + } + $.when(result).then(function() { + field.validate(); + }); + }); + deferred_stack.push('force resolution if no fields'); + return deferred_stack.then(function() { + if (!record.id) { + // New record: Second pass in order to trigger the onchanges + self.show_invalid = false; + for (var f in record) { + var field = self.fields[f]; + if (field) { + field.dirty = true; + self.do_onchange(field); + } } } - } - this.on_form_changed(); - this.initial_mutating_lock.resolve(); - this.show_invalid = true; - this.do_update_pager(record.id == null); - if (this.sidebar) { - this.sidebar.attachments.do_update(); - } - if (this.default_focus_field && !this.embedded_view) { - this.default_focus_field.focus(); - } + self.on_form_changed(); + self.initial_mutating_lock.resolve(); + self.show_invalid = true; + self.do_update_pager(record.id == null); + if (self.sidebar) { + self.sidebar.attachments.do_update(); + } + if (self.default_focus_field && !self.embedded_view) { + self.default_focus_field.focus(); + } + }); }, on_form_changed: function() { for (var w in this.widgets) { @@ -234,69 +242,99 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# $pager.find('span.oe_pager_index').html(index); $pager.find('span.oe_pager_count').html(this.dataset.ids.length); }, + parse_on_change: function (on_change, widget) { + var self = this; + var onchange = _.str.trim(on_change); + var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); + if (!call) { + return null; + } + + var method = call[1]; + if (!_.str.trim(call[2])) { + return {method: method, args: [], context_index: null} + } + + var argument_replacement = { + 'False': function () {return false;}, + 'True': function () {return true;}, + 'None': function () {return null;}, + 'context': function (i) { + context_index = i; + var ctx = widget.build_context ? widget.build_context() : {}; + return ctx; + } + }; + var parent_fields = null, context_index = null; + var args = _.map(call[2].split(','), function (a, i) { + var field = _.str.trim(a); + + // literal constant or context + if (field in argument_replacement) { + return argument_replacement[field](i); + } + // literal number + if (/^-?\d+(\.\d+)?$/.test(field)) { + return Number(field); + } + // form field + if (self.fields[field]) { + var value = self.fields[field].get_on_change_value(); + return value == null ? false : value; + } + // parent field + var splitted = field.split('.'); + if (splitted.length > 1 && _.str.trim(splitted[0]) === "parent" && self.dataset.parent_view) { + if (parent_fields === null) { + parent_fields = self.dataset.parent_view.get_fields_values(); + } + var p_val = parent_fields[_.str.trim(splitted[1])]; + if (p_val !== undefined) { + return p_val == null ? false : p_val; + } + } + // string literal + var first_char = field[0], last_char = field[field.length-1]; + if ((first_char === '"' && last_char === '"') + || (first_char === "'" && last_char === "'")) { + return field.slice(1, -1); + } + + throw new Error("Could not get field with name '" + field + + "' for onchange '" + onchange + "'"); + }); + + return { + method: method, + args: args, + context_index: context_index + }; + }, do_onchange: function(widget, processed) { var self = this; var act = function() { try { - processed = processed || []; - if (widget.node.attrs.on_change) { - var onchange = _.trim(widget.node.attrs.on_change); - var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); - if (call) { - var method = call[1], args = []; - var context_index = null; - var argument_replacement = { - 'False' : function() {return false;}, - 'True' : function() {return true;}, - 'None' : function() {return null;}, - 'context': function(i) { - context_index = i; - var ctx = widget.build_context ? widget.build_context() : {}; - return ctx; - } - }; - var parent_fields = null; - _.each(call[2].split(','), function(a, i) { - var field = _.trim(a); - if (field in argument_replacement) { - args.push(argument_replacement[field](i)); - return; - } else if (self.fields[field]) { - var value = self.fields[field].get_on_change_value(); - args.push(value == null ? false : value); - return; - } else { - var splitted = field.split('.'); - if (splitted.length > 1 && _.trim(splitted[0]) === "parent" && self.dataset.parent_view) { - if (parent_fields === null) { - parent_fields = self.dataset.parent_view.get_fields_values(); - } - var p_val = parent_fields[_.trim(splitted[1])]; - if (p_val !== undefined) { - args.push(p_val == null ? false : p_val); - return; - } - } - } - throw "Could not get field with name '" + field + - "' for onchange '" + onchange + "'"; - }); - var ajax = { - url: '/web/dataset/call', - async: false - }; - return self.rpc(ajax, { - model: self.dataset.model, - method: method, - args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(args), - context_id: context_index === null ? null : context_index + 1 - }).pipe(function(response) { - return self.on_processed_onchange(response, processed); - }); - } else { - console.warn("Wrong on_change format", on_change); + processed = processed || []; + var on_change = widget.node.attrs.on_change; + if (on_change) { + var change_spec = self.parse_on_change(on_change, widget); + if (change_spec) { + var ajax = { + url: '/web/dataset/call', + async: false + }; + return self.rpc(ajax, { + model: self.dataset.model, + method: change_spec.method, + args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args), + context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1 + }).pipe(function(response) { + return self.on_processed_onchange(response, processed); + }); + } else { + console.warn("Wrong on_change format", on_change); + } } - } } catch(e) { console.error(e); return $.Deferred().reject(); @@ -317,7 +355,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# processed.push(field.name); if (field.get_value() != value) { field.set_value(value); - field.dirty = this.dirty_for_user = true; + field.dirty = true; if (_.indexOf(processed, field.name) < 0) { this.do_onchange(field, processed); } @@ -356,12 +394,13 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# var keys = _.keys(self.fields_view.fields); $.when(self.do_set_editable()).then(function() { if (keys.length) { - self.dataset.default_get(keys).then(self.on_record_loaded).then(function() { + self.dataset.default_get(keys).pipe(self.on_record_loaded).then(function() { def.resolve(); }); } else { - self.on_record_loaded({}); - def.resolve(); + self.on_record_loaded({}).then(function() { + def.resolve(); + }); } }); } @@ -387,16 +426,22 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# var def = $.Deferred(); $.when(this.has_been_loaded).then(function() { if (self.can_be_discarded() && self.datarecord.id) { - self.dataset.unlink([self.datarecord.id]).then(function() { - self.on_pager_action('next'); - def.resolve(); - }); + if (confirm(_t("Do you really want to delete this record?"))) { + self.dataset.unlink([self.datarecord.id]).then(function() { + self.on_pager_action('next'); + def.resolve(); + }); + } else { + setTimeout(function () { + def.reject(); + }, 0) + } } }); return def.promise(); }, can_be_discarded: function() { - return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); + return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); }, /** * Triggers saving the form's record. Chooses between creating a new @@ -412,8 +457,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# try { if (!self.initial_mutating_lock.isResolved() && !self.initial_mutating_lock.isRejected()) return; - var form_dirty = false, - form_invalid = false, + var form_invalid = false, values = {}, first_invalid_field = null; for (var f in self.fields) { @@ -424,8 +468,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (!first_invalid_field) { first_invalid_field = f; } - } else if (f.is_dirty()) { - form_dirty = true; + } else if (f.name !== 'id' && !f.readonly && (!self.datarecord.id || f.is_dirty())) { + // Special case 'id' field, do not save this field + // on 'create' : save all non readonly fields + // on 'edit' : save non readonly modified fields values[f.name] = f.get_value(); } } @@ -474,8 +520,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# // should not happen in the server, but may happen for internal purpose return $.Deferred().reject(); } else { - this.reload(); - return $.when(r).then(success); + return $.when(this.reload()).pipe(function () { + return $.when(r).then(success); }, null); } }, /** @@ -522,7 +568,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (self.dataset.index == null || self.dataset.index < 0) { return $.when(self.on_button_new()); } else { - return self.dataset.read_index(_.keys(self.fields_view.fields), self.on_record_loaded); + return self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_record_loaded); } }; this.reload_lock = this.reload_lock.pipe(act, act); @@ -547,6 +593,11 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return self.dataset.parent_view.recursive_save(); }); }, + is_dirty: function() { + return _.any(this.fields, function (value) { + return value.is_dirty(); + }); + }, is_interactible_record: function() { var id = this.datarecord.id; if (!id) { @@ -557,6 +608,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return false; } return true; + }, + sidebar_context: function () { + return this.do_save().pipe($.proxy(this, 'get_fields_values')); } }); openerp.web.FormDialog = openerp.web.Dialog.extend({ @@ -632,7 +686,7 @@ openerp.web.form.SidebarAttachments = openerp.web.Widget.extend({ }, on_attachment_delete: function(e) { var self = this, $e = $(e.currentTarget); - var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); + var name = _.str.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); if (confirm("Do you really want to delete the attachment " + name + " ?")) { this.rpc('/web/dataset/unlink', { model: 'ir.attachment', @@ -770,11 +824,35 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form. var template = this.template; return QWeb.render(template, { "widget": this }); }, + do_attach_tooltip: function(widget, trigger, options) { + widget = widget || this; + trigger = trigger || this.$element; + options = _.extend({ + delay: 1000, + maxWidth: openerp.connection.debug ? '300px' : '200px', + content: function() { + var template = widget.template + '.tooltip'; + if (!QWeb.has_template(template)) { + template = 'WidgetLabel.tooltip'; + } + return QWeb.render(template, { + debug: openerp.connection.debug, + widget: widget + }); + } + }, options || {}); + trigger.tipTip(options); + }, _build_view_fields_values: function() { var a_dataset = this.view.dataset; var fields_values = this.view.get_fields_values(); - var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {}; - fields_values.parent = parent_values; + var active_id = a_dataset.ids[a_dataset.index]; + _.extend(fields_values, { + active_id: active_id || false, + active_ids: active_id ? [active_id] : [], + active_model: a_dataset.model, + parent: a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {} + }); return fields_values; }, _build_eval_context: function() { @@ -877,8 +955,9 @@ openerp.web.form.WidgetFrame = openerp.web.form.Widget.extend({ var type = {}; if (node.tag == 'field') { type = this.view.fields_view.fields[node.attrs.name] || {}; - if (node.attrs.widget == 'statusbar') { + if (node.attrs.widget == 'statusbar' && node.attrs.nolabel !== '1') { // This way we can retain backward compatibility between addons and old clients + node.attrs.colspan = (parseInt(node.attrs.colspan, 10) || 1) + 1; node.attrs.nolabel = '1'; } } @@ -910,6 +989,10 @@ openerp.web.form.WidgetFrame = openerp.web.form.Widget.extend({ } }); +openerp.web.form.WidgetGroup = openerp.web.form.WidgetFrame.extend({ + template: 'WidgetGroup' +}), + openerp.web.form.WidgetNotebook = openerp.web.form.Widget.extend({ template: 'WidgetNotebook', init: function(view, node) { @@ -938,6 +1021,11 @@ openerp.web.form.WidgetNotebook = openerp.web.form.Widget.extend({ }); this.$element.tabs(); this.view.on_button_new.add_first(this.do_select_first_visible_tab); + if (openerp.connection.debug) { + this.do_attach_tooltip(this, this.$element.find('ul:first'), { + defaultPosition: 'top' + }); + } }, do_select_first_visible_tab: function() { for (var i = 0; i < this.pages.length; i++) { @@ -1001,6 +1089,9 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({ start: function() { this._super.apply(this, arguments); this.$element.find("button").click(this.on_click); + if (this.help || openerp.connection.debug) { + this.do_attach_tooltip(); + } }, on_click: function() { var self = this; @@ -1100,6 +1191,9 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ start: function() { this._super(); var self = this; + if (this['for'] && (this['for'].help || openerp.connection.debug)) { + this.do_attach_tooltip(self['for']); + } this.$element.find("label").dblclick(function() { var widget = self['for'] || self; openerp.log(widget.element_class , widget); @@ -1134,8 +1228,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f this.nolabel = (this.field.nolabel || node.attrs.nolabel) === '1'; this.readonly = this.modifiers['readonly'] === true; this.required = this.modifiers['required'] === true; - this.invalid = false; - this.dirty = false; + this.invalid = this.dirty = false; this.classname = 'oe_form_field_' + this.type; }, @@ -1145,6 +1238,11 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f this.view.translatable_fields.push(this); this.$element.find('.oe_field_translate').click(this.on_translate); } + if (this.nolabel && openerp.connection.debug) { + this.do_attach_tooltip(this, this.$element, { + defaultPosition: 'top' + }); + } }, set_value: function(value) { this.value = value; @@ -1186,7 +1284,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f } }, on_ui_change: function() { - this.dirty = this.view.dirty_for_user = true; + this.dirty = true; this.validate(); if (this.is_valid()) { this.set_value_from_ui(); @@ -1200,6 +1298,9 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f this.invalid = false; }, focus: function() { + }, + reset: function() { + this.dirty = false; } }); @@ -1289,7 +1390,6 @@ openerp.web.form.FieldFloat = openerp.web.form.FieldChar.extend({ if (value === false || value === undefined) { // As in GTK client, floats default to 0 value = 0; - this.dirty = true; } this._super.apply(this, [value]); } @@ -1299,54 +1399,58 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ template: "web.datetimepicker", jqueryui_object: 'datetimepicker', type_of_date: "datetime", + init: function(parent) { + this._super(parent); + this.name = parent.name; + }, start: function() { var self = this; - this.$element.find('input').change(this.on_change); + this.$input = this.$element.find('input.oe_datepicker_master'); + this.$input_picker = this.$element.find('input.oe_datepicker_container'); + this.$input.change(this.on_change); this.picker({ onSelect: this.on_picker_select, changeMonth: true, changeYear: true, showWeek: true, - showButtonPanel: false + showButtonPanel: true }); this.$element.find('img.oe_datepicker_trigger').click(function() { if (!self.readonly) { self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date()); - self.$element.find('.oe_datepicker').toggle(); + self.$input_picker.show(); + self.picker('show'); + self.$input_picker.hide(); } }); - this.$element.find('.ui-datepicker-inline').removeClass('ui-widget-content ui-corner-all'); - this.$element.find('button.oe_datepicker_close').click(function() { - self.$element.find('.oe_datepicker').hide(); - }); this.set_readonly(false); this.value = false; }, picker: function() { - return $.fn[this.jqueryui_object].apply(this.$element.find('.oe_datepicker_container'), arguments); + return $.fn[this.jqueryui_object].apply(this.$input_picker, arguments); }, on_picker_select: function(text, instance) { var date = this.picker('getDate'); - this.$element.find('input').val(date ? this.format_client(date) : '').change(); + this.$input.val(date ? this.format_client(date) : '').change(); }, set_value: function(value) { this.value = value; - this.$element.find('input').val(value ? this.format_client(value) : ''); + this.$input.val(value ? this.format_client(value) : ''); }, get_value: function() { return this.value; }, set_value_from_ui: function() { - var value = this.$element.find('input').val() || false; + var value = this.$input.val() || false; this.value = this.parse_client(value); }, set_readonly: function(readonly) { this.readonly = readonly; - this.$element.find('input').attr('disabled', this.readonly); + this.$input.attr('disabled', this.readonly); this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly); }, is_valid: function(required) { - var value = this.$element.find('input').val(); + var value = this.$input.val(); if (value === "") { return !required; } else { @@ -1359,7 +1463,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ } }, focus: function() { - this.$element.find('input').focus(); + this.$input.focus(); }, parse_client: function(v) { return openerp.web.parse_value(v, {"widget": this.type_of_date}); @@ -1376,11 +1480,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ openerp.web.DateWidget = openerp.web.DateTimeWidget.extend({ jqueryui_object: 'datepicker', - type_of_date: "date", - on_picker_select: function(text, instance) { - this._super(text, instance); - this.$element.find('.oe_datepicker').hide(); - } + type_of_date: "date" }); openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({ @@ -1392,7 +1492,7 @@ openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({ var self = this; this._super.apply(this, arguments); this.datewidget = this.build_widget(); - this.datewidget.on_change.add(this.on_ui_change); + this.datewidget.on_change.add_last(this.on_ui_change); this.datewidget.appendTo(this.$element); }, set_value: function(value) { @@ -1780,7 +1880,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ if (search_val.length > 0 && !_.include(raw_result, search_val) && (!self.value || search_val !== self.value[1])) { - values.push({label: _.sprintf(_t('   Create "%s"'), + values.push({label: _.str.sprintf(_t('   Create "%s"'), $('').text(search_val).html()), action: function() { self._quick_create(search_val); }}); @@ -2035,7 +2135,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ once.resolve(); }); controller.on_pager_action.add_first(function() { - self.save_form_view(); + self.save_any_view(); }); controller.$element.find(".oe_form_button_save").hide(); } else if (view_type == "graph") { @@ -2044,7 +2144,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ def.resolve(); }); this.viewmanager.on_mode_switch.add_first(function(n_mode, b, c, d, e) { - $.when(self.save_form_view()).then(function() { + $.when(self.save_any_view()).then(function() { if(n_mode === "list") setTimeout(function() {self.reload_current_view();}, 0); }); @@ -2058,7 +2158,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ }, reload_current_view: function() { var self = this; - self.is_loaded = self.is_loaded.pipe(function() { + return self.is_loaded = self.is_loaded.pipe(function() { var view = self.viewmanager.views[self.viewmanager.active_view].controller; if(self.viewmanager.active_view === "list") { return view.reload_content(); @@ -2131,8 +2231,8 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ if (this.dataset.index === null && this.dataset.ids.length > 0) { this.dataset.index = 0; } - self.reload_current_view(); - this.is_setted.resolve(); + self.is_setted.resolve(); + return self.reload_current_view(); }, get_value: function() { var self = this; @@ -2154,7 +2254,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ this.dataset.to_delete, function(x) { return commands['delete'](x.id);})); }, - save_form_view: function() { + save_any_view: function() { if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view && this.viewmanager.views[this.viewmanager.active_view] && this.viewmanager.views[this.viewmanager.active_view].controller) { @@ -2166,6 +2266,13 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ console.warn("Asynchronous get_value() is not supported in form view."); }*/ return res; + } else if (this.viewmanager.active_view === "list") { + var res = $.when(view.ensure_saved()); + // it seems line there are some cases when this happens + /*if (!res.isResolved() && !res.isRejected()) { + console.warn("Asynchronous get_value() is not supported in list view."); + }*/ + return res; } } return false; @@ -2190,7 +2297,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ } }, is_dirty: function() { - this.save_form_view(); + this.save_any_view(); return this._super(); }, update_dom: function() { @@ -2318,6 +2425,10 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({ 'deletable': self.is_readonly() ? false : true, 'selectable': self.multi_selection }); + var embedded = (this.field.views || {}).tree; + if (embedded) { + this.list_view.set_embedded_view(embedded); + } this.list_view.m2m_field = this; var loaded = $.Deferred(); this.list_view.on_loaded.add_last(function() { @@ -2419,7 +2530,8 @@ openerp.web.form.SelectCreatePopup = openerp.web.OldWidget.extend(/** @lends ope }, read_function: null}); this.initial_ids = this.options.initial_ids; this.created_elements = []; - openerp.web.form.dialog(this.render(), {close:function() { + this.render_element(); + openerp.web.form.dialog(this.$element, {close:function() { self.check_exit(); }}); this.start(); @@ -2607,7 +2719,8 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp this.row_id = row_id; this.context = context || {}; this.options = _.defaults(options || {}, {"auto_write": true}); - jQuery(this.render()).dialog({title: '', + this.render_element(); + this.$element.dialog({title: '', modal: true, width: 960, height: 600}); @@ -2897,7 +3010,7 @@ openerp.web.form.FieldStatus = openerp.web.form.Field.extend({ render_list: function() { var self = this; var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","), - function(x) { return _.trim(x); }); + function(x) { return _.str.trim(x); }); shown = _.select(shown, function(x) { return x.length > 0; }); if (shown.length == 0) { @@ -3013,7 +3126,7 @@ openerp.web.form.FieldSelectionReadonly = openerp.web.form.FieldReadonly.extend( this.$element.find('div').text(option ? option[1] : this.values[0][1]); } }); -openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.extend({ +openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldURIReadonly.extend({ set_value: function (value) { value = value || null; this.invalid = false; @@ -3023,24 +3136,39 @@ openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.exte self.on_value_changed(); var real_set_value = function(rval) { self.value = rval; - var div = $(self.$element.find('div')); - div.html(''); - var a = $(div.find("a")); - a.text(rval ? rval[1] : ''); - a.click(function() { - var pop = new openerp.web.form.FormOpenPopup(self.view); - pop.show_element(self.field.relation, self.value[0],self.build_context(), {readonly:true}); - }); + self.$element.find('a') + .unbind('click') + .text(rval ? rval[1] : '') + .click(function () { + self.do_action({ + type: 'ir.actions.act_window', + res_model: self.field.relation, + res_id: self.value[0], + context: self.build_context(), + views: [[false, 'form']], + target: 'current' + }); + return false; + }); }; if (value && !(value instanceof Array)) { - var dataset = new openerp.web.DataSetStatic( - this, this.field.relation, self.build_context()); - dataset.name_get([value], function(data) { - real_set_value(data[0]); - }).fail(function() {self.tmp_value = undefined;}); + new openerp.web.DataSetStatic( + this, this.field.relation, self.build_context()) + .name_get([value], function(data) { + real_set_value(data[0]); + }); } else { setTimeout(function() {real_set_value(value);}, 0); } + }, + get_value: function() { + if (!this.value) { + return false; + } else if (this.value instanceof Array) { + return this.value[0]; + } else { + return this.value; + } } }); @@ -3049,7 +3177,7 @@ openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.exte */ openerp.web.form.widgets = new openerp.web.Registry({ 'frame' : 'openerp.web.form.WidgetFrame', - 'group' : 'openerp.web.form.WidgetFrame', + 'group' : 'openerp.web.form.WidgetGroup', 'notebook' : 'openerp.web.form.WidgetNotebook', 'notebookpage' : 'openerp.web.form.WidgetNotebookPage', 'separator' : 'openerp.web.form.WidgetSeparator', diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index e891a6c7db7..728b090d679 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -295,7 +295,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# } else { last = first + limit; } - this.$element.find('span.oe-pager-state').empty().text(_.sprintf( + this.$element.find('span.oe-pager-state').empty().text(_.str.sprintf( "[%d to %d] of %d", first + 1, last, total)); this.$element @@ -365,6 +365,9 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# return {}; } var aggregation_func = column['group_operator'] || 'sum'; + if (!(aggregation_func in column)) { + return {}; + } return _.extend({}, column, { 'function': aggregation_func, @@ -476,7 +479,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# * @param {Array} ids the ids of the records to delete */ do_delete: function (ids) { - if (!(ids.length && confirm(_t("Are you sure to remove those records ?")))) { + if (!(ids.length && confirm(_t("Do you really want to remove these records?")))) { return; } var self = this; @@ -644,7 +647,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# return; } - $footer_cells.filter(_.sprintf('[data-field=%s]', column.id)) + $footer_cells.filter(_.str.sprintf('[data-field=%s]', column.id)) .html(openerp.web.format_cell(aggregation, column, undefined, false)); }); }, @@ -873,15 +876,20 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis } var cells = []; if (this.options.selectable) { - cells.push(''); + cells.push(''); } _(this.columns).each(function(column) { - if (column.invisible !== '1') { + if (column.invisible === '1') { + return; + } + if (column.tag === 'button') { + cells.push(' '); + } else { cells.push(' '); } }); if (this.options.deletable) { - cells.push(''); + cells.push(''); } cells.unshift(''); cells.push(''); @@ -1119,7 +1127,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L child.datagroup = group; var $row = child.$row = $(''); - if (group.openable) { + if (group.openable && group.length) { $row.click(function (e) { if (!$row.data('open')) { $row.data('open', true) @@ -1145,10 +1153,19 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L row_data[group.grouped_on] = group; var group_column = _(self.columns).detect(function (column) { return column.id === group.grouped_on; }); - $group_column.html(openerp.web.format_cell( - row_data, group_column, _t("Undefined") - )); - if (group.openable) { + try { + $group_column.html(openerp.web.format_cell( + row_data, group_column, _t("Undefined"))); + } catch (e) { + $group_column.html(row_data[group_column.id].value); + } + if (!group.length) { + // Kinda-ugly hack: jquery-ui has no "empty" icon, so set + // wonky background position to ensure nothing is displayed + // there but the rest of the behavior is ui-icon's + $group_column.prepend( + ''); + } else if (group.openable) { // Make openable if not terminal group & group_by_no_leaf $group_column .prepend(''); @@ -1175,7 +1192,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L format = "%.2f"; } $('') - .text(_.sprintf(format, value)) + .text(_.str.sprintf(format, value)) .appendTo($row); } else { $row.append(''); @@ -1234,7 +1251,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L var pages = Math.ceil(dataset.ids.length / limit); self.$row .find('.oe-pager-state') - .text(_.sprintf('%d/%d', page + 1, pages)) + .text(_.str.sprintf('%d/%d', page + 1, pages)) .end() .find('button[data-pager-action=previous]') .attr('disabled', page === 0) diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index dba0a1abba4..f6b7f85dee1 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -5,6 +5,7 @@ openerp.web.list_editable = function (openerp) { var KEY_RETURN = 13, KEY_ESCAPE = 27; + var QWeb = openerp.web.qweb; // editability status of list rows openerp.web.ListView.prototype.defaults.editable = null; @@ -350,6 +351,19 @@ openerp.web.list_editable = function (openerp) { new_record: function () { this.dataset.index = null; this.render_row_as_form(); + }, + render_record: function (record) { + var index = this.records.indexOf(record); + // FIXME: context dict should probably be extracted cleanly + return QWeb.render('ListView.row', { + columns: this.columns, + options: this.options, + record: record, + row_parity: (index % 2 === 0) ? 'even' : 'odd', + view: this.view, + render_cell: $.proxy(this, 'render_cell'), + edited: !!this.edition_form + }); } }); if (!openerp.web.list) { diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index 5143adb3838..34d47b92813 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -42,7 +42,8 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# model: this.model, view_id: this.view_id, view_type: "tree", - toolbar: this.view_manager ? !!this.view_manager.sidebar : false + toolbar: this.view_manager ? !!this.view_manager.sidebar : false, + context: this.dataset.get_context() }, this.on_loaded); }, /** @@ -214,17 +215,23 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# // Get details in listview activate: function(id) { var self = this; + var local_context = { + active_model: self.dataset.model, + active_id: id, + active_ids: [id]}; this.rpc('/web/treeview/action', { id: id, model: this.dataset.model, context: new openerp.web.CompoundContext( - this.dataset.get_context(), { - active_model: this.dataset.model, - active_id: id, - active_ids: [id]}) + this.dataset.get_context(), local_context) }, function (actions) { if (!actions.length) { return; } var action = actions[0][2]; + var c = new openerp.web.CompoundContext(local_context); + if (action.context) { + c.add(action.context); + } + action.context = c; self.do_action(action); }); }, diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index a6aaf02d5e6..5a26ef58b03 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -143,7 +143,7 @@ session.web.ActionManager = session.web.Widget.extend({ var ClientWidget = session.web.client_actions.get_object(action.tag); (this.client_widget = new ClientWidget(this, action.params)).appendTo(this); }, - ir_actions_report_xml: function(action) { + ir_actions_report_xml: function(action, on_closed) { var self = this; $.blockUI(); self.rpc("/web/session/eval_domain_and_context", { @@ -155,8 +155,14 @@ session.web.ActionManager = session.web.Widget.extend({ self.session.get_file({ url: '/web/report', data: {action: JSON.stringify(action)}, - complete: $.unblockUI - }); + complete: $.unblockUI, + success: function(){ + if (!self.dialog && on_closed) { + on_closed(); + } + self.dialog_stop(); + } + }) }); }, ir_actions_act_url: function (action) { @@ -210,7 +216,7 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View sidebar_id : self.element_id + '_sidebar_' + view.view_type, action : self.action, action_views_ids : views_ids - }, self.flags, view.options || {}) + }, self.flags, self.flags[view.view_type] || {}, view.options || {}) }); views_ids[view.view_type] = view.view_id; }); @@ -468,10 +474,10 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner } var $title = self.$element.find('.oe_view_title'), - $search_prefix = $title.find('span'); + $search_prefix = $title.find('span.oe_searchable_view'); if (controller.searchable !== false) { if (!$search_prefix.length) { - $title.prepend('' + _t("Search:") + ''); + $title.prepend('' + _t("Search: ") + ''); } } else { $search_prefix.remove(); @@ -534,7 +540,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner $logs_list = $logs.find('ul').empty(); $logs.toggleClass('oe-has-more', log_records.length > cutoff); _(log_records.reverse()).each(function (record) { - $(_.sprintf('
  • %s
  • ', record.name)) + $(_.str.sprintf('
  • %s
  • ', record.name)) .appendTo($logs_list) .delegate('a', 'click', function (e) { self.do_action({ @@ -568,35 +574,26 @@ session.web.Sidebar = session.web.Widget.extend({ self.do_toggle(); }); }, - - call_default_on_sidebar: function(item) { - var func_name = 'on_sidebar_' + _.underscored(item.label); - var fn = this.widget_parent[func_name]; - if(typeof fn === 'function') { - fn(item); - } - }, - add_default_sections: function() { if (this.session.uid === 1) { this.add_section(_t('Customize'), 'customize'); this.add_items('customize', [ { label: _t("Manage Views"), - callback: this.call_default_on_sidebar, + callback: this.widget_parent.on_sidebar_manage_views, title: _t("Manage views of the current object") }, { label: _t("Edit Workflow"), - callback: this.call_default_on_sidebar, + callback: this.widget_parent.on_sidebar_edit_workflow, title: _t("Manage views of the current object"), classname: 'oe_hide oe_sidebar_edit_workflow' }, { label: _t("Customize Object"), - callback: this.call_default_on_sidebar, + callback: this.widget_parent.on_sidebar_customize_object, title: _t("Manage views of the current object") }, { label: _t("Translate"), - callback: this.call_default_on_sidebar, + callback: this.widget_parent.on_sidebar_translate, title: _t("Technical translation") } ]); @@ -606,13 +603,13 @@ session.web.Sidebar = session.web.Widget.extend({ this.add_items('other', [ { label: _t("Import"), - callback: this.call_default_on_sidebar + callback: this.widget_parent.on_sidebar_import }, { label: _t("Export"), - callback: this.call_default_on_sidebar + callback: this.widget_parent.on_sidebar_export }, { label: _t("View Log"), - callback: this.call_default_on_sidebar, + callback: this.widget_parent.on_sidebar_view_log, classname: 'oe_hide oe_sidebar_view_log' } ]); @@ -637,7 +634,7 @@ session.web.Sidebar = session.web.Widget.extend({ }, add_section: function(name, code) { - if(!code) code = _.underscored(name); + if(!code) code = _.str.underscored(name); var $section = this.sections[code]; if(!$section) { @@ -665,7 +662,7 @@ session.web.Sidebar = session.web.Widget.extend({ // var self = this, - $section = this.add_section(_.titleize(section_code.replace('_', ' ')), section_code), + $section = this.add_section(_.str.titleize(section_code.replace('_', ' ')), section_code), section_id = $section.attr('id'); if (items) { @@ -682,34 +679,11 @@ session.web.Sidebar = session.web.Widget.extend({ item.callback.apply(self, [item]); } if (item.action) { - var ids = self.widget_parent.get_selected_ids(); - if (ids.length == 0) { - //TODO: make prettier warning? - $("
    ").text(_t("You must choose at least one record.")).dialog({ - title: _t("Warning"), - modal: true - }); - return false; - } - var additional_context = { - active_id: ids[0], - active_ids: ids, - active_model: self.widget_parent.dataset.model - }; - self.rpc("/web/action/load", { - action_id: item.action.id, - context: additional_context - }, function(result) { - result.result.context = _.extend(result.result.context || {}, - additional_context); - result.result.flags = result.result.flags || {}; - result.result.flags.new_window = true; - self.do_action(result.result); - }); + self.on_item_action_clicked(item); } return false; }); - + var $ul = $section.find('ul'); if(!$ul.length) { $ul = $('
      ').appendTo($section); @@ -717,6 +691,35 @@ session.web.Sidebar = session.web.Widget.extend({ $items.appendTo($ul); } }, + on_item_action_clicked: function(item) { + var self = this; + self.widget_parent.sidebar_context().then(function (context) { + var ids = self.widget_parent.get_selected_ids(); + if (ids.length == 0) { + //TODO: make prettier warning? + $("
      ").text(_t("You must choose at least one record.")).dialog({ + title: _t("Warning"), + modal: true + }); + return false; + } + var additional_context = _.extend({ + active_id: ids[0], + active_ids: ids, + active_model: self.widget_parent.dataset.model + }, context); + self.rpc("/web/action/load", { + action_id: item.action.id, + context: additional_context + }, function(result) { + result.result.context = _.extend(result.result.context || {}, + additional_context); + result.result.flags = result.result.flags || {}; + result.result.flags.new_window = true; + self.do_action(result.result); + }); + }); + }, do_fold: function() { this.$element.addClass('closed-sidebar').removeClass('open-sidebar'); }, @@ -881,7 +884,7 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ } }; var context = new session.web.CompoundContext(dataset.get_context(), action_data.context || {}); - + var handler = function (r) { var action = r.result; if (action && action.constructor == Object) { @@ -972,6 +975,9 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ }); }, on_sidebar_view_log: function() { + }, + sidebar_context: function () { + return $.Deferred().resolve({}).promise(); } }); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 9783f4ae959..fce34e6ce9a 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -18,7 +18,7 @@
      -
      +
      @@ -63,7 +63,9 @@
      +
      Loading... +
        @@ -358,6 +360,10 @@
      • +
      • + + +
      LOGOUT @@ -623,22 +629,14 @@ - - - - - - - - - - - - + + + @@ -711,7 +709,7 @@ Unhandled widget - + console.warn('Unhandled widget', dict.widget); @@ -729,6 +727,17 @@
      + + +
      + + +
      +
      + + + +
      • @@ -741,6 +750,19 @@ + + +
        + Notebook Page "" +
        +
          +
        • + Modifiers: + +
        • +
        +
        +
        @@ -753,13 +775,72 @@ + +
        + (nolabel) +
        +

        + +

        +
          +
        • + Field: + +
        • +
        • + Object: + +
        • +
        • + Type: + +
        • +
        • + Widget: + +
        • +
        • + Size: + +
        • +
        • + Context: + +
        • +
        • + Domain: + +
        • +
        • + Modifiers: + +
        • +
        • + On change: + +
        • +
        • + Relation: + +
        • +
        • + Selection: +
            +
          • + [] + - + +
          • +
          +
        • +
        +

        @@ -767,7 +848,7 @@ @@ -775,7 +856,7 @@
        @@ -821,13 +902,13 @@
        - + - @@ -995,13 +1076,42 @@ - + + +
        + + Button + : + (no string) + + +
        +
        + +
      • + Special: + +
      • + +
      • + Button Type: + +
      • +
      • + Method: + +
      • +
      • + Action ID: + +
      • +
        +
        @@ -1048,8 +1158,8 @@ t-att-title="attrs.help" t-att-class="classes.join(' ')" t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined"> - -
        + +
        Save + + + + + + + + + $(document.createElement('t')) @@ -1277,51 +1399,70 @@ - - - - - - - -
        - - - -
        - - - - - - - - - - -
        - - - - - - - - - -
        - - - - - - - + + + + + + + + +
        + + + + + +
        + + + + + + + + + + +
        + + + + + + + + + +
        + + + + + + + + + + + + + + + + Export @@ -1569,4 +1710,4 @@
        - + \ No newline at end of file diff --git a/addons/web/static/test/formats.js b/addons/web/static/test/formats.js index 8fc5abed42e..d530571583c 100644 --- a/addons/web/static/test/formats.js +++ b/addons/web/static/test/formats.js @@ -11,17 +11,17 @@ $(document).ready(function () { test("format_datetime", function () { var date = openerp.web.str_to_datetime("2009-05-04 12:34:23"); var str = openerp.web.format_value(date, {type:"datetime"}); - equal(str, date.toString("M/d/yyyy h:mm:ss tt")); + equal(str, date.toString("MM/dd/yyyy HH:mm:ss")); }); test("format_date", function () { var date = openerp.web.str_to_datetime("2009-05-04 12:34:23"); var str = openerp.web.format_value(date, {type:"date"}); - equal(str, date.toString("M/d/yyyy")); + equal(str, date.toString("MM/dd/yyyy")); }); test("format_time", function () { var date = openerp.web.str_to_datetime("2009-05-04 12:34:23"); var str = openerp.web.format_value(date, {type:"time"}); - equal(str, date.toString("h:mm:ss tt")); + equal(str, date.toString("HH:mm:ss")); }); test("format_float", function () { var fl = 12.1234; @@ -41,22 +41,28 @@ $(document).ready(function () { '1.00'); equal(openerp.web.format_value(-11.25, {type: 'float'}), "-11.25"); + openerp.web._t.database.parameters.grouping = [1, 2, -1]; + equal(openerp.web.format_value(1111111.25, {type: 'float'}), + "1111,11,1.25"); + openerp.web._t.database.parameters.grouping = [1, 0]; + equal(openerp.web.format_value(-11.25, {type: 'float'}), + "-1,1.25"); }); - test("parse_datetime", function () { - var val = openerp.web.str_to_datetime("2009-05-04 12:34:23"); - var res = openerp.web.parse_value(val.toString("M/d/yyyy h:mm:ss tt"), {type:"datetime"}); - equal(val.toString("M/d/yyyy h:mm:ss tt"), res.toString("M/d/yyyy h:mm:ss tt")); - }); - test("parse_date", function () { - var val = openerp.web.str_to_date("2009-05-04"); - var res = openerp.web.parse_value(val.toString("M/d/yyyy"), {type:"date"}); - equal(val.toString("M/d/yyyy"), res.toString("M/d/yyyy")); - }); - test("parse_time", function () { - var val = openerp.web.str_to_time("12:34:23"); - var res = openerp.web.parse_value(val.toString("h:mm:ss tt"), {type:"time"}); - equal(val.toString("h:mm:ss tt"), res.toString("h:mm:ss tt")); - }); +// test("parse_datetime", function () { +// var val = openerp.web.str_to_datetime("2009-05-04 12:34:23"); +// var res = openerp.web.parse_value(val.toString("MM/dd/yyyy HH:mm:ss"), {type:"datetime"}); +// equal(val.toString("MM/dd/yyyy HH:mm:ss"), res.toString("MM/dd/yyyy HH:mm:ss")); +// }); +// test("parse_date", function () { +// var val = openerp.web.str_to_date("2009-05-04"); +// var res = openerp.web.parse_value(val.toString("MM/dd/yyyy"), {type:"date"}); +// equal(val.toString("MM/dd/yyyy"), res.toString("MM/dd/yyyy")); +// }); +// test("parse_time", function () { +// var val = openerp.web.str_to_time("12:34:23"); +// var res = openerp.web.parse_value(val.toString("HH:mm:ss"), {type:"time"}); +// equal(val.toString("HH:mm:ss"), res.toString("HH:mm:ss")); +// }); test("parse_float", function () { var str = "134,112.1234"; var val = openerp.web.parse_value(str, {type:"float"}); @@ -65,4 +71,45 @@ $(document).ready(function () { var val = openerp.web.parse_value(str, {type:"float"}); equal(val, -134112.1234); }); + test('intersperse', function () { + var g = openerp.web.intersperse; + equal(g("", []), ""); + equal(g("0", []), "0"); + equal(g("012", []), "012"); + equal(g("1", []), "1"); + equal(g("12", []), "12"); + equal(g("123", []), "123"); + equal(g("1234", []), "1234"); + equal(g("123456789", []), "123456789"); + equal(g("&ab%#@1", []), "&ab%#@1"); + + equal(g("0", []), "0"); + equal(g("0", [1]), "0"); + equal(g("0", [2]), "0"); + equal(g("0", [200]), "0"); + + equal(g("12345678", [0], '.'), '12345678'); + equal(g("", [1], '.'), ''); + equal(g("12345678", [1], '.'), '1234567.8'); + equal(g("12345678", [1], '.'), '1234567.8'); + equal(g("12345678", [2], '.'), '123456.78'); + equal(g("12345678", [2, 1], '.'), '12345.6.78'); + equal(g("12345678", [2, 0], '.'), '12.34.56.78'); + equal(g("12345678", [-1, 2], '.'), '12345678'); + equal(g("12345678", [2, -1], '.'), '123456.78'); + equal(g("12345678", [2, 0, 1], '.'), '12.34.56.78'); + equal(g("12345678", [2, 0, 0], '.'), '12.34.56.78'); + equal(g("12345678", [2, 0, -1], '.'), '12.34.56.78'); + }); + test('format_integer', function () { + openerp.web._t.database.parameters.grouping = [3, 3, 3, 3]; + equal(openerp.web.format_value(1000000, {type: 'integer'}), + '1,000,000'); + openerp.web._t.database.parameters.grouping = [3, 2, -1]; + equal(openerp.web.format_value(106500, {type: 'integer'}), + '1,06,500'); + openerp.web._t.database.parameters.grouping = [1, 2, -1]; + equal(openerp.web.format_value(106500, {type: 'integer'}), + '106,50,0'); + }); }); diff --git a/addons/web/static/test/onchange.js b/addons/web/static/test/onchange.js new file mode 100644 index 00000000000..8074c755bd3 --- /dev/null +++ b/addons/web/static/test/onchange.js @@ -0,0 +1,74 @@ +$(document).ready(function () { + var openerp, + make_form = function (default_values) { + var fields = {}; + _(default_values).each(function (value, name) { + fields[name] = value instanceof Function ? value : { + get_on_change_value: function () { return value; } + }; + }); + return _.extend(new openerp.web.FormView(null, {}), + {fields: fields}); + }; + module("form.onchange", { + setup: function () { + openerp = window.openerp.init(true); + window.openerp.web.core(openerp); + window.openerp.web.chrome(openerp); + // views loader stuff + window.openerp.web.data(openerp); + window.openerp.web.views(openerp); + window.openerp.web.list(openerp); + window.openerp.web.form(openerp); + } + }); + test('Parse args-less onchange', function () { + var f = new openerp.web.FormView(null, {}); + var result = f.parse_on_change('on_change_foo()', {}); + equal(result.method, 'on_change_foo'); + deepEqual(result.args, []); + }); + test('Parse 1-arg onchange', function () { + var f = make_form({foo: 3}); + var result = f.parse_on_change('on_change_foo(foo)', {}); + equal(result.method, 'on_change_foo'); + deepEqual(result.args, [3]); + }); + test('Parse 2-args onchange', function () { + var f = make_form({foo: 3, bar: 'qux'}); + var result = f.parse_on_change('on_change_foo(bar, foo)', {}); + equal(result.method, 'on_change_foo'); + deepEqual(result.args, ['qux', 3]); + }); + test('Literal null', function () { + var f = make_form(); + var result = f.parse_on_change('on_null(None)', {}); + deepEqual(result.args, [null]); + }); + test('Literal true', function () { + var f = make_form(); + var result = f.parse_on_change('on_null(True)', {}); + deepEqual(result.args, [true]); + }); + test('Literal false', function () { + var f = make_form(); + var result = f.parse_on_change('on_null(False)', {}); + deepEqual(result.args, [false]); + }); + test('Literal string', function () { + var f = make_form(); + var result = f.parse_on_change('on_str("foo")', {}); + deepEqual(result.args, ['foo']); + var result2 = f.parse_on_change("on_str('foo')", {}); + deepEqual(result2.args, ['foo']); + }); + test('Literal number', function () { + var f = make_form(); + var result = f.parse_on_change('on_str(42)', {}); + deepEqual(result.args, [42]); + var result2 = f.parse_on_change("on_str(-25)", {}); + deepEqual(result2.args, [-25]); + var result3 = f.parse_on_change("on_str(25.02)", {}); + deepEqual(result3.args, [25.02]); + }); +}); diff --git a/addons/web/static/test/test.html b/addons/web/static/test/test.html index f6248e705c0..9bbfff168fd 100644 --- a/addons/web/static/test/test.html +++ b/addons/web/static/test/test.html @@ -23,6 +23,8 @@ + + @@ -47,4 +49,5 @@ + diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index 5b09e70cba8..fcdbd3746c7 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -8,8 +8,9 @@ 'static/lib/dhtmlxScheduler/codebase/ext/dhtmlxscheduler_minical.js', 'static/src/js/calendar.js' ], - "css": ['static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css', - 'static/lib/dhtmlxScheduler/codebase/ext/dhtmlxscheduler_ext.css' + "css": [ + 'static/lib/dhtmlxScheduler/codebase/ext/dhtmlxscheduler_ext.css', + 'static/src/css/web_calendar.css' ], 'qweb' : [ "static/src/xml/*.xml", diff --git a/addons/web_calendar/po/ar.po b/addons/web_calendar/po/ar.po index 33e04220c2c..4263e2bde16 100644 --- a/addons/web_calendar/po/ar.po +++ b/addons/web_calendar/po/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-04 05:32+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/da.po b/addons/web_calendar/po/da.po index 68e2b21a673..038a7c3cd08 100644 --- a/addons/web_calendar/po/da.po +++ b/addons/web_calendar/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/de.po b/addons/web_calendar/po/de.po index 27e0168a44e..ed614c661b6 100644 --- a/addons/web_calendar/po/de.po +++ b/addons/web_calendar/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/es.po b/addons/web_calendar/po/es.po index 9e0c5f32f98..07af7e0926d 100644 --- a/addons/web_calendar/po/es.po +++ b/addons/web_calendar/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/es_EC.po b/addons/web_calendar/po/es_EC.po index 6b9cf2145dd..43df5a70a01 100644 --- a/addons/web_calendar/po/es_EC.po +++ b/addons/web_calendar/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/et.po b/addons/web_calendar/po/et.po index b08c52fbfc7..42d69283eb7 100644 --- a/addons/web_calendar/po/et.po +++ b/addons/web_calendar/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/fr.po b/addons/web_calendar/po/fr.po index 5f04d2d7182..92c6328e59a 100644 --- a/addons/web_calendar/po/fr.po +++ b/addons/web_calendar/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/gl.po b/addons/web_calendar/po/gl.po index 7705a7cda2f..fc6d0982a9f 100644 --- a/addons/web_calendar/po/gl.po +++ b/addons/web_calendar/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/it.po b/addons/web_calendar/po/it.po index 5b98572ab45..b99ba98bc47 100644 --- a/addons/web_calendar/po/it.po +++ b/addons/web_calendar/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/nl_BE.po b/addons/web_calendar/po/nl_BE.po index b071632ea47..158e6d03eca 100644 --- a/addons/web_calendar/po/nl_BE.po +++ b/addons/web_calendar/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/pt.po b/addons/web_calendar/po/pt.po new file mode 100644 index 00000000000..a2ba6e02a2a --- /dev/null +++ b/addons/web_calendar/po/pt.po @@ -0,0 +1,22 @@ +# Portuguese translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-21 21:57+0000\n" +"Last-Translator: Daniel Reis \n" +"Language-Team: Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-11-22 05:13+0000\n" +"X-Generator: Launchpad (build 14299)\n" + +#: addons/web_calendar/static/src/xml/web_calendar.xml:0 +msgid " " +msgstr " " diff --git a/addons/web_calendar/po/sk.po b/addons/web_calendar/po/sk.po index f879c6b13f1..2beb26d4e0e 100644 --- a/addons/web_calendar/po/sk.po +++ b/addons/web_calendar/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/sl.po b/addons/web_calendar/po/sl.po index 80c32b8728b..0f4b85d1fba 100644 --- a/addons/web_calendar/po/sl.po +++ b/addons/web_calendar/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/static/src/css/web_calendar.css b/addons/web_calendar/static/src/css/web_calendar.css new file mode 100644 index 00000000000..cdad3ae794f --- /dev/null +++ b/addons/web_calendar/static/src/css/web_calendar.css @@ -0,0 +1,1062 @@ +#openerp_scheduler { + background-color:white; +} +.openerp .dhx_mini_calendar { + -moz-box-shadow: none; + -khtml-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} +.openerp .dhx_cal_container, .openerp .dhx_cal_event { + background-position:0 24px; + background-repeat:repeat-x; + font-family: Ubuntu, Helvetica, sans-serif; + position:relative; + overflow:hidden; +} +.openerp .dhx_cal_container.dhx_mini_calendar { + background-color:#eee; +} +.openerp .dhx_cal_container div{ + -moz-user-select:none; + -moz-user-select:-moz-none; +} + +.openerp .dhx_cal_navline{ + height:20px; position:absolute;z-index:3;width:750px;color:#2F3A48; +} +.openerp .dhx_cal_navline div{ + top:2px; + white-space:nowrap; +} + +.openerp .dhx_cal_navline .dhx_cal_date{ + font-weight:bold; + float:left; + font-size:1em; + margin:2px 0px 0px 10px; +} + +.openerp .dhx_cal_button .dhx_left_bg{width:1px;overflow:hidden;height:17px;z-index:20;top:0;} + +.openerp .dhx_cal_today_button, .openerp .dhx_cal_prev_button, .openerp .dhx_cal_next_button { + color:white; + height:17px; + line-height:17px; + font-weight:bold; + cursor:pointer; + font-size:90%; + text-decoration:none; + float:left; + margin:0px 3px; + padding:2px 2px; + border:1px solid black; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + vertical-align:0px; +} + +.openerp .dhx_cal_today_button { + background: #ccc; /* Old browsers */ + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c9c9c9', endColorstr='#999999'); /* IE6-9 */ + background: -webkit-gradient(linear, left top, left bottom, from(#c9c9c9), to(#999999)); /* Chrome,Safari4+ */ + background: -moz-linear-gradient(top, #c9c9c9, #999999); /* FF3.6+ */ + background: -webkit-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* IE10+ */ + background: linear-gradient(top, #c9c9c9 0%,#999999 60%); /* W3C */ + padding-left:5px; + padding-right:5px; +} + +.openerp .dhx_cal_prev_button{ + background: #bbb; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c9c9c9', endColorstr='#999999'); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -webkit-gradient(linear, left top, left bottom, from(#c9c9c9), to(#999999)); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -moz-linear-gradient(top, #c9c9c9, #999999); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -webkit-linear-gradient(top, #c9c9c9 0%,#999999 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -o-linear-gradient(top, #c9c9c9 0%,#999999 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -ms-linear-gradient(top, #c9c9c9 0%,#999999 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, linear-gradient(top, #c9c9c9 0%,#999999 60%); + background-repeat:no-repeat; + width:20px; +} + +.openerp .dhx_cal_next_button { + background: #ccc; /* Old browsers */ + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#888', endColorstr='#888'); /* IE6-9 */ + background: url("/web_calendar/src/img/cal_right.png") 5px 3px, -webkit-gradient(linear, left top, left bottom, from(#c9c9c9), to(#999999)); /* Chrome,Safari4+ */ + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -moz-linear-gradient(top, #c9c9c9, #999999); /* FF3.6+ */ + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -webkit-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* Chrome10+,Safari5.1+ */ + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -o-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* Opera11.10+ */ + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -ms-linear-gradient(top, #c9c9c9 0%,#999999 60%); /* IE10+ */ + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, linear-gradient(top, #c9c9c9 0%,#999999 60%); /* W3C */ + background-repeat:no-repeat; + width:20px; +} + +.openerp .dhx_cal_prev_button:hover, .openerp .dhx_cal_prev_button:active { + background: #bbb; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#888', endColorstr='#888'); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -webkit-gradient(linear, left top, left bottom, from(#888), to(#888)); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -moz-linear-gradient(top, #888, #888); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -webkit-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -o-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, -ms-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_left.png") 5px 3px, linear-gradient(top, #888 0%,#888 60%); + background-repeat:no-repeat; +} + +.openerp .dhx_cal_next_button:hover, .openerp .dhx_cal_next_button:active { + background: #bbb; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#888', endColorstr='#888'); + background:-webkit-gradient(linear, left top, left bottom, from(#888), to(#888)); + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -moz-linear-gradient(top, #888, #888); + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -webkit-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -o-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, -ms-linear-gradient(top, #888 0%,#888 60%); + background: url("/web_calendar/static/src/img/cal_right.png") 5px 3px, linear-gradient(top, #888 0%,#888 60%); + background-repeat:no-repeat; +} + +.openerp .dhx_cal_today_button:hover, .openerp .dhx_cal_today_button:active { + background: #bbb; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#bbb', endColorstr='#bbb'); + background: -webkit-gradient(linear, left top, left bottom, from(#888), to(#888)); + background: -moz-linear-gradient(top, #888, #888); + background: -webkit-linear-gradient(top, #888 0%,#888 60%); + background: -o-linear-gradient(top, #888 0%,#888 60%); + background: -ms-linear-gradient(top, #888 0%,#888 60%); + background: linear-gradient(top, #888 0%,#888 60%); + background-repeat:no-repeat; +} + +.openerp .dhx_mini_calendar .dhx_cal_prev_button, .openerp .dhx_mini_calendar .dhx_cal_next_button, .openerp .dhx_mini_calendar .dhx_cal_today_button { + background:none; + border:0px; +} +.openerp .dhx_mini_calendar .dhx_cal_prev_button, .openerp .dhx_mini_calendar .dhx_cal_next_button { + width:16px; + height:18px; +} +.openerp .dhx_mini_calendar .dhx_cal_prev_button { + background:url("/web_calendar/static/src/img/minical_left.png") no-repeat 5px 6px; +} + +.openerp .dhx_mini_calendar .dhx_cal_next_button { + background:url("/web_calendar/static/src/img/minical_right.png") no-repeat 8px 6px; +} + +.openerp .dhx_mini_calendar .dhx_month_head { + font-size:0.9em; + color:#888 +} +.openerp .dhx_mini_calendar .dhx_month_head:hover { + background-color:#bbb; + color:white; + text-shadow:none; +} +.openerp .dhx_mini_calendar .dhx_scale_bar { + border-width:0px; + padding:2px 0px; +} + +.openerp .dhx_cal_tab { + width:59px; + height:16px; + line-height:16px; + text-align:center; + text-transform:uppercase; + text-decoration:none; + font-weight:bold; + font-size:80%; + color:#555; + margin:6px 1px 0px 1px; + padding-top:2px; + cursor:pointer; + float:right; + background-color:#bbb; + -webkit-border-top-left-radius:4px; + -webkit-border-top-right-radius:4px; + -moz-border-radius-topleft:4px; + -moz-border-radius-topright:4px; + border-top-left-radius:4px; + border-top-right-radius:4px; +} +.openerp .dhx_cal_tab[name="month_tab"] { right:16px; } +.openerp .dhx_cal_tab[name="week_tab"] { right:78px; } +.openerp .dhx_cal_tab[name="day_tab"] { right:123px; } + +.openerp .dhx_cal_tab:hover { + background-color:#ddd; +} + +.openerp .dhx_cal_tab.active{ + height:17px; + line-height:17px; + text-decoration:none; + cursor:default; + border:1px dotted #8894A3; + border-bottom:0px; + background-color:white /*#F4F4F4;*/ +} + +.openerp .dhx_cal_tab[name="day_tab"] { + margin-right:18px; +} + +.openerp .dhx_cal_header{ + position:absolute; + left:10px; + top:23px; + width:750px; + text-transform:uppercase; + font-size:0.8em; + font-weight:bold; + color:#3F3F3F; + border-bottom:1px dotted #8894A3; + border-top:1px dotted #8894A3; + /*border-right:1px dotted #8894A3;z-index:2;*/ + overflow:hidden; + background-color: white; /*#F4F4F4;*/ + text-shadow: 0 1px 0 white; +} + +.openerp .dhx_cal_data{ + position:absolute; + top:44px; + width:600px; + overflow-y:auto; + overflow-x:hidden; +} + +.openerp .dhx_cal_data tr td { + border-width:0px; +} + +.openerp .dhx_scale_bar{ + position:absolute; + text-align:center; + text-shadow: 0 1px 0 white; + background-color:#C2D5FC; + padding-top:3px; + border-left:1px dotted #586A7E; +} + +.openerp .dhx_scale_holder{ + position:absolute; + border-right:1px solid #ccc; + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png"); +} +.openerp .dhx_scale_holder_now{ + position:absolute; + border-right:1px solid #ccc; + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg_now.png"); +} + +.openerp .dhx_scale_hour{ + height:41px; + width:50px; + border-bottom:1px dotted #8894A3; + border-right:1px dotted #8894A3; + background-color:#ddd; + text-align:center; + line-height:40px; + color:#586A7E; + overflow:hidden; +} + +.openerp .dhx_month_head{ + background-color:#F4F4F4; + color:#2F3A48; + text-shadow: 0 1px 0 white; + font-weight:bold; + text-align:center; + border-left:1px solid #E9E9E9; + height:18px; + padding-right:4px; + padding-top:4px; + text-align:right; + font-size:0.9em; +} +.openerp .dhx_mini_calendar .dhx_month_head{ + padding-right:6px; +} + +.openerp .dhx_cal_data table tbody tr td:nth-child(7) { + color:red; +} + + +.openerp .dhx_now .openerp .dhx_month_body{ + background-color:#cccccc; +} + +.openerp .dhx_after .dhx_month_body,.openerp .dhx_before .dhx_month_body{background-color:#ECECEC;} + +.openerp .dhx_after .dhx_month_head,.openerp .dhx_before .dhx_month_head{background-color:#F4F4F4;color:#94A6BB;} + +.openerp .dhx_now .dhx_month_head{ + background-color:#ddd; +} + +.openerp .dhx_cal_drag{position:absolute;z-index:9999;background-color:#FFE763;border:1px solid #B7A543;opacity:.5;filter:alpha(opacity=50);} + +.openerp .dhx_loading{position:absolute;width:128px;height:15px;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/loading.gif);z-index:9999;} + +.openerp .dhx_multi_day_icon, .openerp .dhx_multi_day{ + background-color:#ddd; + background-repeat:no-repeat; + /*border-right:1px dotted #8894A3;*/ +} +.openerp .dhx_multi_day{ + position:absolute; +/*border-top:1px dotted #8894A3;*/ +} + +.openerp .dhx_multi_day_icon{ + background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_big.gif); +} + +.openerp .dhx_multi_day_icon_small { + background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_small.gif); +} + +.openerp .dhx_multi_day_icon, .openerp .dhx_multi_day_icon_small{ + background-position:center center; + background-repeat:no-repeat; + border:1px dotted #8894A3; + border-left:0px; +} + +.openerp .dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container{background-color:none;} + +.openerp .dhx_cal_event div{ + font-family: Ubuntu, Helvetica, sans-serif; + background-color:#FFE763; + border:1px solid #a73636; + color:#887A2E; + overflow:hidden; + font-size:100%; +} + +.openerp .dhx_move_denied .dhx_cal_event .dhx_header, .openerp .dhx_move_denied .dhx_cal_event .dhx_title{cursor:default;} + +.openerp .dhx_cal_event .dhx_header{ + height:0px; + margin-left:1px; + /*border-width:1px 1px 0 1px;*/ + cursor:pointer; +} + +.openerp .dhx_cal_event .dhx_title{ + height:18px; + border-bottom-style:solid; + border-top-style:solid; + font-weight:bold; + text-align:center; + background-position:right; + background-repeat:no-repeat; + cursor:pointer; + vertical-align:middle; + padding-top:2px; + font-size: 90%; + -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; +} + +.openerp .dhx_cal_event .dhx_body{ + border-width:0 1px 1px 1px; + padding:0px 5px; + -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; + font-size:90%; + line-height:9px; +} + +.openerp .dhx_resize_denied .dhx_cal_event .dhx_footer{ + cursor:default; +} + +.openerp .dhx_cal_event .dhx_footer{ + height:2px; + margin-left:2px; + border-width:0 1px 1px 1px; + cursor:s-resize; + overflow:auto; +} + +/* +The old one + +.openerp .dhx_cal_event_line{ + background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/event-bg.png); + background-color:#FFE763; + border:1px solid #FFBD51; + border-radius:3px; + height:13px; + padding-left:10px; + color:#000; + cursor:pointer; + overflow:hidden; +}*/ + +.openerp .dhx_cal_event_clear, .openerp .dhx_cal_event_line{ + font-family:Ubuntu, Helvetica, sans-serif; + font-size:95%; + height:15px; + line-height:15px; + padding:0px 2px; + color:white; + white-space:nowrap; + overflow:hidden; + cursor:pointer; + vertical-align:middle; +} +.openerp .dhx_cal_event_clear:hover, .openerp .dhx_cal_event_line:hover{ + background-color:#ccc; +} + +.openerp .dhx_in_move{background-color:#FFFF80;} + +.openerp div .dhx_cal_editor{ + background-color:white; + border:1px solid #B7A543; + width:100%; + /*min-height:40px;*/ + height:100%; + z-index:999; + position:absolute; + overflow:hidden; +} + +.openerp textarea .dhx_cal_editor{ + background-color:white; + width:100%; +/*min-height:40px;*/ + height:100%; + border:0 solid black; + margin:none; + padding:none; + overflow:auto; +} + +.openerp div .dhx_menu_head{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif);background-position:0 -43px;width:10px;height:10px;margin-left:5px;margin-top:1px;border:none;cursor:default;} + +.openerp div .dhx_menu_icon{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif);width:20px;height:20px;margin-left:-5px;margin-top:0;border:none;cursor:pointer;} +.openerp div .icon_details{background-position:0 0;} + +.openerp div .icon_edit{background-position:-22px 0;} +.openerp div .icon_save{background-position:-84px -1px;} +.openerp div .icon_cancel{background-position:-62px 0;}div.icon_delete{background-position:-42px 0;} +.openerp div .dhx_now_time{position:absolute;width:100%;border-bottom:2px dotted red;z-index:1;} +.openerp div .dhx_time_block{position:absolute;width:100%;background:silver;opacity:.4;filter:alpha(opacity=40);z-index:1;} + +.openerp .dhx_unselectable, .dhx_unselectable div{-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none;} + +.openerp .dhx_cal_light{background-color:#FFE763;border-radius:5px; + font-size:8pt;border:1px solid #B7A64B;color:#887A2E;position:absolute;z-index:10001;width:580px;height:300px;box-shadow:5px 5px 5px #888;} + +.openerp .dhx_cal_light_wide{width:650px;} +.openerp .dhx_mark{position:relative;top:3px;background-image:url('/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif');background-position:0 -43px;padding-left:10px;} + +.openerp .dhx_ie6 .dhx_mark{background-position:6px -41px;} + +.openerp .dhx_cal_light select{font-size:8pt;color:#887A2E;padding:2px;margin:0;}.openerp .dhx_cal_ltitle{padding:2px 0 2px 5px;overflow:hidden;white-space:nowrap;} + +.openerp .dhx_cal_ltitle span{white-space:nowrap;} + +.openerp .dhx_cal_lsection{background-color:#DBCF8C;color:#FFF4B5;font-weight:bold;padding:5px 0 3px 10px;}.openerp .dhx_section_time{background-color:#DBCF8C;} + +.openerp .dhx_cal_lsection .dhx_fullday{float:right;margin-right:5px;color:#887A2E;font-size:12px;font-weight:normal;line-height:20px;vertical-align:top;cursor:pointer;} + +.openerp .dhx_cal_lsection{font-size:18px;} + +.openerp .dhx_cal_ltext{padding:2px 0 2px 10px;overflow:hidden;} +.openerp .dhx_cal_ltext textarea{background-color:#FFF4B5;overflow:auto;border:none;color:#887A2E;height:100%;width:100%;outline:none!important;} +.openerp .dhx_time{font-weight:bold;} + +.openerp .dhx_cal_light .openerp .dhx_title{padding-left:10px;} + +.openerp .dhx_cal_larea{border:1px solid #DCC43E;background-color:#FFF4B5;overflow:hidden;margin-left:3px;width:572px;height:1px;} +.openerp .dhx_btn_set{padding:5px 10px 0 10px;float:left;}.openerp .dhx_btn_set div{float:left;height:21px;line-height:21px;vertical-align:middle;cursor:pointer;} +.openerp .dhx_save_btn{background-image:url('/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif');background-position:-84px 0;width:21px;} +.openerp .dhx_cancel_btn{background-image:url('/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif');background-position:-63px 0;width:20px;} +.openerp .dhx_delete_btn{background-image:url('/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif');background-position:-42px 0;width:20px;} +.openerp .dhx_cal_cover{width:100%;height:100%;position:absolute;z-index:10000;top:0;left:0;background-color:black;opacity:.1;filter:alpha(opacity=10);} +.openerp .dhx_custom_button{padding:0 3px 0 3px;color:#887A2E;font-size:8pt;background-color:#FFE763;font-weight:normal;margin-right:5px;margin-top:0;cursor:pointer;} +.openerp .dhx_custom_button div{cursor:pointer;float:left;height:21px;line-height:21px;vertical-align:middle;} + +.openerp .dhx_cal_light_wide .dhx_cal_larea{border-top-width:0;} +.openerp .dhx_cal_light_wide .dhx_cal_lsection{border:0;float:left;text-align:right;width:100px;height:20px;font-size:16px;padding:5px 0 0 10px;} +.openerp .dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #DBCF8C;position:relative;background-color:#DBCF8C;overflow:hidden;} +.openerp .dhx_cal_light_wide .dhx_section_time{padding-top:2px!important;height:20px!important;} +.openerp .dhx_section_time{text-align:center;} +.openerp .dhx_cal_light_wide .dhx_cal_larea{width:730px;} +.openerp .dhx_cal_light_wide{width:738px;} +.openerp .dhx_cal_light_wide .dhx_section_time{background:transparent;} +.openerp .dhx_cal_light_wide .dhx_cal_checkbox label{padding-left:0;} +.openerp .dhx_cal_wide_checkbox input{margin-top:8px;margin-left:14px;} +.openerp .dhx_cal_light input{;font-size:8pt;color:#887A2E;} + +.openerp .dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{float:none;margin-right:0;color:#FFF4B5;font-weight:bold;font-size:16px;cursor:pointer;} + +.openerp .dhx_custom_button{float:right;height:21px;width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;} +.openerp .dhx_cal_light_wide .dhx_custom_button{position:absolute;top:0;right:0;margin-top:2px;} +.openerp .dhx_cal_light_wide .dhx_repeat_right{margin-right:55px;} +.openerp .dhx_cal_light_wide .dhx_repeat_divider{border-color:#FFE763;} + +.openerp .dhx_scale_bar_header{position:absolute;border-bottom:1px dotted #8894A3;width:100%;} + +.openerp .dhx_expand_icon{position:absolute;top:0;right:0;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/colapce-expand-icon.gif);width:18px;height:18px;cursor:pointer;background-position:0 18px;z-index:16;} +.openerp .dhx_agenda_area{width:100%;height:100%;overflow-y:auto;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png);} +.openerp .dhx_agenda_line{height:21px;clear:both;overflow:hidden;} +.openerp .dhx_agenda_line div{float:left;width:188px;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;} +.openerp .dhx_agenda_area .dhx_agenda_line div{border-right:0 dotted #8894A3;} +.openerp .dhx_v_border{position:absolute;left:186px;top:0;border-right:1px dotted #8894A3;width:1px;height:100%;} +.openerp .dhx_agenda_line .dhx_event_icon{width:20px;border-width:0;background:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;} +.openerp .dhx_agenda_line span{padding-left:5px;line-height:21px;} + + +.openerp .dhx_year_week{ + position:relative; + font-weight:bold; + font-size:1em; + color:#aaa; + vertical-align:middle; + border-top:1px solid #ccc; + border-bottom:1px solid #ccc; +} + +.openerp .dhx_scale_bar_last{border-right:1px dotted #586A7E;} + +.openerp .dhx_year_month{ + height:18px; + line-height:18px; + padding-top:2px; + text-align:center; + vertical-align:middle; + text-transform:uppercase; + font-weight:bold; + font-size:0.9em; + text-shadow: 0 1px 0 white; + border:0px; + color:#444; +} +/*.openerp .dhx_mini_calendar .openerp .dhx_year_month{ + padding-top:0px; +} */ + +.openerp .dhx_mini_calendar + .dhx_year_body { + border:0px; +} + +.openerp .dhx_year_body .dhx_before .dhx_month_head,.openerp .dhx_year_body .dhx_after .dhx_month_head, .openerp .dhx_year_body .dhx_before .dhx_month_head a,.openerp .dhx_year_body .dhx_after .dhx_month_head a {color:#bbb;} + +.openerp .dhx_year_body .dhx_month_body{height:0;overflow:hidden;} + +.openerp .dhx_year_body .dhx_before .dhx_month_head, .dhx_year_body .dhx_after .dhx_month_head{cursor:default;} + +.openerp .dhx_tooltip{border:1px solid #BBB;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png);position:absolute;z-index:9998;width:300px;height:auto; +font-size:8pt;overflow:hidden;} +.openerp .dhx_tooltip_line{line-height:20px;height:20px;overflow:hidden;} +.openerp .dhx_tooltip_line .dhx_event_icon{width:20px;height:20px;padding-right:10px;float:left;border-width:0;position:relative;background:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;} +.openerp .dhx_tooltip_date{float:left;width:auto;padding-left:5px;text-align:center;} + +.openerp .dhx_text_disabled{color:#887A2E;font-size:8pt;} + +.openerp .dhx_cal_navline div .dhx_minical_icon{width:18px;height:18px;left:190px;top:1px;cursor:pointer;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/calendar.gif);} + +.openerp .dhx_matrix_scell{height:100%;} +.openerp .dhx_matrix_cell, +.openerp .dhx_matrix_scell{overflow:hidden;text-align:center;vertical-align:middle;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;} +.openerp .dhx_matrix_cell{background-color:white;} +.openerp .dhx_matrix_line{overflow:hidden;} +.openerp .dhx_matrix_cell div, .openerp .dhx_matrix_scell div{overflow:hidden;text-align:center;height:auto;} +.openerp .dhx_cal_lsection .dhx_readonly{font-size:9pt;font-size:8pt;padding:2px;color:#887A2E;} + +.openerp .dhx_matrix_scell.folder,.openerp .dhx_data_table.folder .dhx_matrix_cell{background-color:#969394;cursor:pointer;} +.openerp .dhx_matrix_scell .dhx_scell_level0{padding-left:5px;} +.openerp .dhx_matrix_scell .dhx_scell_level1{padding-left:20px;} +.openerp .dhx_matrix_scell .dhx_scell_level2{padding-left:35px;} +.openerp .dhx_matrix_scell .dhx_scell_level3{padding-left:50px;} +.openerp .dhx_matrix_scell .dhx_scell_level4{padding-left:65px;} +.openerp .dhx_matrix_scell.folder{font-weight:bold;text-align:left;} +.openerp .dhx_matrix_scell.folder .dhx_scell_expand{float:left;width:10px;padding-right:3px;} +.openerp .dhx_matrix_scell.folder .dhx_scell_name{float:left;width:auto;} +.openerp .dhx_matrix_scell.item .dhx_scell_name{padding-left:15px;text-align:left;} + +.openerp .dhx_data_table.folder .dhx_matrix_cell{border-right:0;} +.openerp .dhx_section_timeline{overflow:hidden;padding:4px 0 2px 10px;} +.openerp .dhx_section_timeline select{width:552px;} +.openerp .dhx_map_area{width:100%;height:100%;overflow-y:auto;overflow-x:hidden;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png);} +.openerp .dhx_map_line .dhx_event_icon{width:20px;border-width:0;background:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;} +.openerp .dhx_map_line{height:21px;clear:both;overflow:hidden;} +.openerp .dhx_map{position:absolute;} +.openerp .dhx_map_line div{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;} +.openerp .dhx_map_line .headline_description{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;} +.openerp .dhx_map_line .dhx_map_description{float:left;border-right:0 dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;} + +.openerp .dhx_map_line .line_description{float:left;border-right:1px dotted #8894A3;text-align:left;padding-left:5px;line-height:21px;overflow:hidden;} +.openerp .dhx_map_line.highlight{background-color:#C4C5CC;} +.openerp .dhx_map_area .dhx_map_line div{border-right:0 dotted #8894A3;}.dhtmlXTooltip.tooltip{-moz-box-shadow:3px 3px 3px #888;-webkit-box-shadow:3px 3px 3px #888;-o-box-shadow:3px 3px 3px #888;box-shadow:3px 3px 3px #888;filter:progid:DXImageTransform.Microsoft.Shadow(color='#888888',Direction=135,Strength=5);background-color:white;border-left:1px dotted #887A2E;border-top:1px dotted #887A2E;color:#887A2E;cursor:default;padding:10px;position:absolute;z-index:500;} +.openerp .dhx_cal_checkbox label{padding-left:5px;} +.openerp .dhx_cal_light .radio{padding:2px 0 2px 10px;} +.openerp .dhx_cal_light .radio input,.openerp .dhx_cal_light .radio label{line-height:15px;} +.openerp .dhx_cal_light .radio input{vertical-align:middle;margin:0;padding:0;} +.openerp .dhx_cal_light .radio label{vertical-align:middle;padding-right:10px;} +.openerp .dhx_cal_light .combo{padding:4px;} +.openerp .dhx_wa_column{float:left;} +.openerp .dhx_wa_column_last .dhx_wa_day_cont{border-left:1px dotted #8894A3;} + +.openerp .dhx_wa_scale_bar{padding-left:10px;font-size:11px;border-top:1px dotted #8894A3;border-bottom:1px dotted #8894A3;} +.openerp .dhx_wa_day_data{background-color:#FCFEFC;overflow-y:auto;} +.openerp .dhx_wa_ev_body{border-bottom:1px dotted #789;font-size:12px;padding:5px 0 5px 7px;} + +.openerp .dhx_wa_dnd{position:absolute;padding-right:7px;color:#887AE2!important;background-color:#FFE763!important;border:1px solid #B7A543;} +.openerp .dhx_cal_event_selected{background-color:#9cc1db;color:white;} +.openerp .dhx_second_scale_bar{border-bottom:1px dotted #586A7E;padding-top:2px;} +.openerp div .dhx_form_repeat input.radio{margin:-4px 0 0 -4px!ie;} +.openerp div .dhx_form_repeat input.checkbox{margin:0 0 0 -4px!ie;} + +.openerp .dhx_form_repeat,.openerp .dhx_form_repeat input{padding:0;margin:0;padding-left:5px; +font-size:11px;line-height:24px;} +.openerp .dhx_form_repeat{overflow:hidden;height:0;background-color:#FFF4B5;} +.openerp .dhx_cal_light_wide .dhx_form_repeat{background-color:transparent;} +.openerp .dhx_repeat_center,.openerp .dhx_repeat_left{height:115px;padding:10px 0 10px 10px;float:left;} +.openerp .dhx_repeat_left{width:95px;} +.openerp .dhx_repeat_center{width:335px;margin-top:12px;} +.openerp .dhx_repeat_divider{float:left;height:115px;border-left:1px dotted #DCC43E;width:1px;} +.openerp .dhx_repeat_right{float:right;height:115px;width:160px;padding:10px 3px 10px 10px;margin-top:7px;} +.openerp input .dhx_repeat_text{height:16px;width:27px;margin:0 4px 0 4px;line-height:18px;padding:0 0 0 2px;} +.openerp .dhx_form_repeat select{height:20px;width:87px;padding:0 0 0 2px;margin:0 4px 0 4px;} +.openerp input .dhx_repeat_date{height:18px;width:80px;padding:0 0 0 2px;margin:0 4px 0 4px;background-repeat:no-repeat;background-position:64px 0;border:1px #7f9db9 solid;line-height:18px;}input.openerp .dhx_repeat_radio{margin-right:4px;} +.openerp input .dhx_repeat_checkbox{margin:4px 4px 0 0;} +.openerp .dhx_repeat_days td{padding-right:5px;} +.openerp .dhx_repeat_days label{font-size:10px;} +.openerp .dhx_custom_button{width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;} +.openerp .dhx_custom_button_recurring{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/but_repeat.gif);background-position:-5px 20px;width:20px;margin-right:10px;} +.openerp .dhx_cal_light_rec{width:640px;} +.openerp .dhx_cal_light_rec .dhx_cal_larea{width:632px;} +.openerp .dhx_cal_light_rec .dhx_cal_light_wide{width:816px;} +.openerp .dhx_cal_light_rec .dhx_cal_light_wide .dhx_cal_larea{width:808px;} + +.openerp .dhx_cal_navline{background-color:none;height:23px!important;} + + + + +.openerp .dhx_scale_bar{/*background-image:url(imgs/top-separator.gif);background-position:0 0;background-repeat:no-repeat; */background-color:transparent;padding-top:3px;border-left:0;} + +.openerp .dhx_multi_day{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/multi-days-bg.png);background-repeat:repeat;} + +.openerp .dhx_month_head{background-color:#F4F4F4;} + +.openerp .dhx_after .dhx_month_head,.openerp .dhx_before .dhx_month_head{background-color:#F4F4F4;} + +.openerp .dhx_after .dhx_month_body,.openerp .dhx_before .dhx_month_body{background-color:#EFEDE2;} + +.openerp .dhx_cal_event div{border:1px solid #FFBD51;background-color:#FFE4AB;color:#000;} + +.openerp .dhx_in_move{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/move.png);} + +.openerp .dhx_cal_event .dhx_title{background-color:#FFE4AB;} + +.openerp .dhx_cal_light{-moz-box-shadow:5px 5px 5px #888;-khtml-box-shadow:5px 5px 5px #888;background-color:#EBEBEB;border:2px solid #A4BED4;color:#000;} +.openerp .dhx_cal_larea{border:1px solid #A4BED4;border-width:0 1px 1px;background-color:#FFF;} + +.openerp .dhx_cal_lsection{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/lightbox.png);font-size:14px;padding:5px 0 5px 10px;color:#000;} + +.openerp .dhx_cal_light_wide .dhx_cal_lsection{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/multi-days-bg.png);}.openerp .dhx_cal_ltext textarea{background-color:#fff;color:#000;} + +.openerp .dhx_cal_light select,.openerp .dhx_cal_light input{color:#000;} +.openerp .dhx_save_btn{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controlls5.png);} + +.openerp .dhx_cancel_btn{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controlls5.png);} +.openerp .dhx_delete_btn{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controlls5.png);} + +.openerp .div .dhx_menu_head{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controlls5.png);border:1px solid #FFE4AB;} + +.openerp .div .dhx_menu_icon{background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controlls5.png);border:medium none;} + +.openerp .dhx_section_time{height:20px!important;padding:7px 0!important;text-align:center;background:white;} + +.openerp .div .dhx_cal_editor{background-color:#FFE4AB;} + +.openerp .dhx_month_body{ + border-left:1px solid #E9E9E9; + border-bottom:1px solid #E9E9E9; +} + +.openerp .dhx_scale_bar_last{border-right:none;} + +.openerp .dhx_month_head .dhx_year_event{background-color:#ddd;} + +.openerp .dhx_year_body .dhx_before .dhx_month_head,.openerp .dhx_year_body .dhx_after .dhx_month_head, .dhx_year_body .dhx_before .dhx_month_head a,.openerp .dhx_year_body .dhx_after .dhx_month_head a{color:#EFEDE2 ;} + +.openerp .dhx_cal_lsection .dhx_readonly{color:#000;} +.openerp .dhx_tooltip{-moz-box-shadow:2px 2px 2px #888;-khtml-box-shadow:2px 2px 2px #888;} +.openerp .dhx_custom_button{margin-top:-2px;} +.openerp .dhx_cal_lsection .dhx_fullday{color:#000;} +.openerp .dhx_cal_lsection .dhx_cal_checkbox{height:16px;line-height:18px;} +.openerp .dhx_cal_light_wide +.openerp .dhx_cal_lsection .dhx_cal_checkbox{height:20px;} +.openerp .dhx_cal_checkbox label{vertical-align:top;} +.openerp .dhx_cal_light_wide .dhx_cal_lsection{color:black;} +.openerp .dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #A4BED4;background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/multi-days-bg.png);} +.openerp .dhx_cal_light_wide .dhx_cal_ltext{border-left:1px solid #A4BED4;} +.openerp .dhx_cal_light_wide .dhx_cal_ltext{background-color:white;} +.openerp .dhx_custom_button{background:white;color:black;} +.openerp .dhx_form_repeat{background:white;} +.openerp .dhx_repeat_divider{border-left:1px solid #A4BED4;} +.openerp .dhx_cal_header .dhx_second_cal_header{background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/second-top-days-bg.png");padding-right:20px;} +.openerp .dhx_scale_bar{padding-top:4px;} + +.openerp .dhx_second_scale_bar{border-bottom:0;padding-top:4px;} +.openerp .dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday,.openerp .dhx_cal_lsection .dhx_fullday{color:#000;font-size:14px;} +.openerp .dhx_cal_light_wide .dhx_cal_lsection{font-size:14px;padding-right:10px;} + + +.openerp .dhx_scale_bar { +/*background-color:#bac6cf; + border-left:1px dotted #7e7e7e; */ + } + + +.openerp .dhx_cal_drag { + background-color:#ff8d8d; + border:1px solid #a73636; +} + + + +.openerp .dhx_in_move{ + background-color:#f7ffb1; +} + + +.openerp .dhx_cal_event div .dhx_menu_icon { + border: medium none; +} + +.openerp .dhx_after .dhx_month_body, .openerp .dhx_before .dhx_month_body { + background-color:#e9e9e9; +} + + +.openerp .dhx_cal_light { + background-color:#ff8d8d; + color: #000102; + border:1px solid #b7a543; +} + +.openerp .dhx_cal_light select { + color: #000102; +} + +.openerp .dhx_cal_lsection { + background-color:#dbcf8c; + color: #fff4b5; +} + +.openerp .dhx_cal_larea { + background-color:#fff4b5; + border:1px solid #b7a543; +} + + +.openerp .dhx_agenda_area{ + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png"); +} + +.openerp .dhx_agenda_line div { + border-right:1px dotted #7e7e7e; +} + +.openerp .dhx_agenda_area .dhx_agenda_line div { + border-right:0px dotted #7e7e7e; +} + + +.openerp .dhx_scale_bar_last { + border-right: none; +} + +.openerp .dhx_year_body .dhx_before .dhx_month_head, .openerp .dhx_year_body .dhx_after .dhx_month_head, .openerp .dhx_year_body .dhx_before .dhx_month_head a, .openerp .dhx_year_body .dhx_after .dhx_month_head a { + color:#bbb; +} +.openerp .dhx_year_body .dhx_before .dhx_month_head:hover, .openerp .dhx_year_body .dhx_after .dhx_month_head:hover, .openerp .dhx_year_body .dhx_before .dhx_month_head a:hover, .openerp .dhx_year_body .dhx_after .dhx_month_head a:hover { + color:white; + text-shadow:none; +} + +.openerp .dhx_tooltip { + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png"); +} + +.openerp .dhx_cal_event div .dhx_menu_head { + border:none; +} + +div.openerp .dhx_menu_head{ + border:1px solid #ff8d8d; +} + +.openerp .dhx_after .dhx_month_head, .openerp .dhx_before .dhx_month_head { + color:#8c9299; +} + +.openerp .dhx_cal_data .dhx_agenda_line { + color:#000102; +} + +.openerp .dhx_cal_header .dhx_agenda_line { + color: #020202; +} + +.openerp .dhx_tooltip_line { + color:#000102; +} + +.openerp .dhx_cal_light select { + background-color: #ffffff; +} + +.openerp .dhx_custom_button { + color: #000102; + background-color: #bac6cf; +} + +div.openerp .dhx_form_repeat { + background-color: #ffffff; +} + +div.openerp .dhx_repeat_divider { + border-left:1px dotted #dbcf8c; +} + + +.openerp .dhx_v_border { + border-right:1px dotted #8c9299; +} + + +.openerp .dhx_scale_bar_last { + border-right: none; +} + +.openerp .dhx_tooltip { + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png"); +} + +.openerp .dhx_text_disabled { + color:#000102; +} + +.openerp .dhx_mini_calendar .dhx_calendar_click { + background-color:#bac6cf; +} + +.openerp .dhx_matrix_cell, .openerp .dhx_matrix_scell { + border-bottom:1px dotted #757575; + border-right:1px dotted #757575; +} + +.openerp .dhx_matrix_cell { + background-color: #ffffff; +} + + +/*=================================================================*/ +/* pro */ +/*=================================================================*/ + + +.openerp .dhx_cal_navline{ + background-color:none; +} + +.openerp .dhx_in_move{ + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/move.png"); +} +.openerp .dhx_cal_light{ + background-color:#bac6cf; + border:2px solid #757575; + color:#000102; +} + +.openerp .dhx_cal_larea{ + border:1px solid #757575; + background-color:#FFFFFF; +} + +.openerp .dhx_cal_lsection{ + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/lightbox.png"); + color:#000102; +} + +.openerp .dhx_cal_ltext{ + background-color:#ffffff; +} + +.openerp .dhx_cal_ltext textarea{ + color:#000102; + background-color:#ffffff; +} + +.openerp .dhx_form_repeat input, .openerp .dhx_form_repeat select{ + background-color:white; + color:black; +} + +.openerp .dhx_cal_light select{ + color:#000102; + background-color:#ffffff; +} + +.openerp .dhx_section_time{ + background-image:none; + background-color:#ffffff; +} + +div.openerp .dhx_cal_editor{ + background-color:#ff8d8d; +} + +div.openerp .dhx_cal_editor textarea { + color: #000102; +} + + +/* .openerp .dhx_year_week{ + background-image:url("./imgs/top-days-bg.png"); +} + +.openerp .dhx_month_head.openerp .dhx_year_event{ + background-color:#ff8d8d; +} */ + +.openerp .dhx_cal_lsection .dhx_readonly{ + color:#000102; +} + +.openerp .dhx_after .dhx_month_head, .openerp .dhx_before .dhx_month_head { + background-color:#F4F4F4; +} + +/* Tree view */ +.openerp .dhx_matrix_scell.folder, .dhx_data_table.folder .dhx_matrix_cell{ + background-color: #7e7e7e; +} +.dhtmlXTooltip.tooltip{ + border-left:1px dotted #7e7e7e; + border-top:1px dotted #7e7e7e; +} +.openerp .dhx_map_area{ + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg_now.png"); +} +.openerp .dhx_map_line div{ + border-right:1px dotted #7e7e7e; +} +.openerp .dhx_map_line .headline_description{ + border-right:1px dotted #7e7e7e; +} +.openerp .dhx_map_line .dhx_map_description{ + border-right: 0px dotted #7e7e7e; +} +.openerp .dhx_map_line .line_description{ + border-right:1px dotted #7e7e7e; +} +.openerp .dhx_map_line.highlight{ + background-color: #bac6cf; +} +.openerp .dhx_map_area .dhx_map_line div{ + border-right:0px dotted #7e7e7e; +} +/* Map view */ +.openerp .dhx_map_area{ + background-image:url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png"); +} +/* Map view end */ + + +/* Agenda week start */ +.openerp .dhx_wa_column_last .dhx_wa_day_cont{ + border-left: 1px dotted #757575; +} +.openerp .dhx_wa_scale_bar { + border-top: 1px dotted #757575; + border-bottom: 1px dotted #757575; + color: #020202; +} +.openerp .dhx_wa_day_data { + background-color: #ffffff; +} +.openerp .dhx_wa_ev_body { + border-bottom: 1px dotted #757575; + color: #000102; +} +.openerp .dhx_wa_dnd { + color: #525253 !important; + background-color: #f7ffb1 !important; + border: 1px solid #757575; +} +.openerp .dhx_cal_event_selected{ + background-color: #757575; + color: ffffff; +} +/* Agenda week end */ +.openerp .dhx_scale_bar_header { + border-bottom: 1px dotted #8894A3; +} + +/*All*/ +/* increase width of lightbox */ +.openerp .dhx_cal_light_wide .dhx_cal_lsection{ + background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/multi-days-bg.png); +} +/*2.3*/ +.openerp .dhx_cal_lsection .dhx_fullday{ + color:#000000; +} +.openerp .dhx_cal_light_wide .dhx_cal_lsection{ + color:#000000; +} +.openerp .dhx_cal_light_wide .dhx_wrap_section{ + border-top:1px solid #757575; + background-image:url(/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/multi-days-bg.png); +} +.openerp .dhx_cal_light_wide .dhx_cal_ltext{ + border-left:1px solid #757575; +} +.openerp .dhx_cal_light_wide .dhx_cal_ltext { + background-color:#ffffff; +} +.openerp .dhx_custom_button{ + background:#ffffff; + color:#000000; +} +/* timeline second scale start */ +.openerp .dhx_cal_header.openerp .dhx_second_cal_header { + background-image: url("/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/second-top-days-bg.png"); +} +/* timeline second scale end */ +.openerp .dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday, .openerp .dhx_cal_lsection .dhx_fullday{ + color:#000000; + font-size: 14px; +} +.openerp .dhx_cal_light_wide .dhx_cal_lsection { + font-size: 14px; +} +.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container { + background-color: #d0e5ff; +} +.openerp div .dhx_cal_editor{ + border:1px solid #B7A543; +} +.openerp .dhx_cal_light_wide .dhx_repeat_divider { + border-color: #757575; +} +.openerp .dhx_cal_event .dhx_header, .openerp .dhx_cal_event .dhx_header { + display:none; +} diff --git a/addons/web_calendar/static/src/img/cal_left.png b/addons/web_calendar/static/src/img/cal_left.png new file mode 100644 index 00000000000..b9b66aaeb63 Binary files /dev/null and b/addons/web_calendar/static/src/img/cal_left.png differ diff --git a/addons/web_calendar/static/src/img/cal_right.png b/addons/web_calendar/static/src/img/cal_right.png new file mode 100644 index 00000000000..3c48e521be4 Binary files /dev/null and b/addons/web_calendar/static/src/img/cal_right.png differ diff --git a/addons/web_calendar/static/src/img/minical_left.png b/addons/web_calendar/static/src/img/minical_left.png new file mode 100644 index 00000000000..b17118fcc67 Binary files /dev/null and b/addons/web_calendar/static/src/img/minical_left.png differ diff --git a/addons/web_calendar/static/src/img/minical_right.png b/addons/web_calendar/static/src/img/minical_right.png new file mode 100644 index 00000000000..ab660de81f0 Binary files /dev/null and b/addons/web_calendar/static/src/img/minical_right.png differ diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js index 982fc60e1c4..93e798ba804 100644 --- a/addons/web_calendar/static/src/js/calendar.js +++ b/addons/web_calendar/static/src/js/calendar.js @@ -112,6 +112,9 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({ scheduler.init('openerp_scheduler', null, this.mode || 'month'); + // Remove hard coded style attributes from dhtmlx scheduler + this.$element.find(".dhx_cal_navline div").removeAttr('style'); + scheduler.detachAllEvents(); scheduler.attachEvent('onEventAdded', this.do_create_event); scheduler.attachEvent('onEventDeleted', this.do_delete_event); @@ -119,20 +122,24 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({ scheduler.attachEvent('onDblClick', this.do_edit_event); scheduler.attachEvent('onBeforeLightbox', this.do_edit_event); - this.mini_calendar = scheduler.renderCalendar({ - container: this.sidebar.navigator.element_id, - navigation: true, - date: scheduler._date, - handler: function(date, calendar) { - scheduler.setCurrentView(date, 'day'); - } - }); + if (this.options.sidebar) { + this.mini_calendar = scheduler.renderCalendar({ + container: this.sidebar.navigator.element_id, + navigation: true, + date: scheduler._date, + handler: function(date, calendar) { + scheduler.setCurrentView(date, 'day'); + } + }); + } }, refresh_scheduler: function() { scheduler.setCurrentView(scheduler._date); }, refresh_minical: function() { - scheduler.updateCalendar(this.mini_calendar); + if (this.options.sidebar) { + scheduler.updateCalendar(this.mini_calendar); + } }, reload_event: function(id) { this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded); @@ -192,7 +199,7 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({ scheduler.parse(res_events, 'json'); this.refresh_scheduler(); this.refresh_minical(); - if (!no_filter_reload) { + if (!no_filter_reload && this.options.sidebar) { this.sidebar.responsible.on_events_loaded(sidebar_items); } }, diff --git a/addons/web_dashboard/po/ar.po b/addons/web_dashboard/po/ar.po index 0e2cf4dfcf2..2c5b34384e5 100644 --- a/addons/web_dashboard/po/ar.po +++ b/addons/web_dashboard/po/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-04 05:32+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/da.po b/addons/web_dashboard/po/da.po index 312ceaa7327..d7de581fb02 100644 --- a/addons/web_dashboard/po/da.po +++ b/addons/web_dashboard/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/de.po b/addons/web_dashboard/po/de.po index 1fecf9c9550..67a6b680ed5 100644 --- a/addons/web_dashboard/po/de.po +++ b/addons/web_dashboard/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/es.po b/addons/web_dashboard/po/es.po index 9686bc1b517..14e8f725d7a 100644 --- a/addons/web_dashboard/po/es.po +++ b/addons/web_dashboard/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/es_EC.po b/addons/web_dashboard/po/es_EC.po index 24ae8287a6d..23c5bdac2c8 100644 --- a/addons/web_dashboard/po/es_EC.po +++ b/addons/web_dashboard/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/et.po b/addons/web_dashboard/po/et.po index 06fccba4842..55560d7a569 100644 --- a/addons/web_dashboard/po/et.po +++ b/addons/web_dashboard/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/fr.po b/addons/web_dashboard/po/fr.po index a8c0e7ba530..47dc7096e90 100644 --- a/addons/web_dashboard/po/fr.po +++ b/addons/web_dashboard/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/gl.po b/addons/web_dashboard/po/gl.po index 16edea4823f..f92e878a783 100644 --- a/addons/web_dashboard/po/gl.po +++ b/addons/web_dashboard/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/it.po b/addons/web_dashboard/po/it.po index 90e98cd48bc..6c190ad89e5 100644 --- a/addons/web_dashboard/po/it.po +++ b/addons/web_dashboard/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/nl_BE.po b/addons/web_dashboard/po/nl_BE.po index 57a9fdadbf5..15d871f19a1 100644 --- a/addons/web_dashboard/po/nl_BE.po +++ b/addons/web_dashboard/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/pl.po b/addons/web_dashboard/po/pl.po index 256945c9030..d5928814062 100644 --- a/addons/web_dashboard/po/pl.po +++ b/addons/web_dashboard/po/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-05 06:04+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/sk.po b/addons/web_dashboard/po/sk.po index a9e11093ef1..cabce5bf3fa 100644 --- a/addons/web_dashboard/po/sk.po +++ b/addons/web_dashboard/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/sl.po b/addons/web_dashboard/po/sl.po index 01a5bf45deb..f0f5cefa43c 100644 --- a/addons/web_dashboard/po/sl.po +++ b/addons/web_dashboard/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/static/src/js/dashboard.js b/addons/web_dashboard/static/src/js/dashboard.js index e629a4a6ef5..deba1529aa3 100644 --- a/addons/web_dashboard/static/src/js/dashboard.js +++ b/addons/web_dashboard/static/src/js/dashboard.js @@ -103,7 +103,7 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({ }, function(result) { self.actions_attrs[aid] = { name: aid, - string: _.trim(result.result.name) + string: _.str.trim(result.result.name) }; qdict.action = { attrs : self.actions_attrs[aid] @@ -218,9 +218,35 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({ }); }, on_load_action: function(result) { - var self = this; - var action_orig = _.extend({}, result.result); - var action = result.result; + var self = this, + action = result.result, + action_attrs = this.actions_attrs[action.id], + view_mode = action_attrs.view_mode; + + // TODO: Use xmo's python evaluator when ready + if (action_attrs.context) { + action.context = _.extend(action.context || {}, action_attrs.context); + } + if (action_attrs.domain) { + action.domain = action.domain || []; + action.domain.push.apply(action.domain, action_attrs.domain); + } + var action_orig = _.extend({}, action); + + if (view_mode && view_mode != action.view_mode) { + var action_view_mode = action.view_mode.split(','); + action.views = _.map(view_mode.split(','), function(mode) { + if (_.indexOf(action_view_mode, mode) < 0) { + return [false, mode == 'tree' ? 'list': mode]; + } else { + mode = mode === 'tree' ? 'list' : mode; + return _.find(action.views, function(view) { + return view[1] == mode; + }); + } + }); + } + action.flags = { search_view : false, sidebar : false, @@ -228,7 +254,10 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({ action_buttons : false, pager: false, low_profile: true, - display_title: false + display_title: false, + list: { + selectable: false + } }; var am = new openerp.web.ActionManager(this); this.action_managers.push(am); @@ -239,6 +268,15 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({ } if (am.inner_viewmanager) { am.inner_viewmanager.on_mode_switch.add(function(mode) { + var new_views = []; + _.each(action_orig.views, function(view) { + new_views[view[1] === mode ? 'unshift' : 'push'](view); + }); + if (!new_views.length || new_views[0][1] !== mode) { + new_views.unshift([false, mode]); + } + action_orig.views = new_views; + action_orig.res_id = am.inner_viewmanager.dataset.ids[am.inner_viewmanager.dataset.index]; self.do_action(action_orig); }); } @@ -420,7 +458,7 @@ openerp.web_dashboard.ApplicationTiles = openerp.web.View.extend({ var Installer = new openerp.web.DataSet(this, 'base.setup.installer'); Installer.call('default_get', [], function (installed_modules) { var installed = _(installed_modules).any(function (active, name) { - return _.startsWith(name, 'cat') && active; }); + return _.str.startsWith(name, 'cat') && active; }); if(installed) { self.do_display_root_menu(); @@ -483,10 +521,13 @@ openerp.web_dashboard.ApplicationTiles = openerp.web.View.extend({ run_configuration_wizards: function () { var self = this; new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) { - $.unblockUI(); self.widget_parent.widget_parent.do_action(action, function () { openerp.webclient.do_reload(); }); + self.$element.empty(); + self.do_display_root_menu().then(function () { + $.unblockUI(); + }); }); } }); @@ -521,7 +562,7 @@ openerp.web_dashboard.Widget = openerp.web.View.extend(/** @lends openerp.web_da }, on_widget_loaded: function (widgets) { var widget = widgets[0]; - var url = _.sprintf( + var url = _.str.sprintf( '/web_dashboard/widgets/content?session_id=%s&widget_id=%d', this.session.session_id, widget.id); this.$element.html(QWeb.render('HomeWidget.content', { diff --git a/addons/web_dashboard/static/src/xml/web_dashboard.xml b/addons/web_dashboard/static/src/xml/web_dashboard.xml index 77eab4b7e28..72f418ebbad 100644 --- a/addons/web_dashboard/static/src/xml/web_dashboard.xml +++ b/addons/web_dashboard/static/src/xml/web_dashboard.xml @@ -116,7 +116,7 @@

        Welcome to your new OpenERP instance.

      • Remember to bookmark this page.
      • -
      • Remember your login:
      • +
      • Remember your login:
      • Choose the first OpenERP Application you want to install..
      • diff --git a/addons/web_default_home/po/ar.po b/addons/web_default_home/po/ar.po index 16c56db9120..f2ffbe0d9bd 100644 --- a/addons/web_default_home/po/ar.po +++ b/addons/web_default_home/po/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-09 05:09+0000\n" -"X-Generator: Launchpad (build 14263)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/da.po b/addons/web_default_home/po/da.po index 989daa78361..ae78d55092a 100644 --- a/addons/web_default_home/po/da.po +++ b/addons/web_default_home/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/de.po b/addons/web_default_home/po/de.po index 2363aea8505..420026692c1 100644 --- a/addons/web_default_home/po/de.po +++ b/addons/web_default_home/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/es.po b/addons/web_default_home/po/es.po index 5120f12015d..75060c85fc9 100644 --- a/addons/web_default_home/po/es.po +++ b/addons/web_default_home/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/es_EC.po b/addons/web_default_home/po/es_EC.po index 077b51cbeee..e57355cf87b 100644 --- a/addons/web_default_home/po/es_EC.po +++ b/addons/web_default_home/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/et.po b/addons/web_default_home/po/et.po index a2dedb192d4..cc250cc6b2b 100644 --- a/addons/web_default_home/po/et.po +++ b/addons/web_default_home/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/fr.po b/addons/web_default_home/po/fr.po index e1b15ca7021..97e7e4467d4 100644 --- a/addons/web_default_home/po/fr.po +++ b/addons/web_default_home/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/gl.po b/addons/web_default_home/po/gl.po index 5783af8a2fb..5447f024fb2 100644 --- a/addons/web_default_home/po/gl.po +++ b/addons/web_default_home/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/it.po b/addons/web_default_home/po/it.po index a9f3a86854b..98bb491b0d8 100644 --- a/addons/web_default_home/po/it.po +++ b/addons/web_default_home/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/nl_BE.po b/addons/web_default_home/po/nl_BE.po index 1f046075120..d6ba01c8cac 100644 --- a/addons/web_default_home/po/nl_BE.po +++ b/addons/web_default_home/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/pl.po b/addons/web_default_home/po/pl.po index 3eec2b0ab49..1c71e3eeb76 100644 --- a/addons/web_default_home/po/pl.po +++ b/addons/web_default_home/po/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-05 06:04+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/sk.po b/addons/web_default_home/po/sk.po index bf766fb65b0..8faf58f469a 100644 --- a/addons/web_default_home/po/sk.po +++ b/addons/web_default_home/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-02 05:05+0000\n" -"X-Generator: Launchpad (build 14214)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/sl.po b/addons/web_default_home/po/sl.po index 2f9d918cb49..88fa4acfd4f 100644 --- a/addons/web_default_home/po/sl.po +++ b/addons/web_default_home/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_diagram/po/ar.po b/addons/web_diagram/po/ar.po index af8c6ab7213..19685c1d457 100644 --- a/addons/web_diagram/po/ar.po +++ b/addons/web_diagram/po/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-04 05:32+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/da.po b/addons/web_diagram/po/da.po index 76d870fbc78..4cff320091f 100644 --- a/addons/web_diagram/po/da.po +++ b/addons/web_diagram/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-09 05:09+0000\n" -"X-Generator: Launchpad (build 14263)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/de.po b/addons/web_diagram/po/de.po index 1a511d763ba..9b7a9c30e89 100644 --- a/addons/web_diagram/po/de.po +++ b/addons/web_diagram/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/es.po b/addons/web_diagram/po/es.po index 465cc16f401..b1d392c9bbd 100644 --- a/addons/web_diagram/po/es.po +++ b/addons/web_diagram/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/es_EC.po b/addons/web_diagram/po/es_EC.po index 3faa86e9bc5..aaf879b3bfe 100644 --- a/addons/web_diagram/po/es_EC.po +++ b/addons/web_diagram/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/et.po b/addons/web_diagram/po/et.po index 5f8e394d816..62aefffe1c4 100644 --- a/addons/web_diagram/po/et.po +++ b/addons/web_diagram/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/gl.po b/addons/web_diagram/po/gl.po index 27f4dc017fa..954f8fab6f6 100644 --- a/addons/web_diagram/po/gl.po +++ b/addons/web_diagram/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/it.po b/addons/web_diagram/po/it.po index c3ced470ca6..443a7e29412 100644 --- a/addons/web_diagram/po/it.po +++ b/addons/web_diagram/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/nl_BE.po b/addons/web_diagram/po/nl_BE.po index 4d2999c099d..756c1ae71b4 100644 --- a/addons/web_diagram/po/nl_BE.po +++ b/addons/web_diagram/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/pl.po b/addons/web_diagram/po/pl.po index f36f3853850..7e9236c6c1b 100644 --- a/addons/web_diagram/po/pl.po +++ b/addons/web_diagram/po/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-05 06:04+0000\n" -"X-Generator: Launchpad (build 14231)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/sl.po b/addons/web_diagram/po/sl.po index 6766b54fb3c..7f552a5576f 100644 --- a/addons/web_diagram/po/sl.po +++ b/addons/web_diagram/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" -"X-Generator: Launchpad (build 14197)\n" +"X-Launchpad-Export-Date: 2011-11-21 05:50+0000\n" +"X-Generator: Launchpad (build 14299)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 04e9d77f5d0..f940cac8b0b 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -187,7 +187,6 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ schedule_bar: function(results) { var self = this; - var group_list, view_chart; if (!this.group_field) { view_chart = (this.orientation === 'horizontal') ? 'barH' : 'bar'; @@ -220,7 +219,7 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ .map(function (value, index) { return { group: self.ordinate + '_' + - value.toLowerCase().replace(/\s/g, '_'), + value.toLowerCase().replace(/[\s\/]+/g,'_'), text: value, color: COLOR_PALETTE[index % COLOR_PALETTE.length] }; @@ -233,23 +232,21 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ // second argument is coerced to a str, no good for boolean r[self.abscissa] = records[0][self.abscissa]; _(records).each(function (record) { - var key = _.sprintf('%s_%s', + var key = _.str.sprintf('%s_%s', self.ordinate, - record[self.group_field].toLowerCase().replace(/\s/g, '_')); + record[self.group_field].toLowerCase().replace(/[\s\/]+/g,'_')); r[key] = record[self.ordinate]; }); return r; }) .value(); } - var abscissa_description = { title: "" + this.fields[this.abscissa].string + "", template: function (obj) { return obj[self.abscissa] || 'Undefined'; } }; - var ordinate_description = { lines: true, title: "" + this.fields[this.ordinate].string + "" @@ -263,7 +260,6 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ x_axis = abscissa_description; y_axis = ordinate_description; } - var renderer = function () { if (self.$element.is(':hidden')) { self.renderer = setTimeout(renderer, 100); @@ -278,7 +274,7 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ border: false, width: 1024, tooltip:{ - template: _.sprintf("#%s#, %s=#%s#", + template: _.str.sprintf("#%s#, %s=#%s#", self.abscissa, group_list[0].text, group_list[0].group) }, radius: 0, @@ -306,7 +302,7 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ bar_chart.addSeries({ value: "#"+column.group+"#", tooltip:{ - template: _.sprintf("#%s#, %s=#%s#", + template: _.str.sprintf("#%s#, %s=#%s#", self.abscissa, column.text, column.group) }, color: column.color @@ -373,9 +369,8 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ }, open_list_view : function (id){ var self = this; - if($(".dhx_tooltip").is(":visible")) { - $(".dhx_tooltip").remove('div'); - } + // unconditionally nuke tooltips before switching view + $(".dhx_tooltip").remove('div'); id = id[this.abscissa]; if (typeof id == 'object'){ id = id[0]; diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index b2d5dcadc25..a3755541548 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -23,6 +23,7 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ this.form_dialog = new openerp.web.FormDialog(this, {}, this.options.action_views_ids.form, dataset).start(); this.form_dialog.on_form_dialog_saved.add_last(this.do_reload); this.aggregates = {}; + this.group_operators = ['avg', 'max', 'min', 'sum', 'count']; this.qweb = new QWeb2.Engine(); this.qweb.debug = openerp.connection.debug; this.qweb.default_dict = { @@ -58,22 +59,26 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ this.transform_qweb_template(child); this.qweb.add_template(openerp.web.json_node_to_xml(child)); break; + } else if (child.tag === 'field') { + this.extract_aggregates(child); + } + } + }, + extract_aggregates: function(node) { + for (var j = 0, jj = this.group_operators.length; j < jj; j++) { + if (node.attrs[this.group_operators[j]]) { + this.aggregates[node.attrs.name] = node.attrs[this.group_operators[j]]; + break; } } }, transform_qweb_template: function(node) { - var qweb_prefix = QWeb.prefix, - group_operator = ['avg', 'max', 'min', 'sum', 'count']; + var qweb_prefix = QWeb.prefix; switch (node.tag) { case 'field': node.tag = qweb_prefix; node.attrs[qweb_prefix + '-esc'] = 'record.' + node.attrs['name'] + '.value'; - for (var j = 0, jj = group_operator.length; j < jj; j++) { - if (node.attrs[group_operator[j]]) { - this.aggregates[node.attrs.name] = node.attrs[group_operator[j]]; - break; - } - } + this.extract_aggregates(node); break case 'button': case 'a': @@ -87,13 +92,13 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ }); if (node.attrs['data-states']) { var states = _.map(node.attrs['data-states'].split(','), function(state) { - return "record.state.raw_value == '" + _.trim(state) + "'"; + return "record.state.raw_value == '" + _.str.trim(state) + "'"; }); node.attrs[qweb_prefix + '-if'] = states.join(' or '); } if (node.attrs['data-kanban_states']) { var states = _.map(node.attrs['data-kanban_states'].split(','), function(state) { - return "record.kanban_state.raw_value == '" + _.trim(state) + "'"; + return "record.kanban_state.raw_value == '" + _.str.trim(state) + "'"; }); node.attrs[qweb_prefix + '-if'] = states.join(' or '); } @@ -372,7 +377,7 @@ openerp.web_kanban.KanbanRecord = openerp.web.Widget.extend({ var self = this, new_record = {}; _.each(record, function(value, name) { - var r = _.clone(self.view.fields_view.fields[name]); + var r = _.clone(self.view.fields_view.fields[name] || {}); r.raw_value = value; r.value = openerp.web.format_value(value, r); new_record[name] = r; @@ -385,7 +390,7 @@ openerp.web_kanban.KanbanRecord = openerp.web.Widget.extend({ widget: this } for (var p in this) { - if (_.startsWith(p, 'kanban_')) { + if (_.str.startsWith(p, 'kanban_')) { ctx[p] = _.bind(this[p], this); } } @@ -497,8 +502,10 @@ openerp.web_kanban.KanbanRecord = openerp.web.Widget.extend({ }, kanban_gravatar: function(email, size) { size = size || 22; + email = _.str.trim(email || '').toLowerCase(); + var default_ = _.str.isBlank(email) ? 'mm' : 'identicon'; var email_md5 = $.md5(email); - return 'http://www.gravatar.com/avatar/' + email_md5 + '.png?s=' + size; + return 'http://www.gravatar.com/avatar/' + email_md5 + '.png?s=' + size + '&d=' + default_; }, kanban_image: function(model, field, id) { id = id || ''; diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml index c1346a0b90d..e63d4de3e66 100644 --- a/addons/web_kanban/static/src/xml/web_kanban.xml +++ b/addons/web_kanban/static/src/xml/web_kanban.xml @@ -1,7 +1,9 @@