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/controllers/main.py b/addons/web/controllers/main.py index 72868647a48..c542bffffad 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -307,7 +307,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: @@ -935,10 +935,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): diff --git a/addons/web/po/pt_BR.po b/addons/web/po/pt_BR.po new file mode 100644 index 00000000000..8b81c9c90cb --- /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-13 05:56+0000\n" +"X-Generator: Launchpad (build 14277)\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/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..62843c10b48 --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch @@ -0,0 +1,34 @@ +--- jquery.tipTip_old.js 2011-11-14 14:05:53.000000000 +0100 ++++ jquery.tipTip.js 2011-11-14 14:41:34.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"); 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..e2fbb832890 --- /dev/null +++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js @@ -0,0 +1,188 @@ + /* + * 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).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/src/css/base.css b/addons/web/static/src/css/base.css index 01f4b11f4d3..c061353d113 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; } @@ -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; diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 0b49e1cc52d..369e1191665 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -993,7 +993,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": ","}; }, @@ -1009,6 +1009,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) { diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 355c6c1b493..d5e789ce3e7 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -70,8 +70,8 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ height: 'auto', position: 'top', buttons: [ - {text: "Close", click: function() { self.stop(); }}, - {text: "Import File", click: function() { self.do_import(); }, 'class': 'oe-dialog-import-button'} + {text: _t("Close"), click: function() { self.stop(); }}, + {text: _t("Import File"), click: function() { self.do_import(); }, 'class': 'oe-dialog-import-button'} ], close: function(event, ui) { self.stop(); diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index d5fcdd35b62..c4af2d0cf6b 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -1,6 +1,66 @@ openerp.web.formats = function(openerp) { +var _t = openerp.web._t; +/** + * Intersperses ``separator`` in ``str`` at the positions indicated by + * ``indices``. + * + * ``indices`` is an array of relative offsets (from the previous insertion + * position, starting from the end of the string) at which to insert + * ``separator``. + * + * There are two special values: + * + * ``-1`` + * indicates the insertion should end now + * ``0`` + * indicates that the previous section pattern should be repeated (until all + * of ``str`` is consumed) + * + * @param {String} str + * @param {Array} 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 * @@ -22,13 +82,16 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { 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( + _.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 = _.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", Math.floor(value), @@ -43,29 +106,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 +130,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 "": @@ -119,8 +172,8 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { case 'progressbar': return openerp.web.parse_value(value, {type: "float"}); case 'datetime': - var datetime = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, - Date.CultureInfo.formatPatterns.longTime)); + var datetime = Date.parseExact( + value, (date_pattern + ' ' + time_pattern)); if (datetime !== null) return openerp.web.datetime_to_str(datetime); datetime = Date.parse(value); @@ -128,7 +181,7 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { return openerp.web.datetime_to_str(datetime); throw new Error(value + " is not a valid datetime"); case 'date': - var date = Date.parseExact(value, Date.CultureInfo.formatPatterns.shortDate); + var date = Date.parseExact(value, date_pattern); if (date !== null) return openerp.web.date_to_str(date); date = Date.parse(value); @@ -136,7 +189,7 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { return openerp.web.date_to_str(date); throw new Error(value + " is not a valid date"); case 'time': - var time = Date.parseExact(value, Date.CultureInfo.formatPatterns.longTime); + var time = Date.parseExact(value, time_pattern); if (time !== null) return openerp.web.time_to_str(time); time = Date.parse(value); diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 0ceab43f1fd..4fb5f02c690 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", @@ -134,6 +135,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(_.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 +218,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 +234,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 +344,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 +356,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 +425,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 _.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 +747,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 +761,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'}); @@ -969,6 +978,12 @@ openerp.web.search.ExtendedSearch = openerp.web.OldWidget.extend({ 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(); @@ -1153,73 +1168,78 @@ 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(); }, start: function() { - this.$element = $("#" + this.element_id); + this._super(); this.datewidget = new openerp.web.DateTimeWidget(this); 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(); }, start: function() { - this.$element = $("#" + this.element_id); + this._super(); this.datewidget = new openerp.web.DateWidget(this); 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 { @@ -1229,16 +1249,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 { @@ -1248,12 +1271,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; @@ -1262,12 +1285,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; @@ -1286,7 +1309,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 cc9f6051462..4dc4eab5301 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -1,4 +1,5 @@ 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) { @@ -43,22 +44,25 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ height: 500, buttons: { "Create": function(){ - //to do + self.on_create_view(); }, "Edit": function(){ self.xml_element_id = 0; self.get_arch(); }, + "Remove": function(){ + self.do_delete_view(); + }, "Close": function(){ self.view_edit_dialog.close(); } }, }).start().open(); this.main_view_id = this.parent.fields_view.view_id; - var action_manager = new openerp.web.ActionManager(this); - action_manager.appendTo(this.view_edit_dialog); - $.when(action_manager.do_action(action)).then(function() { - var viewmanager = action_manager.inner_viewmanager, + 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({ @@ -69,6 +73,99 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); }); }, + on_create_view: function() { + var self = this; + this.create_view_dialog = new openerp.web.Dialog(this, { + modal: true, + title: _.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.invalid) { + warn = true; + return false; + }; + if (widget.dirty && !widget.invalid) { + view_values[widget.name] = widget.get_value(); + } + }); + if (warn) { + self.on_valid_create_view(); + } 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': 'char', '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.name); + if (widget.selection) { + type_widget.selection = widget.selection; + } + type_widget.required = widget.required; + 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; + } + }); + 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 = _.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() { + var msg = "
    "; + _.each(self.create_view_widget, function(widget) { + if (widget.invalid) { + msg += "
  • " + widget.name + "
  • "; + } + }); + msg += "
"; + self.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'))? @@ -80,7 +177,16 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ _.sprintf( "<%s>",node.tagName.toLowerCase()); } }, - + do_delete_view: function() { + var self = this; + 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(); + self.main_view_id = self.parent.fields_view.view_id; + }); + } + }, create_View_Node: function(node){ var self = this; ViewNode = { @@ -96,7 +202,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); return ViewNode; }, - append_child_object: function(main_object, parent_id, child_obj_list) { var self = this; if(main_object.id == parent_id){ @@ -109,7 +214,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); } }, - convert_arch_to_obj: function(xml_Node, main_object, parent_id){ var self = this; var child_obj_list = []; @@ -127,7 +231,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); return main_object; }, - parse_xml: function(arch, view_id) { main_object = { 'level': 0, @@ -139,23 +242,26 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var xml_arch = QWeb.load_xml(arch); return [this.convert_arch_to_obj(xml_arch.childNodes, main_object, this.xml_element_id)]; }, - get_arch: function() { var self = this; var view_arch_list = []; this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type'], function(arch) { - var arch_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}); - 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); + if (arch.length) { + var arch_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}); + 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}); }); - return self.edit_view({"main_object": arch_object, - "parent_child_id": self.parent_child_list(arch_object, []), - "arch": view_arch_list}); - }); + } else { + self.do_warn("Please select view in list :"); + } }); }, parent_child_list : function(one_object, parent_list) { @@ -168,7 +274,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); return parent_list; }, - inherit_view : function(arch_object, result) { var self = this; var xml_list = []; @@ -279,8 +384,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ sidebar: false, views_switcher: false, action_buttons: false, - search_view: false, - pager: false, }, }; var action_manager = new openerp.web.ActionManager(self); @@ -291,7 +394,11 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ } } }).start().open(); - this.edit_xml_dialog.$element.html(QWeb.render('view_editor', {'data': one_object['main_object']})); + var no_property_att = []; + _.each(_PROPERTIES, function(val, key) { + if (! val.length) no_property_att.push(key); + }); + 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'); @@ -451,8 +558,12 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ if (insert.length == check_list.length ) {return xml_child;} }); } - return self.do_save_xml(arch.arch, obj[0].child_id[0], parseInt(clicked_tr_id), [], parseInt(clicked_tr_level), - parseInt(view_id), arch, move_direct, update_values); + 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], + parseInt(clicked_tr_id), [], parseInt(clicked_tr_level), + parseInt(view_id), arch, move_direct, update_values); }, get_object_by_id: function(view_xml_id, one_object, result) { var self = this; @@ -511,7 +622,8 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ } } var parent = $(arch1).parents(); - var convert_to_utf = QWeb.tools.xml_node_to_string(parent[parent.length-1]); + var convert_to_utf = (parent.length != 0)?parent[parent.length-1]:arch1; + 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; @@ -564,8 +676,8 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ "Update": function(){ var update_values = []; _.each(self.edit_widget, function(widget) { - if (widget.dirty) { - update_values.push(widget.get_value()); + if (widget.dirty && !widget.invalid) { + update_values.push([widget.name, widget.get_value()]); } }); self.do_save_update_arch(obj, view_id, view_xml_id, clicked_tr_id, clicked_tr_level, "update_node", update_values); @@ -581,20 +693,20 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var arch_val = self.get_object_by_id(clicked_tr_id,obj['main_object'], []); this.edit_node_dialog.$element.append('
'); this.edit_widget = []; - _.each(properties, function(record) { - var id = record, - type_widget; - self.ready = $.when(self.on_groups(id)).then(function () { - if (_.include(widget,id)){ - type_widget = new (self.property.get_any(['undefined' , id, arch_val[0]['att_list'][0]])) (self.edit_node_dialog, id); + _.each(properties, function(property) { + type_widget = false; + self.ready = $.when(self.on_groups(property)).then(function () { + if (_.include(widget, property)){ + type_widget = new (self.property.get_any([property])) (self.edit_node_dialog, property); } else { - type_widget = new openerp.web.ViewEditor.FieldChar (self.edit_node_dialog, id); + type_widget = new openerp.web.ViewEditor.FieldChar (self.edit_node_dialog, property); } var value = _.detect(arch_val[0]['att_list'],function(res) { - return _.include(res, id); + return _.include(res, property); }); - if (id == 'groups') type_widget.selection = self.groups; - self.edit_node_dialog.$element.find('table[id=rec_table]').append(''+id+':'+type_widget.render()+''); + value = value instanceof Array ? value[1] : value; + if (property == 'groups') type_widget.selection = self.groups; + self.edit_node_dialog.$element.find('table[id=rec_table]').append('' + property + ':' + type_widget.render() + ''); type_widget.start(); type_widget.set_value(value); self.edit_widget.push(type_widget); @@ -602,10 +714,10 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); }, //for getting groups - on_groups: function(id){ + on_groups: function(property){ var self = this, def = $.Deferred(); - if (id != 'groups') { + if (property != 'groups') { self.groups = false; return false; } @@ -638,10 +750,11 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var self = this; var positions = ['After','Before','Inside']; var render_list = []; - render_list.push(["node_type",(_.keys(_CHILDREN)).sort()]); - render_list.push(["position",positions]); - render_list.push(["Fields",fields]); - this.edit_widget = []; + var render_list =[{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), + 'value': 'field', 'string': 'Node Type'}, + {'name': 'position','selection': positions, 'value': false, 'string': 'Position'}, + {'name': 'field_value','selection': fields, 'value': false, 'string': ''}]; + this.add_widget = []; this.add_node_dialog = new openerp.web.Dialog(this,{ modal: true, title: 'Properties', @@ -649,25 +762,23 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ height: 300, buttons: { "Update": function(){ - var node_type,position,field_value; var check_add_node = true; - _.each(self.edit_widget, function(widget) { - (widget.name == "node_type")?node_type = widget.get_value()[1]:false; - (widget.name == "position")?position = widget.get_value()[1]:false; - (widget.name == "Fields")?field_value = widget.get_value()[1]:false; + var values = {}; + _.each(self.add_widget, function(widget) { + values[widget.name] = widget.get_value() || false; }); - (position == "Inside")? - check_add_node =(_.include(_CHILDREN[properties[0]],node_type))?true:false: - check_add_node =(_.include(_CHILDREN[properties[1]],node_type))?true:false; - if(node_type == "field" && check_add_node ) - {check_add_node = (field_value != " ")?true: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 = (node_type == "field")? - _.sprintf("<%s name='%s'> ",node_type,field_value,node_type): - _.sprintf("<%s> ",node_type,node_type); + var tag = (values.node_type == "field")? + _.sprintf("<%s name='%s'> ",values.node_type,values.field_value,values.node_type): + _.sprintf("<%s> ",values.node_type,values.node_type); self.do_save_update_arch(one_object, view_id, view_xml_id, - clicked_tr_id, clicked_tr_level, "add_node", [tag, position]); + clicked_tr_id, clicked_tr_level, "add_node", [tag, values.position]); }else{alert("Can't Update View");} }, "Cancel": function(){ @@ -679,15 +790,14 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ append('
'); var table_selector = self.add_node_dialog.$element.find('table[id=rec_table]'); _.each(render_list,function(node){ - type_widget = new openerp.web.ViewEditor.FieldSelect (self.add_node_dialog, node[0]); - type_widget.selection = node[1]; - if(node[0]=="Fields"){ node[0] = "";} - table_selector.append(''+node[0]+''+type_widget.render()+''); + type_widget = new openerp.web.ViewEditor.FieldSelect (self.add_node_dialog, node.name); + type_widget.selection = node.selection; + table_selector.append('' + node.string + ':' + type_widget.render() + ''); type_widget.start(); - self.edit_widget.push(type_widget); + type_widget.set_value(node.value); + self.add_widget.push(type_widget); }); table_selector.append(' '); - self.add_node_dialog.$element.find("select[id=node_type] option[value=field]").attr("selected",1); 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) { @@ -704,77 +814,98 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ target: "new", flags: { action_buttons: true, - }, - }; + } + } var action_manager = new openerp.web.ActionManager(self); action_manager.do_action(action); - }); - } }); openerp.web.ViewEditor.Field = openerp.web.Class.extend({ - init: function(view, id) { + init: function(view, name) { this.$element = view.$element; this.dirty = false; - this.name = id; + this.name = name; + this.required = false; + this.invalid = false; + }, + start: function () { + this.update_dom(); + }, + update_dom: function() { + this.$element.find("td[id="+ this.name+"]").toggleClass('invalid', this.invalid); + this.$element.find("td[id="+ this.name+"]").toggleClass('required', this.required); }, on_ui_change: function() { + var value = this.get_value(); + value = value instanceof Array ? value[1] : value; + if (this.required && !value) { + this.invalid = true; + } else { + this.invalid = false; + } this.dirty = true; + this.update_dom(); }, render: function() { - return QWeb.render(this.template, {widget: this}); + return _.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', value[1]); + this.$element.find("input[id=" + this.name+ "]").attr('checked', true); } }, get_value: function() { - var value = this.$element.find("input[id=" + this.name + "]").is(':checked'); - return value ? [this.name, value] : [this.name, null]; + return this.$element.find("input[id=" + this.name + "]").is(':checked') || 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) { - value ? this.$element.find("input[id=" + this.name + "]").val(value[1]): this.$element.find("tr[id=" + this.name + "] input").val(); + this.$element.find("input[id=" + this.name + "]").val(value); }, get_value: function() { - var value= this.$element.find("input[id=" + this.name + "]").val(); - return value ? [this.name, value] : [this.name, ""]; + return this.$element.find("input[id=" + this.name + "]").val(); } }); openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ template : "vieweditor_selection", + init: function(view, name) { + this._super(view, name); + this.selection = false; + }, start: function () { var self = this; + this._super(); this.$element.find("select[id=" + this.name + "]").css('width', '100%').change(function() { self.on_ui_change(); - add_node = self.get_value(); - if(add_node[0] == "node_type"){ - if(add_node[1] == "field"){self.$element.find("select[id=Fields]").show();} - else{self.$element.find("select[id=Fields]").hide();} + if(self.name == "node_type"){ + (self.get_value() == "field")? + self.$element.find("select[id=field_value]").show(): + self.$element.find("select[id=field_value]").hide(); } }); + }, set_value: function(value) { value = value === null ? false : value; - value = value instanceof Array ? value[1] : value; var index = 0; 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; @@ -782,13 +913,12 @@ openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ this.$element.find("select[id=" + this.name + "]")[0].selectedIndex = index; }, get_value: function() { - var value = this.$element.find("select[id=" + this.name + "]").val(); - return value ? [this.name, value] : [this.name, ""]; + return this.$element.find("select[id=" + this.name + "]").val(); } }); openerp.web.ViewEditor.WidgetProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.registry = openerp.web.form.widgets; var values = _.keys(this.registry.map); values.push(''); @@ -797,46 +927,42 @@ openerp.web.ViewEditor.WidgetProperty = openerp.web.ViewEditor.FieldSelect.exten }, }); openerp.web.ViewEditor.IconProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); - this.selection = icons; + init: function(view, name) { + this._super(view, name); + this.selection = _ICONS; }, }); openerp.web.ViewEditor.ButtonTargetProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.selection = [['', ''], ['new', 'New Window']]; }, }); openerp.web.ViewEditor.ButtonTypeProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.selection = [['', ''], ['action', 'Action'], ['object', 'Object'], ['workflow', 'Workflow'], ['server_action', 'Server Action']]; }, }); openerp.web.ViewEditor.AlignProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.selection = [['', ''], ['0.0', 'Left'], ['0.5', 'Center'], ['1.0', 'Right']]; }, }); openerp.web.ViewEditor.ButtonSpecialProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.selection = [['',''],['save', 'Save Button'], ['cancel', 'Cancel Button'], ['open', 'Open Button']]; }, }); openerp.web.ViewEditor.PositionProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); + init: function(view, name) { + this._super(view, name); this.selection = [['',''],['after', 'After'],['before', 'Before'],['inside', 'Inside'],['replace', 'Replace']]; }, }); openerp.web.ViewEditor.GroupsProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, id) { - this._super(view, id); - this.multiple = true; - }, start: function () { this._super(); this.$element.find("select[id=" + this.name + "]").css('height', '100px').attr("multiple",true); @@ -846,7 +972,7 @@ openerp.web.ViewEditor.GroupsProperty = openerp.web.ViewEditor.FieldSelect.exten self.$element.find("#groups option").attr("selected",false); if (!value) return false; _.each(this.selection, function(item) { - if (_.include(value[1].split(','), item[0])) { + if (_.include(value.split(','), item[0])) { self.$element.find("select[id="+self.name+"] option[value='" + item[0] +"']").attr("selected",1) } }); @@ -871,7 +997,7 @@ var _PROPERTIES = { 'graph' : ['string', 'type'], 'calendar' : ['string', 'date_start', 'date_stop', 'date_delay', 'day_length', 'color', 'mode'], }; -_CHILDREN = { +var _CHILDREN = { 'form': ['notebook', 'group', 'field', 'label', 'button','board', 'newline', 'separator'], 'tree': ['field'], 'graph': ['field'], @@ -922,11 +1048,13 @@ openerp.web.ViewEditor.property_widget = new openerp.web.Registry({ 'completion' : 'openerp.web.ViewEditor.FieldBoolean', 'widget' : 'openerp.web.ViewEditor.WidgetProperty', 'groups' : 'openerp.web.ViewEditor.GroupsProperty', - 'position': 'openerp.web.ViewEditor.PositionProperty', - 'icon': 'openerp.web.ViewEditor.IconProperty', - 'align': 'openerp.web.ViewEditor.AlignProperty', - 'special': 'openerp.web.ViewEditor.ButtonSpecialProperty', - 'type': 'openerp.web.ViewEditor.ButtonTypeProperty', - 'target': 'openerp.web.ViewEditor.ButtonTargetProperty' + 'position' : 'openerp.web.ViewEditor.PositionProperty', + 'icon' : 'openerp.web.ViewEditor.IconProperty', + 'align' : 'openerp.web.ViewEditor.AlignProperty', + 'special' : 'openerp.web.ViewEditor.ButtonSpecialProperty', + 'type' : 'openerp.web.ViewEditor.ButtonTypeProperty', + 'target' : 'openerp.web.ViewEditor.ButtonTargetProperty', + 'selection' : 'openerp.web.ViewEditor.FieldSelect', + 'char' : 'openerp.web.ViewEditor.FieldChar', }); }; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 53d7eeb60fb..84041ef8b60 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -776,6 +776,25 @@ 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(); @@ -916,6 +935,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) { @@ -944,6 +967,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++) { @@ -1007,6 +1035,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; @@ -1106,6 +1137,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); @@ -1151,6 +1185,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; @@ -3083,7 +3122,7 @@ openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldURIReadonly.exten */ 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 207d12a64e1..77f04d4c864 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -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, @@ -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(''); diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 92ad85232c4..efa5ac5b2a8 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -468,10 +468,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(); @@ -568,35 +568,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 +597,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' } ]); @@ -682,34 +673,17 @@ 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 + if (self.widget_parent instanceof session.web.FormView) { + self.widget_parent.do_save(function() { + self.on_item_action_clicked(item); }); - return false; + } else { + self.on_item_action_clicked(item); } - 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); - }); } return false; }); - + var $ul = $section.find('ul'); if(!$ul.length) { $ul = $('
    ').appendTo($section); @@ -717,6 +691,33 @@ session.web.Sidebar = session.web.Widget.extend({ $items.appendTo($ul); } }, + on_item_action_clicked: function(item) { + var self = this; + 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); + }); + }, do_fold: function() { this.$element.addClass('closed-sidebar').removeClass('open-sidebar'); }, diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index d8eb6a3f8f4..9b1c5175571 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -629,7 +629,8 @@ @@ -720,6 +721,17 @@ + + +
    + + +
    +
    + + + +
    • @@ -732,6 +744,19 @@ + + +
      + Notebook Page "" +
      +
        +
      • + Modifiers: + +
      • +
      +
      +
      @@ -744,13 +769,72 @@ + +
      + (nolabel) +
      +

      + +

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

      @@ -758,7 +842,7 @@ @@ -766,7 +850,7 @@
      @@ -986,13 +1070,42 @@ - + + +
      + + Button + : + (no string) + + +
      +
      + +
    • + Special: + +
    • + +
    • + Button Type: + +
    • +
    • + Method: + +
    • +
    • + Action ID: + +
    • +
      +
      @@ -1268,50 +1381,54 @@ - - - - - - - -
      - - - -
      - - - - - - - - - - -
      - - - - - - - - - -
      - - - - - - + + + + + + + + +
      + + + + + +
      + + + + + + + + + + +
      + + + + + + + + + +
      + + + + + + + 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/test.html b/addons/web/static/test/test.html index f6248e705c0..d182ce18707 100644 --- a/addons/web/static/test/test.html +++ b/addons/web/static/test/test.html @@ -23,6 +23,8 @@ + +