diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..d6210b1 --- /dev/null +++ b/__init__.py @@ -0,0 +1,3 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..0384395 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,29 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Web Hierarchy', + 'category': 'Hidden', + 'version': '1.0', + 'description': + """ +Odoo Web Hierarchy view +======================= + +This module adds a new view called to be able to define a view to display +an organization such as an Organization Chart for employees for instance. + """, + 'depends': ['web'], + 'assets': { + 'web.assets_backend': [ + 'web_hierarchy/static/src/hierarchy.variables.scss', + 'web_hierarchy/static/src/**/*', + ], + 'web.assets_web_dark': [ + ('before', 'web_hierarchy/static/src/hierarchy.variables.scss', 'web_hierarchy/static/src/**/*.variables.dark.scss'), + ], + 'web.qunit_suite_tests': [ + 'web_hierarchy/static/tests/**/*', + ], + }, + 'license': 'LGPL-3', +} diff --git a/i18n/ar.po b/i18n/ar.po new file mode 100644 index 0000000..73c6cba --- /dev/null +++ b/i18n/ar.po @@ -0,0 +1,121 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Malaz Abuidris , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Malaz Abuidris , 2024\n" +"Language-Team: Arabic (https://app.transifex.com/odoo/teams/41243/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "عرض نافذة الإجراء" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "قاعدة " + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "لا يمكن تغيير الأصل لأنه سيتسبب في حلقة مغلقة. " + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "طي" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "التسلسل الهرمي" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "يمكن أن يكون التسلسل الهرمي للتابع إما حقل أو قالب فقط ، به %s " + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" +"يمكن أن تحتوي نافذة عرض التسلسل الهرمي الآن على علامة تصنيف قوالب واحدة فقط " + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"من المستحيل تحديث العقدة الأصلية للعقدة التي تم سحبها لأنه لم يتم العثور على" +" الأصل. " + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"خواص غير صالحة (%s) في نافذة عرض التسلسل الهرمي. يجب أن تكون الخواص في (%s) " + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "جديد" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "لا يمكن أن يكون السجل الأصلي السجل الذي تم سحبه. " + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "كشف" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "أداة العرض" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "نوع واجهة العرض" diff --git a/i18n/bg.po b/i18n/bg.po new file mode 100644 index 0000000..566baf6 --- /dev/null +++ b/i18n/bg.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# KeyVillage, 2023 +# Maria Boyadjieva , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Maria Boyadjieva , 2024\n" +"Language-Team: Bulgarian (https://app.transifex.com/odoo/teams/41243/bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Основа" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Сгънете" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Йерархия" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Нов" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Преглед" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Вид изглед" diff --git a/i18n/ca.po b/i18n/ca.po new file mode 100644 index 0000000..1c3ff09 --- /dev/null +++ b/i18n/ca.po @@ -0,0 +1,124 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# RGB Consulting , 2023 +# Josep Anton Belchi, 2023 +# Martin Trigaux, 2023 +# Arnau Ros, 2024 +# Manel Fernandez Ramirez , 2024 +# Óscar Fonseca , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Óscar Fonseca , 2024\n" +"Language-Team: Catalan (https://app.transifex.com/odoo/teams/41243/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Vista de la finestra d'acció" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "No es pot canviar el pare perquè causarà un cíclic." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Plegar" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Jerarquia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "El fill jeràrquic només pot ser un camp o plantilla, s'ha obtingut %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "La vista jeràrquica només pot contenir una etiqueta de plantilles." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Impossible d'actualitzar el node pare a partir del node arrossegat perquè no" +" s'ha trobat cap pare." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Atributs no vàlids (%s) a la vista jeràrquica. Els atributs han d'estar en " +"(%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nou" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "El registre pare no pot ser el registre arrossegat." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Desplegar" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Vista" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipus de vista" diff --git a/i18n/cs.po b/i18n/cs.po new file mode 100644 index 0000000..86b5484 --- /dev/null +++ b/i18n/cs.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Jiří Podhorecký, 2023 +# Jakub Smolka, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Czech (https://app.transifex.com/odoo/teams/41243/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Akce okna zobrazení" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Jádro" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Sbalit" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchie" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nové" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Rozbalit" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Zobrazení" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Typ zobrazení" diff --git a/i18n/da.po b/i18n/da.po new file mode 100644 index 0000000..da68287 --- /dev/null +++ b/i18n/da.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Ejner Sønniksen , 2023 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Danish (https://app.transifex.com/odoo/teams/41243/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Visning af handlingsvindue" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Basis" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Fold" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarki" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Ny" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Fold ud" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Vis" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Se type" diff --git a/i18n/de.po b/i18n/de.po new file mode 100644 index 0000000..a2f17e5 --- /dev/null +++ b/i18n/de.po @@ -0,0 +1,123 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Larissa Manderfeld, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Larissa Manderfeld, 2024\n" +"Language-Team: German (https://app.transifex.com/odoo/teams/41243/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Ansicht des Aktionsfensters" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Basis" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" +"Sie können das übergeordnete Element nicht ändern, da dies einen Zyklus " +"verursacht." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Einklappen" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchie" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"Untergeordnetes Element der Hierarchie kann nur Feld oder Vorlage sein, %s " +"erhalten" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "Hierarchie-Ansicht kann nur ein Vorlagen-Stichwort beinhalten" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Es ist nicht möglich, den übergeordneten Knoten des gezogenen Knotens zu " +"aktualisieren, da kein übergeordneter Knoten gefunden wurde." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Ungültige Attribute (%s) in der Hierarchie-Ansicht. Attribute müssen in (%s)" +" stehen." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Neu" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Der übergeordnete Datensatz kann nicht der gezogene Datensatz sein." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Ausklappen" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Ansicht" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Ansichtstyp" diff --git a/i18n/es.po b/i18n/es.po new file mode 100644 index 0000000..ecdfb0d --- /dev/null +++ b/i18n/es.po @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Larissa Manderfeld, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Larissa Manderfeld, 2024\n" +"Language-Team: Spanish (https://app.transifex.com/odoo/teams/41243/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Vista de acción de ventana" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "No se puede cambiar el principal porque causará un ciclo." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Plegar" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Jerarquía" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"La jerarquía secundaria solo puede ser un campo o una plantilla, recibió %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "La vista de jerarquía solo puede contener una etiqueta de plantillas" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"No se pudo actualizar el nodo principal del nodo arrastrado. No se encontró " +"ningún nodo principal." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Atributos no válidos (%s) en la vista gantt. Los atributos deben estar en " +"(%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nuevo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "El registro principal no puede ser el registro que arrastró." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Desplegar" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Ver" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo de vista" diff --git a/i18n/es_419.po b/i18n/es_419.po new file mode 100644 index 0000000..39d008e --- /dev/null +++ b/i18n/es_419.po @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Fernanda Alvarez, 2023 +# Wil Odoo, 2024 +# Lucia Pacheco, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Lucia Pacheco, 2024\n" +"Language-Team: Spanish (Latin America) (https://app.transifex.com/odoo/teams/41243/es_419/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es_419\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Vista de acción de ventana" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "No se puede cambiar el principal porque causará un ciclo." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Plegar" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Jerarquía" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"La jerarquía secundaria solo puede ser un campo o una plantilla, obtuvo %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "La vista de jerarquía solo puede contener una etiqueta de plantillas" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"No se pudo actualizar el nodo principal del nodo arrastrado. No se encontró " +"ningún nodo principal." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Atributos no válidos (%s) en la vista gantt. Los atributos deben estar en " +"(%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nuevo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "El registro principal no puede ser el registro que arrastró." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Desplegar" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Ver" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo de vista" diff --git a/i18n/et.po b/i18n/et.po new file mode 100644 index 0000000..2008c7b --- /dev/null +++ b/i18n/et.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Leaanika Randmets, 2023 +# Arma Gedonsky , 2023 +# Patrick-Jordan Kiudorv, 2023 +# Eneli Õigus , 2024 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Estonian (https://app.transifex.com/odoo/teams/41243/et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Toimingu akna vaade" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Baas" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Voldi" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarhia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Uus" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Ava" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Vaade" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Vaate tüüp" diff --git a/i18n/fa.po b/i18n/fa.po new file mode 100644 index 0000000..e44cf2c --- /dev/null +++ b/i18n/fa.po @@ -0,0 +1,118 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Zahed Alfak , 2023 +# Martin Trigaux, 2023 +# Hamed Mohammadi , 2024 +# Hanna Kheradroosta, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Hanna Kheradroosta, 2024\n" +"Language-Team: Persian (https://app.transifex.com/odoo/teams/41243/fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "مشاهده پنجره اقدام" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "پایه" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "تا کردن" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "سلسله مراتب" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "جدید" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "باز کردن" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "نما" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "نوع نما" diff --git a/i18n/fi.po b/i18n/fi.po new file mode 100644 index 0000000..5706153 --- /dev/null +++ b/i18n/fi.po @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Tuomo Aura , 2023 +# Miku Laitinen , 2023 +# Martin Trigaux, 2024 +# Ossi Mantylahti , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Ossi Mantylahti , 2024\n" +"Language-Team: Finnish (https://app.transifex.com/odoo/teams/41243/fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Toimintoikkunan näkymä" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Pohja" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "Aiempaa ei voi muuttaa, koska se aiheuttaa ikuisen kierron." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Laskosta" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarkia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "Hierarkian alempi taso voi olla vain kenttä tai malli, sai %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "Hierarkianäkymä voi sisältää vain yhden mallinetunnisteen" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Vedetyn solmun vanhemman solmun päivittäminen on mahdotonta, koska ylemmän " +"tason solmua ei ole löydetty." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Virheelliset attribuutit (%s) hierarkianäkymässä. Attribuuttien on oltava " +"(%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Uusi" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Ylemmällä tasolla oleva tietue ei voi olla vedettävä tietue." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Avaa laskostus" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Näytä" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Näkymän tyyppi" diff --git a/i18n/fr.po b/i18n/fr.po new file mode 100644 index 0000000..8d08646 --- /dev/null +++ b/i18n/fr.po @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Jolien De Paepe, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Jolien De Paepe, 2024\n" +"Language-Team: French (https://app.transifex.com/odoo/teams/41243/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Vue de la fenêtre d'action" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" +"Il n'est pas possible de modifier le parent, car cela entraînerait un cycle." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Replier" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hiérarchie" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"Une ligne enfant hiérarchie ne peut être qu'un champ ou un modèle, vous avez" +" %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "La vie hiérarchie ne peut contenir qu'une seule étiquette de modèles" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Impossible de mettre à jour le nœud parent du nœud déplacé, car aucun parent" +" n'a été trouvé." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Attributs invalides (%s) dans la vue hiérarchie. Les attributs doivent être " +"en (%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nouveau" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "L'enregistrement parent ne peut pas être l'enregistrement déplacé." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Déplier" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Vue" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Type de vue" diff --git a/i18n/he.po b/i18n/he.po new file mode 100644 index 0000000..003718d --- /dev/null +++ b/i18n/he.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# ZVI BLONDER , 2024 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Hebrew (https://app.transifex.com/odoo/teams/41243/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "תצוגת חלון פעולה" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "בסיס" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "קפל" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "היררכיה" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "חדש" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "פרוס" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "תצוגה" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "סוג תצוגה" diff --git a/i18n/hu.po b/i18n/hu.po new file mode 100644 index 0000000..613a91d --- /dev/null +++ b/i18n/hu.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Tamás Németh , 2023 +# Csaba Tóth , 2023 +# krnkris, 2023 +# Martin Trigaux, 2024 +# Ákos Nagy , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Ákos Nagy , 2024\n" +"Language-Team: Hungarian (https://app.transifex.com/odoo/teams/41243/hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Műveletablak megjelenítése" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Alap" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Behajtás" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Rangsor" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Új" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Kihajtás" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Megtekintés" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Nézet típusa" diff --git a/i18n/id.po b/i18n/id.po new file mode 100644 index 0000000..d13e1f6 --- /dev/null +++ b/i18n/id.po @@ -0,0 +1,120 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Abe Manyo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Abe Manyo, 2024\n" +"Language-Team: Indonesian (https://app.transifex.com/odoo/teams/41243/id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Jendela Tindakan" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "Tidak dapat mengubah parent karena akan menimbulkan cyclic." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Lipat" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hirarki" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "Hierarki anak hanya dapat merupakan field atau templat, bukan %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "Tampilan hierarki hanya dapat memiliki satu tag templat" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Mustahil untuk memperbarui node induk dari node yang ditarik karena tidak " +"ada induk yang ditemukan." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Atribut tidak valid (%s) di tampilan hierarki. Atribut harus berada di (%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Baru" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Record induk tidak dapat merupakan record yang ditarik." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Buka" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Lihat" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipe Tampilan" diff --git a/i18n/it.po b/i18n/it.po new file mode 100644 index 0000000..c47e289 --- /dev/null +++ b/i18n/it.po @@ -0,0 +1,123 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Sergio Zanchetta , 2024 +# Marianna Ciofani, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Marianna Ciofani, 2024\n" +"Language-Team: Italian (https://app.transifex.com/odoo/teams/41243/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: it\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Azione visualizzazione finestra" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "Impossibile modificare il genitore perché causerà un ciclo." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Minimizza" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Gerarchia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"Una riga figlia gerarchia può essere solo un campo o un modello, tu hai %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "La vista gerarchia può contenere solo un tag modello" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Impossibile aggiornare il nodo genitore del nodo spostato perché non è stato" +" trovato nessun nodo." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Attributi non validi (%s) nella vista gerarchia. Gli attributi devono essere" +" in (%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nuova" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Il record genitore non può essere il record spostato." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Espandi" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Visualizza" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo vista" diff --git a/i18n/ja.po b/i18n/ja.po new file mode 100644 index 0000000..401b3a9 --- /dev/null +++ b/i18n/ja.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Junko Augias, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Junko Augias, 2024\n" +"Language-Team: Japanese (https://app.transifex.com/odoo/teams/41243/ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "アクションウィンドウビュー" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "ベース" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "サイクリックを引き起こすため、親を変更することはできません。" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "折りたたむ" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "階層" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "階層の子にはフィールドかテンプレートしか指定できません。 %sがあります。" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "階層ビューにはテンプレートタグを1つだけ含めることができます" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "ドラッグされたノードの親ノードが見つからないため、更新できません。" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "階層ビューの無効な属性 (%s)。属性は(%s)である必要があります。" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "新規" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "親レコードをドラッグしたレコードにすることはできません。" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "展開" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "ビュー" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "ビュータイプ" diff --git a/i18n/ko.po b/i18n/ko.po new file mode 100644 index 0000000..57a7e19 --- /dev/null +++ b/i18n/ko.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Daye Jeong, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Korean (https://app.transifex.com/odoo/teams/41243/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "작업 윈도우 보기" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "기준액" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "접기" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "계층" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "하위 계층 구조는 필드나 템플릿만 선택 가능하며, 다음 내용입니다 %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "계층 구조 보기에는 서식 태그가 하나만 포함될 수 있습니다." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "상위 노드를 찾을 수 없으므로 드래그한 노드의 상위 노드를 업데이트할 수 없습니다." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "계층 구조 보기에 유효하지 않은 속성 (%s)이 있습니다. 속성은 (%s)에 위치해야 합니다." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "신규" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "상위 레코드는 드래그한 레코드가 될 수 없습니다." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "펼치기" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "보기" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "화면 유형" diff --git a/i18n/lt.po b/i18n/lt.po new file mode 100644 index 0000000..65e0db5 --- /dev/null +++ b/i18n/lt.po @@ -0,0 +1,118 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# digitouch UAB , 2023 +# Naglis Jonaitis, 2023 +# Linas Versada , 2024 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Lithuanian (https://app.transifex.com/odoo/teams/41243/lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Veiksmo lango peržiūra" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Bazė" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Sutraukti" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchija" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Naujas" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Išskleisti" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Peržiūrėti" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Rodinio tipas" diff --git a/i18n/lv.po b/i18n/lv.po new file mode 100644 index 0000000..624dc00 --- /dev/null +++ b/i18n/lv.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Arnis Putniņš , 2023 +# ievaputnina , 2024 +# JanisJanis , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: JanisJanis , 2024\n" +"Language-Team: Latvian (https://app.transifex.com/odoo/teams/41243/lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Darbības loga skatījums" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Bāze" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Sakļaut" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Jauns" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Izvērst" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Skatījums" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Skatījuma Veids" diff --git a/i18n/nl.po b/i18n/nl.po new file mode 100644 index 0000000..188c752 --- /dev/null +++ b/i18n/nl.po @@ -0,0 +1,124 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# Jolien De Paepe, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Jolien De Paepe, 2024\n" +"Language-Team: Dutch (https://app.transifex.com/odoo/teams/41243/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Actie venster weergave" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Basis" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" +"Kan het bovenliggende model niet wijzigen omdat het een cyclus zal " +"genereren." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Vouwen" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchie" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"Onderliggende hiërarchie kan alleen een veld of een sjabloon zijn, bekwam %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "Hiërarchieweergave kan slechts één sjabloonlabel bevatten" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Kon de bovenliggende node van de versleepte node niet bijwerken, omdat er " +"geen bovenliggende node is gevonden." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Ongeldige kenmerken (%s) in de hiërarchieweergave. Kenmerken moeten in (%s) " +"zijn" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nieuw" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Het bovenliggend record kan niet het versleepte record zijn." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Uitvouwen" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Bekijk" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Soort weergave" diff --git a/i18n/pl.po b/i18n/pl.po new file mode 100644 index 0000000..99510f0 --- /dev/null +++ b/i18n/pl.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Paweł Michoń , 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Polish (https://app.transifex.com/odoo/teams/41243/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Widok okna akcji" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Baza" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Zwiń" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nowe" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Rozwiń" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Widok" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Typ widoku" diff --git a/i18n/pt.po b/i18n/pt.po new file mode 100644 index 0000000..4a19d98 --- /dev/null +++ b/i18n/pt.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Nuno Silva , 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Portuguese (https://app.transifex.com/odoo/teams/41243/pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Dobrar" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarquia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Novo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Ver" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo de Vista" diff --git a/i18n/pt_BR.po b/i18n/pt_BR.po new file mode 100644 index 0000000..4bd151e --- /dev/null +++ b/i18n/pt_BR.po @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# a75f12d3d37ea5bf159c4b3e85eb30e7_0fa6927, 2023 +# Wil Odoo, 2024 +# Maitê Dietze, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Maitê Dietze, 2024\n" +"Language-Team: Portuguese (Brazil) (https://app.transifex.com/odoo/teams/41243/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Exibição da janela de ação" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Base" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "Não é possível alterar o superior porque isso causará um ciclo." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Dobrar" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarquia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"O secundário da hierarquia só pode ser um campo ou um modelo, mas obteve %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "A visualização hierárquica pode conter apenas um marcador de modelo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Não é possível atualizar o nó primário do nó arrastado porque nenhum " +"primário foi encontrado." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Atributos inválidos (%s) na exibição de hierarquia. Os atributos devem estar" +" em (%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Novo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "O registro primário não pode ser o registro arrastado." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Desdobrar" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Visualização" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo de visualização" diff --git a/i18n/ru.po b/i18n/ru.po new file mode 100644 index 0000000..8b7ccff --- /dev/null +++ b/i18n/ru.po @@ -0,0 +1,123 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Сергей Шебанин , 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Russian (https://app.transifex.com/odoo/teams/41243/ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Вид окна действий" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "База" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" +"Невозможно изменить родителя, так как это приведет к циклической ситуации." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Сложить" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Иерархия" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" +"Дочерним элементом иерархии может быть только поле или шаблон, есть %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "Иерархическое представление может содержать только один тег шаблонов" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" +"Невозможно обновить родительский узел перетаскиваемого узла, поскольку " +"родительский узел не найден." + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" +"Недопустимые атрибуты (%s) в представлении иерархии. Атрибуты должны быть в " +"(%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Новый" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "Родительская запись не может быть перетаскиваемой записью." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Разворот" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Просмотр" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Тип просмотра" diff --git a/i18n/sk.po b/i18n/sk.po new file mode 100644 index 0000000..0e4a668 --- /dev/null +++ b/i18n/sk.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Slovak (https://app.transifex.com/odoo/teams/41243/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Okno pohľadu aktivít" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Základ" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Zložiť" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchia" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Nové" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Rozvinúť" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Náhľad" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Typ zobrazenia" diff --git a/i18n/sl.po b/i18n/sl.po new file mode 100644 index 0000000..72e3dc4 --- /dev/null +++ b/i18n/sl.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Tomaž Jug , 2023 +# Matjaz Mozetic , 2023 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Slovenian (https://app.transifex.com/odoo/teams/41243/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Pogled okna za ukrep" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Osnova" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Zlaganje" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Novo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Prikaz" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Vrsta prikaza" diff --git a/i18n/sr.po b/i18n/sr.po new file mode 100644 index 0000000..c932f54 --- /dev/null +++ b/i18n/sr.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Uros Kalajdzic , 2023 +# Dragan Vukosavljevic , 2023 +# Martin Trigaux, 2023 +# Milan Bojovic , 2024 +# コフスタジオ, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: コフスタジオ, 2024\n" +"Language-Team: Serbian (https://app.transifex.com/odoo/teams/41243/sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Action Window View" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Osnova" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Preklopi" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarchy" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Novo" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Razviti" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Pregled" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Vrsta pregleda" diff --git a/i18n/sv.po b/i18n/sv.po new file mode 100644 index 0000000..44a319c --- /dev/null +++ b/i18n/sv.po @@ -0,0 +1,120 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Chrille Hedberg , 2023 +# Mikael Åkerberg , 2023 +# Martin Wilderoth , 2023 +# Kristoffer Grundström , 2023 +# Kim Asplund , 2024 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Swedish (https://app.transifex.com/odoo/teams/41243/sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Vy för åtgärdsfönster" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Bas" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Vik ihop" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hierarki" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Ny" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Veckla ut" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Visa" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Typ av vy" diff --git a/i18n/th.po b/i18n/th.po new file mode 100644 index 0000000..b14f72f --- /dev/null +++ b/i18n/th.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Wil Odoo, 2024 +# Rasareeyar Lappiam, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Rasareeyar Lappiam, 2024\n" +"Language-Team: Thai (https://app.transifex.com/odoo/teams/41243/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "มุมมองหน้าต่างการดำเนินการ" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "ฐาน" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "ไม่สามารถเปลี่ยนพาเรนต์ได้เนื่องจากจะทำให้เกิดวงจร" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "พับ" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "ลำดับชั้น" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "ลำดับชั้นย่อยสามารถเป็นได้เฉพาะฟิลด์หรือเทมเพลต ได้รับ %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "มุมมองลำดับชั้นสามารถมีแท็กเทมเพลตได้เพียงแท็กเดียว" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "ไม่สามารถอัปเดตโหนดหลักของโหนดที่ถูกลากได้ เนื่องจากไม่พบพาเรนต์" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "คุณลักษณะไม่ถูกต้อง (%s) ในมุมมองลำดับชั้น คุณสมบัติต้องอยู่ใน (%s)" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "ใหม่" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "บันทึกหลักไม่สามารถลากบันทึกได้" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "กางออก" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "ดู" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "ประเภทมุมมอง" diff --git a/i18n/tr.po b/i18n/tr.po new file mode 100644 index 0000000..b60458f --- /dev/null +++ b/i18n/tr.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Ediz Duman , 2023 +# İmat Yahya Çataklı , 2023 +# abc Def , 2023 +# Murat Kaplan , 2024 +# Martin Trigaux, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Martin Trigaux, 2024\n" +"Language-Team: Turkish (https://app.transifex.com/odoo/teams/41243/tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Pencere Aksiyon Görünümü" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Temel" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Katla" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Hiyerarşi" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Yeni" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Katları Aç" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Görüntüle" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Görünüm Türü" diff --git a/i18n/uk.po b/i18n/uk.po new file mode 100644 index 0000000..2785331 --- /dev/null +++ b/i18n/uk.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Ukrainian (https://app.transifex.com/odoo/teams/41243/uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Перегляд вікна дії" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "База" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Згорнути" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Ієрархія" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Новий" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Розгорнути" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Перегляд" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Тип перегляду" diff --git a/i18n/vi.po b/i18n/vi.po new file mode 100644 index 0000000..7d0c4c6 --- /dev/null +++ b/i18n/vi.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Thi Huong Nguyen, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Vietnamese (https://app.transifex.com/odoo/teams/41243/vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "Chế độ xem cửa sổ hành động" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "Cơ sở" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "Thu gọn" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "Phân cấp bậc" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "Mới" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "Mở ra" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "Xem" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "Dạng hiển thị" diff --git a/i18n/web_hierarchy.pot b/i18n/web_hierarchy.pot new file mode 100644 index 0000000..283471e --- /dev/null +++ b/i18n/web_hierarchy.pot @@ -0,0 +1,111 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2024-01-05 12:32+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "" diff --git a/i18n/zh_CN.po b/i18n/zh_CN.po new file mode 100644 index 0000000..5df3f66 --- /dev/null +++ b/i18n/zh_CN.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# 山西清水欧度(QQ:54773801) <54773801@qq.com>, 2024 +# Yazi Tian, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Yazi Tian, 2024\n" +"Language-Team: Chinese (China) (https://app.transifex.com/odoo/teams/41243/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "动作窗体视图" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "基础" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "不能更改父节点,因为这会导致循环." + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "折叠" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "层级" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "层次结构子项只能是字段或模板,得 %s" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "层次视图只能包含一个模板标记" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "无法更新拖动节点的父节点,因为没有找到父节点。" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "层次视图中的属性 (%s) 无效。属性必须在 (%s) 中。" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "创建" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "父记录不能是被拖动。" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "展开" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "查看" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "视图类型" diff --git a/i18n/zh_TW.po b/i18n/zh_TW.po new file mode 100644 index 0000000..0bf48ee --- /dev/null +++ b/i18n/zh_TW.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_hierarchy +# +# Translators: +# Martin Trigaux, 2023 +# Wil Odoo, 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 12:32+0000\n" +"PO-Revision-Date: 2023-10-26 23:09+0000\n" +"Last-Translator: Wil Odoo, 2024\n" +"Language-Team: Chinese (Taiwan) (https://app.transifex.com/odoo/teams/41243/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_actions_act_window_view +msgid "Action Window View" +msgstr "動作窗檢視" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_base +msgid "Base" +msgstr "計稅基數" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "Cannot change the parent because it will cause a cyclic." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Fold" +msgstr "收攏" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_view.js:0 +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_actions_act_window_view__view_mode__hierarchy +#: model:ir.model.fields.selection,name:web_hierarchy.selection__ir_ui_view__type__hierarchy +#, python-format +msgid "Hierarchy" +msgstr "層級" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy child can only be field or template, got %s" +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Hierarchy view can contain only one templates tag" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_renderer.js:0 +#, python-format +msgid "" +"Impossible to update the parent node of the dragged node because no parent " +"has been found." +msgstr "" + +#. module: web_hierarchy +#. odoo-python +#: code:addons/web_hierarchy/models/ir_ui_view.py:0 +#, python-format +msgid "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)" +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_controller.xml:0 +#, python-format +msgid "New" +msgstr "新增" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_model.js:0 +#, python-format +msgid "The parent record cannot be the record dragged." +msgstr "" + +#. module: web_hierarchy +#. odoo-javascript +#: code:addons/web_hierarchy/static/src/hierarchy_card.xml:0 +#, python-format +msgid "Unfold" +msgstr "展開" + +#. module: web_hierarchy +#: model:ir.model,name:web_hierarchy.model_ir_ui_view +msgid "View" +msgstr "檢視" + +#. module: web_hierarchy +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_actions_act_window_view__view_mode +#: model:ir.model.fields,field_description:web_hierarchy.field_ir_ui_view__type +msgid "View Type" +msgstr "檢視類型" diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..89107c8 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,5 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import ir_actions +from . import ir_ui_view +from . import models diff --git a/models/ir_actions.py b/models/ir_actions.py new file mode 100644 index 0000000..74ae4fa --- /dev/null +++ b/models/ir_actions.py @@ -0,0 +1,9 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class ActWindowView(models.Model): + _inherit = 'ir.actions.act_window.view' + + view_mode = fields.Selection(selection_add=[('hierarchy', 'Hierarchy')], ondelete={'hierarchy': 'cascade'}) diff --git a/models/ir_ui_view.py b/models/ir_ui_view.py new file mode 100644 index 0000000..d285816 --- /dev/null +++ b/models/ir_ui_view.py @@ -0,0 +1,51 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from lxml import etree + +from odoo import fields, models, _ + +HIERARCHY_VALID_ATTRIBUTES = { + '__validate__', # ir.ui.view implementation detail + 'class', + 'js_class', + 'string', + 'create', + 'edit', + 'delete', + 'parent_field', + 'child_field', + 'icon', + 'draggable', +} + +class View(models.Model): + _inherit = 'ir.ui.view' + + type = fields.Selection(selection_add=[('hierarchy', "Hierarchy")]) + + def _is_qweb_based_view(self, view_type): + return super()._is_qweb_based_view(view_type) or view_type == "hierarchy" + + def _validate_tag_hierarchy(self, node, name_manager, node_info): + if not node_info['validate']: + return + + templates_count = 0 + for child in node.iterchildren(tag=etree.Element): + if child.tag == 'templates': + if not templates_count: + templates_count += 1 + else: + msg = _('Hierarchy view can contain only one templates tag') + self._raise_view_error(msg, child) + elif child.tag != 'field': + msg = _('Hierarchy child can only be field or template, got %s', child.tag) + self._raise_view_error(msg, child) + + remaining = set(node.attrib) - HIERARCHY_VALID_ATTRIBUTES + if remaining: + msg = _( + "Invalid attributes (%s) in hierarchy view. Attributes must be in (%s)", + ','.join(remaining), ','.join(HIERARCHY_VALID_ATTRIBUTES), + ) + self._raise_view_error(msg, node) diff --git a/models/models.py b/models/models.py new file mode 100644 index 0000000..aa8d2db --- /dev/null +++ b/models/models.py @@ -0,0 +1,42 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, models + + +class Base(models.AbstractModel): + _inherit = 'base' + + @api.model + def hierarchy_read(self, domain, fields, parent_field, child_field=None): + if parent_field not in fields: + fields.append(parent_field) + records = self.search(domain) + focus_record = self.env[self._name] + fetch_child_ids_for_all_records = False + if len(records) == 1: + domain = [(parent_field, '=', records.id), ('id', '!=', records.id)] + if records[parent_field]: + focus_record = records + records += focus_record[parent_field] + domain = [('id', 'not in', records.ids), (parent_field, 'in', records.ids)] + records += self.search(domain) + elif not records: + records = self.search([(parent_field, '=', False)]) + else: + fetch_child_ids_for_all_records = True + children_ids_per_record_id = {} + if not child_field: + children_ids_per_record_id = { + record.id: child_ids + for record, child_ids in self._read_group( + [(parent_field, 'in', records.ids if fetch_child_ids_for_all_records else (records - records[parent_field]).ids)], + (parent_field,), + ('id:array_agg',), + ) + } + result = records.read(fields) + if children_ids_per_record_id: + for record_data in result: + if record_data['id'] in children_ids_per_record_id: + record_data['__child_ids__'] = children_ids_per_record_id[record_data['id']] + return result diff --git a/static/src/hierarchy.variables.dark.scss b/static/src/hierarchy.variables.dark.scss new file mode 100644 index 0000000..f6da125 --- /dev/null +++ b/static/src/hierarchy.variables.dark.scss @@ -0,0 +1,3 @@ +$hierarchy_element_dragged-background: $gray-100 !default; +$hierarchy_element_hover-background: #{darken($gray-100, 5%)} !default; +$hierarchy_element_hover-border: #{$gray-100} !default; diff --git a/static/src/hierarchy.variables.scss b/static/src/hierarchy.variables.scss new file mode 100644 index 0000000..b499e58 --- /dev/null +++ b/static/src/hierarchy.variables.scss @@ -0,0 +1,3 @@ +$hierarchy_element_dragged-background: white !default; +$hierarchy_element_hover-background: #e6f2f3 !default; +$hierarchy_element_hover-border: #017e84 !default; diff --git a/static/src/hierarchy_arch_parser.js b/static/src/hierarchy_arch_parser.js new file mode 100644 index 0000000..86f002b --- /dev/null +++ b/static/src/hierarchy_arch_parser.js @@ -0,0 +1,74 @@ +/** @odoo-module */ + +import { visitXML } from "@web/core/utils/xml"; +import { Field } from "@web/views/fields/field"; +import { archParseBoolean, getActiveActions } from "@web/views/utils"; + +export class HierarchyArchParser { + parse(xmlDoc, models, modelName) { + const archInfo = { + activeActions: getActiveActions(xmlDoc), + draggable: false, + icon: "fa-share-alt o_hierarchy_icon", + parentFieldName: "parent_id", + fieldNodes: {}, + templateDocs: {}, + xmlDoc, + }; + const fieldNextIds = {}; + const fields = models[modelName]; + + visitXML(xmlDoc, (node) => { + if (node.hasAttribute("t-name")) { + archInfo.templateDocs[node.getAttribute("t-name")] = node; + return; + } + if (node.tagName === "hierarchy") { + if (node.hasAttribute("parent_field")) { + const parentFieldName = node.getAttribute("parent_field"); + if (!(parentFieldName in fields)) { + throw new Error(`The parent field set (${parentFieldName}) is not defined in the model (${modelName}).`); + } else if (fields[parentFieldName].type !== "many2one") { + throw new Error(`Invalid parent field, it should be a Many2One field.`); + } else if (fields[parentFieldName].relation !== modelName) { + throw new Error(`Invalid parent field, the co-model should be same model than the current one (expected: ${modelName}).`); + } + archInfo.parentFieldName = parentFieldName; + } + if (node.hasAttribute("child_field")) { + const childFieldName = node.getAttribute("child_field"); + if (!(childFieldName in fields)) { + throw new Error(`The child field set (${childFieldName}) is not defined in the model (${modelName}).`); + } else if (fields[childFieldName].type !== "one2many") { + throw new Error(`Invalid child field, it should be a One2Many field.`); + } else if (fields[childFieldName].relation !== modelName) { + throw new Error(`Invalid child field, the co-model should be same model than the current one (expected: ${modelName}).`); + } + archInfo.childFieldName = childFieldName; + } + if (node.hasAttribute("draggable")) { + archInfo.draggable = archParseBoolean(node.getAttribute("draggable")); + } + if (node.hasAttribute("icon")) { + archInfo.icon = node.getAttribute("icon"); + } + } else if (node.tagName === "field") { + const fieldInfo = Field.parseFieldNode(node, models, modelName, "hierarchy"); + const name = fieldInfo.name; + if (!(name in fieldNextIds)) { + fieldNextIds[name] = 0; + } + const fieldId = `${name}_${fieldNextIds[name]++}`; + archInfo.fieldNodes[fieldId] = fieldInfo; + node.setAttribute("field_id", fieldId); + } + }); + + const cardDoc = archInfo.templateDocs["hierarchy-box"]; + if (!cardDoc) { + throw new Error("Missing 'hierarchy-box' template."); + } + + return archInfo; + } +} diff --git a/static/src/hierarchy_card.js b/static/src/hierarchy_card.js new file mode 100644 index 0000000..4a7c40b --- /dev/null +++ b/static/src/hierarchy_card.js @@ -0,0 +1,75 @@ +/** @odoo-module */ + +import { Component } from "@odoo/owl"; + +import { Field } from "@web/views/fields/field"; +import { Record } from "@web/model/record"; +import { ViewButton } from "@web/views/view_button/view_button"; +import { useViewCompiler } from "@web/views/view_compiler"; + +import { HierarchyCompiler } from "./hierarchy_compiler"; +import { getFormattedRecord } from "@web/views/kanban/kanban_record"; + +export class HierarchyCard extends Component { + static components = { + Record, + Field, + ViewButton, + }; + static props = { + node: Object, + openRecord: Function, + archInfo: Object, + templates: Object, + classNames: { type: String, optional: true }, + }; + static defaultProps = { + classNames: "", + }; + static template = "web_hierarchy.HierarchyCard"; + static Compiler = HierarchyCompiler; + + setup() { + const { templates } = this.props; + this.templates = useViewCompiler(this.constructor.Compiler, templates); + } + + get classNames() { + const classNames = [this.props.classNames]; + if (this.props.node.nodes.length) { + classNames.push("o_hierarchy_node_unfolded"); + } + return classNames.join(" "); + } + + getRenderingContext(data) { + const record = getFormattedRecord(data.record); + return { + context: this.props.node.context, + JSON, + luxon, + record, + __comp__: Object.assign(Object.create(this), { this: this }), + __record__: data.record, + }; + } + + onGlobalClick(ev) { + if (ev.target.closest("button")) { + return; + } + this.props.openRecord(this.props.node); + } + + onClickArrowUp(ev) { + this.props.node.fetchParentNode(); + } + + onClickArrowDown(ev) { + if (this.props.node.nodes.length) { + this.props.node.collapseChildNodes(); + } else { + this.props.node.showChildNodes(); + } + } +} diff --git a/static/src/hierarchy_card.scss b/static/src/hierarchy_card.scss new file mode 100644 index 0000000..ad58c97 --- /dev/null +++ b/static/src/hierarchy_card.scss @@ -0,0 +1,71 @@ +@mixin o-hierarchy-node-color { + @for $size from 2 through length($o-colors) { + // Note: the first color is not defined as it is the 'no color' for org chart node + .o_hierarchy_node_color_#{$size - 1} { + background-color: nth($o-colors, $size); + } + } +} + +.o_hierarchy_node_container { + width: 250px; + min-height: 130px; + + &.o_hierarchy_dragged { + margin: 0px; + .o_hierarchy_node { + background-color: $hierarchy_element_dragged-background; + } + } + + &.o_hierarchy_hover { + .o_hierarchy_node { + background-color: $hierarchy_element_hover-background; + border: 3px solid green !important; + } + } + + .o_hierarchy_node { + &:hover { + cursor: pointer; + } + + .o_hierarchy_node_header { + height: 30px; + + div.o_field_background_image { + width: 48px; + height: 48px; + margin-bottom: -24px; + transform: translateY(-24px); + z-index: 1; + + > img { + border-radius: 50%; + } + } + } + + .o_hierarchy_node_body { + .o_employee_availability { + position: absolute; + top: 4px; + right: 2px; + } + } + + .o_hierarchy_node_color_0 { + background-color: $gray-200; + } + + @include o-hierarchy-node-color; + } + + .o_hierarchy_node_button { + grid-template-columns: 50px 1fr 50px; + + .o_hierarchy_icon { + vertical-align: text-top; + } + } +} diff --git a/static/src/hierarchy_card.xml b/static/src/hierarchy_card.xml new file mode 100644 index 0000000..c209200 --- /dev/null +++ b/static/src/hierarchy_card.xml @@ -0,0 +1,61 @@ + + + + +
+
+ +
+
+
+ + + +
+ +
+
+
+ +
diff --git a/static/src/hierarchy_compiler.js b/static/src/hierarchy_compiler.js new file mode 100644 index 0000000..6f09517 --- /dev/null +++ b/static/src/hierarchy_compiler.js @@ -0,0 +1,28 @@ +/** @odoo-module **/ + +import { KanbanCompiler } from "@web/views/kanban/kanban_compiler"; + +export class HierarchyCompiler extends KanbanCompiler { + /** + * @override + * @param {Element} el + * @param {Object} params + * @returns {Element} + */ + compileField(el, params) { + const fieldName = el.getAttribute("name"); + return super.compileField(el, { + ...(params || {}), + recordExpr: "__record__", + dataPointIdExpr: "__comp__.props.node.id", + formattedValueExpr: `record['${fieldName}'].value`, + }); + } + + compileButton(el, params) { + return super.compileButton(el, { + ...(params || {}), + recordExpr: "__record__", + }); + } +} diff --git a/static/src/hierarchy_controller.js b/static/src/hierarchy_controller.js new file mode 100644 index 0000000..e4f440d --- /dev/null +++ b/static/src/hierarchy_controller.js @@ -0,0 +1,64 @@ +/** @odoo-module */ + +import { Component, useRef } from "@odoo/owl"; + +import { useBus } from "@web/core/utils/hooks"; +import { useModel } from "@web/model/model"; +import { addFieldDependencies, extractFieldsFromArchInfo } from "@web/model/relational_model/utils"; +import { CogMenu } from "@web/search/cog_menu/cog_menu"; +import { Layout } from "@web/search/layout"; +import { SearchBar } from "@web/search/search_bar/search_bar"; +import { useSearchBarToggler } from "@web/search/search_bar/search_bar_toggler"; +import { standardViewProps } from "@web/views/standard_view_props"; +import { useViewButtons } from "@web/views/view_button/view_button_hook"; + +export class HierarchyController extends Component { + static components = { + Layout, + CogMenu, + SearchBar, + }; + static props = { + ...standardViewProps, + Model: Function, + Renderer: Function, + buttonTemplate: String, + archInfo: Object, + }; + static template = "web_hierarchy.HierarchyView"; + + setup() { + this.rootRef = useRef("root"); + const { parentFieldName, childFieldName } = this.props.archInfo; + const { activeFields, fields } = extractFieldsFromArchInfo(this.props.archInfo, this.props.fields); + addFieldDependencies(activeFields, fields, [{ name: parentFieldName }]); + this.model = useModel(this.props.Model, { + resModel: this.props.resModel, + activeFields, + fields, + parentFieldName, + childFieldName, + }); + useBus( + this.model.bus, + "update", + () => { + this.render(true); + } + ); + useViewButtons(this.model, this.rootRef, { + beforeExecuteAction: this.beforeExecuteActionButton.bind(this), + afterExecuteAction: this.afterExecuteActionButton.bind(this), + }); + this.searchBarToggler = useSearchBarToggler(); + } + + async openRecord(node, mode) { + const activeIds = this.model.root.resIds; + this.props.selectRecord(node.resId, { activeIds, mode }); + } + + async beforeExecuteActionButton(clickParams) {} + + async afterExecuteActionButton(clickParams) {} +} diff --git a/static/src/hierarchy_controller.xml b/static/src/hierarchy_controller.xml new file mode 100644 index 0000000..72da65e --- /dev/null +++ b/static/src/hierarchy_controller.xml @@ -0,0 +1,45 @@ + + + +
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
diff --git a/static/src/hierarchy_model.js b/static/src/hierarchy_model.js new file mode 100644 index 0000000..6441fb1 --- /dev/null +++ b/static/src/hierarchy_model.js @@ -0,0 +1,977 @@ +/** @odoo-module */ + +import { Domain } from "@web/core/domain"; +import { _t } from "@web/core/l10n/translation"; +import { KeepLast, Mutex } from "@web/core/utils/concurrency"; +import { pick } from "@web/core/utils/objects"; +import { Model } from "@web/model/model"; + +let nodeId = 0; +let forestId = 0; +let treeId = 0; + +/** + * Get the id of the given many2one field value + * + * @param {false | [Number, string]} value many2one value + * @returns {false | Number} id of the many2one + */ +function getIdOfMany2oneField(value) { + return value && value[0]; +} + +export class HierarchyNode { + /** + * Constructor of hierarchy node stored in hierarchy tree + * + * @param {HierarchyModel} model + * @param {Object} config + * @param {Object} data + * @param {HierarchyTree} tree + * @param {HierarchyNode} parentNode + * @param {Boolean} populateChildNodes + */ + constructor(model, config, data, tree, parentNode = null, populateChildNodes = true) { + this.id = nodeId++; + this.data = data; + this.parentNode = parentNode; + this.tree = tree; + this.model = model; + this._config = config; + tree.addNode(this); + if (populateChildNodes) { + this.populateChildNodes(); + } + } + + /** + * Get ancestor node + * + * @returns {HierarchyNode} ancestor node + */ + get ancestorNode() { + return this.parentNode ? this.ancestorNode : this; + } + + /** + * Is leaf? + * + * @returns {Boolean} False if the current node has node as child nodes, otherwise True. + */ + get isLeaf() { + return !this.nodes.length; + } + + /** + * Get forest of the current node + * + * @returns {HierarchyForest} + */ + get forest() { + return this.tree.forest; + } + + /** + * Get the resId of current node + * + * @returns {Number} + */ + get resId() { + return this.data.id; + } + + /** + * Get parent field name + * + * @returns {String} + */ + get parentFieldName() { + return this.model.parentFieldName; + } + + /** + * Get parent res id + * + * @returns {Number} + */ + get parentResId() { + return this.parentNode?.resId || getIdOfMany2oneField(this.data[this.parentFieldName]); + } + + /** + * Get child node res ids + * + * @returns {Number[]} + */ + get childResIds() { + return this.nodes.length ? this.nodes.map((node) => node.resId) : this.data[this.childFieldName]?.map((d) => typeof d === "number" ? d : d.id) || []; + } + + /** + * Get child field name + * + * @returns {String} + */ + get childFieldName() { + return this.model.childFieldName || this.model.defaultChildFieldName; + } + + /** + * Has child nodes? + * + * @returns {Boolean} + */ + get hasChildren() { + return this.nodes.length > 0 || this.data[this.childFieldName]?.length > 0; + } + + /** + * Can show parent node + * + * Knows if the parent node can be fetched and displayed inside the view + * + * @returns {Boolean} True if the current node has a parent node but it is not yet displayed and the data of the + * current node is not already displayed in another node. + */ + get canShowParentNode() { + return Boolean(this.parentResId) + && !this.parentNode + && this.tree.forest.resIds.filter((resId) => resId === this.resId).length === 1; + } + + + /** + * Can show child nodes + * + * Knows if the child nodes can be fetched and displayed inside the view + * + * @returns {Boolean} True if the current node has child nodes but they are not yet displayed and the data of the + * current node is not already displayed in another node. + */ + get canShowChildNodes() { + return this.hasChildren + && this.nodes.length === 0 + && this.tree.forest.resIds.filter((resId) => resId === this.resId).length === 1; + } + + get descendantNodes() { + const subNodes = []; + if (!this.isLeaf) { + subNodes.push(...this.nodes); + for (const node of this.nodes) { + if (node.descendantNodes.length) { + subNodes.push(...node.descendantNodes); + } + } + } + return subNodes; + } + + /** + * Get all descendants nodes parent resIds. If the current node has + * descendants, the result also contains its resId. + */ + get descendantsParentIds() { + const descendantsParentIds = []; + if (!this.isLeaf) { + descendantsParentIds.push(this.resId); + this.nodes.reduce((parentIds, node) => { + if (!node.isLeaf) { + parentIds.push(...node.descendantsParentIds); + } + return parentIds; + }, descendantsParentIds); + } + return descendantsParentIds; + } + + /** + * Get all descendants nodes resIds + * + * @returns {Number[]} + */ + get allSubsidiaryResIds() { + return this.descendantNodes.map((n) => n.resId); + } + + /** + * Populate child nodes + * + * Uses to create child nodes of the current one according to its data. + */ + populateChildNodes() { + this.nodes = []; + const children = this.data[this.childFieldName] || []; + if ( + children.length + && children[0] instanceof Object + && this.tree.forest.resIds.filter((resId) => resId === this.resId).length === 1 + ) { + this.createChildNodes(children); + } + } + + /** + * create child nodes + * + * @param {Object[]} childNodesData data of child nodes to generate + */ + createChildNodes(childNodesData) { + this.nodes = (childNodesData || this.data[this.childFieldName]).map( + (childData) => + new HierarchyNode( + this.model, + this._config, + childData, + this.tree, + this + ) + ); + } + + removeParentNode() { + this.parentNode?.removeChildNode(this); + this.parentNode = null; + this.data[this.parentFieldName] = false; + } + + /** + * Fetch parent node + */ + async fetchParentNode() { + await this.model.fetchManager(this); + } + + /** + * Fetch child nodes + */ + async showChildNodes() { + await this.model.fetchSubordinates(this); + } + + /** + * Collapse child nodes + * + * Removes the descendant nodes of the current one and stores + * the resIds of the child nodes in the data of the current one + * to know it has child nodes to be able to show them again + * when it is needed. + */ + collapseChildNodes() { + const childrenData = []; + for (const childNode of this.nodes) { + childNode.data[this.childFieldName] = childNode.childResIds; + childrenData.push(childNode.data); + } + this.data[this.childFieldName] = childrenData; + this.removeChildNodes(); + this.model.notify(); + } + + removeChildNode(node) { + node.removeChildNodes(); + this.tree.removeNodes([node]); + this.nodes = this.nodes.filter((n) => n.id !== node.id); + this.data[this.childFieldName] = this.nodes.map((n) => n.data); + } + + /** + * Remove descendant nodes of the current one + */ + removeChildNodes() { + for (const childNode of this.nodes) { + if (!childNode.isLeaf) { + childNode.removeChildNodes(); + } + } + this.tree.removeNodes(this.nodes); + this.nodes = []; + } + + /** + * Set parent node to the current node + * + * @param {HierarchyNode} node parent node to set + */ + setParentNode(node) { + this.parentNode = node; + node.addChildNode(this); + const tree = node.tree; + if (tree.root === this) { + tree.root = node; + } else if (this.tree.root === this) { + this.tree.removeRoot(); + this.setTree(node.tree); + } + } + + setTree(tree) { + this.tree = tree; + for (const childNode of this.nodes) { + childNode.setTree(tree); + } + } + + /** + * Adds child node to the current node + * + * @param {HierarchyNode} node child node to add + */ + addChildNode(node) { + this.nodes.push(node); + this.data[this.childFieldName].push(node.data); + this.tree.addNode(node); + } +} + +export class HierarchyTree { + /** + * Constructor + * + * @param {HierarchyModel} model + * @param {Object} config config of the model + * @param {Object} data root node data of the tree to create + * @param {HierarchyForest} forest hierarchy forest containing the tree to create + */ + constructor(model, config, data, forest) { + this.id = treeId++; + this.nodePerNodeId = {}; + this.forest = forest; + if (data) { + this.root = new HierarchyNode(model, config, data, this); + this.forest.nodePerNodeId = { + ...this.forest.nodePerNodeId, + ...this.nodePerNodeId, + }; + } + this.model = model; + this._config = config; + } + + /** + * Get node res ids inside the current tree + * + * @returns {Number} + */ + get resIds() { + return Object.values(this.nodePerNodeId).map((node) => node.resId); + } + + /** + * Add node inside the current tree + * + * @param {HierarchyNode} node node to add inside the current tree + */ + addNode(node) { + this.nodePerNodeId[node.id] = node; + this.forest.addNode(node); + } + + /** + * Remove nodes inside the current tree + * + * @param {HierarchyNode} nodes nodes to remove + */ + removeNodes(nodes) { + const nodeIds = nodes.map((node) => node.id); + this.nodePerNodeId = Object.fromEntries( + Object.entries(this.nodePerNodeId) + .filter( + ([nodeId,]) => !nodeIds.includes(Number(nodeId)) + ) + ); + this.forest.removeNodes(nodes); + } + + removeRoot() { + this.forest.removeTree(this); + } +} + +export class HierarchyForest { + /** + * + * @param {HierarchyModel} model + * @param {Object} config model config + * @param {Object[]} data list of tree root nodes data + */ + constructor(model, config, data) { + this.id = forestId++; + this.nodePerNodeId = {}; + this.trees = data.map((d) => new HierarchyTree(model, config, d, this)); + this.model = model; + this._config = config; + } + + /** + * Get node res ids containing inside the current forest + * + * @returns {Number} + */ + get resIds() { + return Object.values(this.nodePerNodeId).map((node) => node.resId); + } + + /** + * Get root node of all trees inside the current forest + * + * @returns {HierarchyNode[]} root nodes + */ + get rootNodes() { + return this.trees.map((t) => t.root); + } + + /** + * Add a node inside the current forest + * + * @param {HierarchyNode} node node to add inside the current forest + */ + addNode(node) { + this.nodePerNodeId[node.id] = node; + } + + /** + * Removes nodes inside the current forest + * + * @param {HierarchyNode} nodes nodes to remove inside the current forest + */ + removeNodes(nodes) { + const nodeIds = nodes.map((node) => node.id); + this.nodePerNodeId = Object.fromEntries( + Object.entries(this.nodePerNodeId) + .filter( + ([nodeId,]) => !nodeIds.includes(Number(nodeId)) + ) + ); + } + + addNewRootNode(node) { + const tree = new HierarchyTree(this.model, this._config, null, this); + tree.root = node; + node.tree = tree; + tree.addNode(node); + for (const subNode of node.descendantNodes) { + tree.addNode(subNode); + } + this.trees.push(tree); + } + + removeTree(tree) { + this.nodePerNodeId = Object.fromEntries( + Object.entries(this.nodePerNodeId) + .filter( + ([nodeId, ]) => !(nodeId in tree.nodePerNodeId) + ) + ); + this.trees = this.trees.filter((t) => t.id !== tree.id); + } +} + +export class HierarchyModel extends Model { + static services = ["notification"]; + + setup(params, { notification }) { + this.keepLast = new KeepLast(); + this.mutex = new Mutex(); + this.resModel = params.resModel; + this.fields = params.fields; + this.parentFieldName = params.parentFieldName; + this.childFieldName = params.childFieldName; + this.activeFields = params.activeFields; + this.notification = notification; + this.config = { + domain: this.defaultDomain, + isRoot: true, + }; + } + + /** + * Get parent field info + * + * @returns {Object} parent field info + */ + get parentField() { + return this.fields[this.parentFieldName]; + } + + /** + * Get res ids of all nodes displayed in the view + * + * @returns {Number[]} resIds of all nodes displayed in the view + */ + get resIds() { + return this.root?.resIds || []; + } + + /** + * Get default child field name when no child field name is given to the view + * + * @returns {String} default child field name to use + */ + get defaultChildFieldName() { + return "__child_ids__"; + } + + /** + * Get active fields name + * + * @returns {String[]} active fields name + */ + get activeFieldNames() { + return Object.keys(this.activeFields); + } + + /** + * Get default domain to use, when no domain is given in the config + * + * @returns {import("@web/src/core/domain").DomainListRepr} default domain + */ + get defaultDomain() { + return [[this.parentFieldName, '=', false]]; + } + + /** + * Get fields to fetch + * @returns {String[]} fields to fetch + */ + get fieldsToFetch() { + const fieldsToFetch = [ + ...this.activeFieldNames, + ]; + if (this.childFieldName) { + fieldsToFetch.push(this.childFieldName); + } + return fieldsToFetch; + } + + /** + * Load the config and data for hierarchy view + * + * @param {Object} params params to use to load data of hierarchy view + */ + async load(params = {}) { + nodeId = forestId = treeId = 0; + const config = this._getNextConfig(this.config, params); + const data = await this.keepLast.add(this._loadData(config)); + this.root = this._createRoot(config, data); + this.config = config; + this.notify(); + } + + /** + * @override + * Each notify should specify a scroll target (default is to scroll to the + * bottom). + */ + notify(payload = { scrollTarget: "bottom" }) { + super.notify(); + this.bus.trigger("hierarchyScrollTarget", payload); + } + + /** + * Fetch parent node of given node + * @param {HierarchyNode} node node to fetch its parent node + */ + async fetchManager(node) { + if (this.root.trees.length > 1) { // reset the hierarchy + const treeExpanded = this._findTreeExpanded(); + const resIdsToFetch = [node.parentResId, node.resId, ...node.allSubsidiaryResIds]; + if (treeExpanded && treeExpanded.root.id !== node.id && treeExpanded.root.parentResId === node.parentResId) { + resIdsToFetch.push(...treeExpanded.root.allSubsidiaryResIds); + } + const config = { + ...this.config, + domain: ["|", [this.parentFieldName, "=", node.parentResId], ["id", "in", resIdsToFetch]], + } + const data = await this._loadData(config); + this.root = this._createRoot(config, data); + this.notify(); + return; + } + const managerData = await this.keepLast.add(this._fetchManager(node)); + if (managerData) { + const parentNode = new HierarchyNode(this, this.config, managerData, node.tree, null, false); + parentNode.createChildNodes(); + node.setParentNode(parentNode); + this.notify(); + } + } + + /** + * Fetch child nodes of given node + * + * @param {HierarchyNode} node node to fetch its child nodes + */ + async fetchSubordinates(node) { + const childFieldName = this.childFieldName || this.defaultChildFieldName; + const children = node.data[childFieldName]; + if (children.length) { + const nodesToUpdate = []; + if (!(children[0] instanceof Object)) { + const allNodeResIds = this.root.resIds; + const existingChildResIds = children.filter((childResId) => allNodeResIds.includes(childResId)) + if (existingChildResIds.length) { // special case with result found with the search view + for (const tree of this.root.trees) { + if (existingChildResIds.includes(tree.root.resId)) { + nodesToUpdate.push(tree.root); + } + } + } + const data = await this.keepLast.add(this._fetchSubordinates(node, existingChildResIds)); + if (data && data.length) { + node.data[childFieldName] = data; + } + } + const nodeToCollapse = this._searchNodeToCollapse(node); + if (nodeToCollapse && !nodesToUpdate.includes(nodeToCollapse)) { + nodeToCollapse.collapseChildNodes(); + } + node.populateChildNodes(); + for (const n of nodesToUpdate) { + n.setParentNode(node); + } + this.notify(); + } + } + + /** + * Search node to collapse to be able to show the child nodes of node given in parameter + * + * @param {HierarchyNode} node node to show its child nodes. + * @returns {HierarchyNode | null} node found to collapse + */ + _searchNodeToCollapse(node) { + const parentNode = node.parentNode; + let nodeToCollapse = null; + if (parentNode) { + nodeToCollapse = parentNode.nodes.find((n) => n.nodes.length); + } else { + const treeExpanded = this._findTreeExpanded(); + if (treeExpanded) { + nodeToCollapse = treeExpanded.root; + } + } + return nodeToCollapse; + } + + _findTreeExpanded() { + return this.root.trees.find((t) => t.root.nodes.length); + } + + /** + * Get the next model config to use + * + * @param {Object} currentConfig current model config used + * @param {Object} params new params + * @returns {Object} new model config to use + */ + _getNextConfig(currentConfig, params) { + const config = Object.assign({}, currentConfig); + config.context = "context" in params ? params.context : config.context; + if ("domain" in params) { + config.domain = params.domain; + if (!params.domain.length) { + if (config.context.hierarchy_res_id) { + config.domain = [["id", "=", config.context.hierarchy_res_id]]; + delete config.context.hierarchy_res_id; // just needed for the first load. + } else { + config.domain = this.defaultDomain; + } + } + } + return config; + } + + /** + * Load data for hierarchy view + * + * @param {Object} config model config + * @returns {Object[]} main data for hierarchy view + */ + async _loadData(config) { + const result = await this.orm.call( + this.resModel, + "hierarchy_read", + [config.domain, this.fieldsToFetch, this.parentFieldName, this.childFieldName], + { + context: config.context, + }, + ); + const resultStringified = JSON.stringify(result); + const recordsPerParentId = {}; + const recordPerId = {}; + for (const record of result) { + recordPerId[record.id] = record; + const parentId = getIdOfMany2oneField(record[this.parentFieldName]); + if (!(parentId.toString() in recordsPerParentId)) { + recordsPerParentId[parentId] = []; + } + recordsPerParentId[parentId].push(record); + } + const data = []; + const recordIds = []; // to check if we have only one arborescence to display otherwise we display the result as the kanban view + for (const [parentId, records] of Object.entries(recordsPerParentId)) { + if (!parentId || !(parentId in recordPerId)) { + data.push(...records); + } else { + const parentRecord = recordPerId[parentId]; + if (recordIds.includes(parentRecord.id)) { + return JSON.parse(resultStringified); + } + const ancestorId = getIdOfMany2oneField(parentRecord[this.parentFieldName]); + if (ancestorId in recordsPerParentId) { + recordIds.push(...recordsPerParentId[ancestorId].map((r) => r.id)); + } + parentRecord[this.childFieldName || this.defaultChildFieldName] = records; + } + } + if (!data.length && result?.length) { + data.push(recordPerId[Object.keys(recordsPerParentId)[0]]); + } + return data; + } + + /** + * Create forest + * + * @param {Object} config model config to use + * @param {Object[]} data root data + * @returns {HierarchyForest} forest hierarchy + */ + _createRoot(config, data) { + return new HierarchyForest(this, config, data); + } + + /** + * Fetch parent node and its children nodes data + * + * @param {HierarchyNode} node node to fetch its parent node + * @returns {Object} the parent node data with children data inside childFieldName + */ + async _fetchManager(node, exclude_node=true) { + let domain = new Domain([ + "|", + ["id", "=", node.parentResId], + [this.parentFieldName, "=", node.parentResId], + ]); + if (exclude_node) { + domain = Domain.and([ + domain, + [["id", "!=", node.resId]], + ]) + } + const result = await this.orm.searchRead( + this.resModel, + domain.toList({}), + this.fieldsToFetch, + { context: this.config.context }, + ); + let managerData = {}; + const children = []; + for (const data of result) { + if (data.id === node.parentResId) { + managerData = data; + } else { + children.push(data); + } + } + if (!this.childFieldName) { + if (children.length) { + await this._fetchDescendants(children); + } + } + managerData[this.childFieldName || this.defaultChildFieldName] = children; + return managerData; + } + + /** + * Fetch children nodes data for a given node + * + * @param {HierarchyNode} node node to fetch its children nodes + * @param {Array | null} excludeResIds list of ids to exclude (because the nodes already exist) + * @returns {Object[]} list of child node data + */ + async _fetchSubordinates(node, excludeResIds = null) { + let childrenResIds = node.data[this.childFieldName || this.defaultChildFieldName]; + if (excludeResIds) { + childrenResIds = childrenResIds.filter((childResId) => !excludeResIds.includes(childResId)); + } + const data = await this.orm.read( + this.resModel, + childrenResIds, + this.fieldsToFetch, + { context: this.config.context }, + ) + if (!this.childFieldName) { + await this._fetchDescendants(data); + } + return data; + } + + /** + * fetch descendants nodes resIds to know if the child nodes have descendants + * + * @param {Object[]} childrenData child nodes data to fetch its descendants + */ + async _fetchDescendants(childrenData) { + const resIds = childrenData.map((d) => d.id); + if (resIds.length) { + const fetchChildren = await this.orm.readGroup( + this.resModel, + [[this.parentFieldName, "in", resIds]], + ['id:array_agg'], + [this.parentFieldName], + { context: this.config.context || {} }, + ); + const childIdsPerId = Object.fromEntries( + fetchChildren.map((r) => [r[this.parentFieldName][0], r.id]) + ); + for (const d of childrenData) { + if (d.id.toString() in childIdsPerId) { + d[this.defaultChildFieldName] = childIdsPerId[d.id.toString()]; + } + } + } + } + + async updateParentNode(nodeId, { parentNodeId, parentResId }) { + const node = this.root.nodePerNodeId[nodeId]; + const parentNode = parentNodeId ? this.root.nodePerNodeId[parentNodeId] : null; + if (node) { + const oldParentNode = node.parentNode; + let fetchParentChildren = false; + const descendantsParentIds = node.descendantsParentIds; + let domain = new Domain([["id", "=", node.resId]]); + if (oldParentNode) { + domain = Domain.or([domain, [["id", "=", oldParentNode.resId]]]); + } + if (parentNode) { + if (parentNode.resId === node.resId) { + this.notification.add( + _t("The parent record cannot be the record dragged."), + { + type: "danger", + } + ); + return; + } else if (node.allSubsidiaryResIds.includes(parentNode.resId)) { + this.notification.add( + _t("Cannot change the parent because it will cause a cyclic."), + { + type: "danger", + } + ); + return; + } + domain = Domain.or([ + domain, + [["id", "in", [parentNode.resId, node.resId]]], + ]); + if (parentNode.nodes.length === 0 && parentNode.childResIds.length > 0) { + fetchParentChildren = true; + domain = Domain.or([domain, [[this.parentFieldName, "=", parentNode.resId]]]); + } + if (node.id === node.tree.root.id) { + this.root.removeTree(node.tree); + node.tree = parentNode.tree; + } else { + node.removeParentNode(); + } + } else { + node.removeParentNode(); + this.root.addNewRootNode(node); + } + this.notify({ scrollTarget: "none" }); + await this.mutex.exec(async () => { + await this.orm.write( + this.resModel, + [node.resId], + { [this.parentFieldName]: parentResId || parentNode?.resId || false }, + { context: this.config.context } + ); + }); + if (descendantsParentIds.length) { + domain = Domain.or([domain, [[this.parentFieldName, "in", descendantsParentIds]]]); + } + domain = domain.toList({}); + const descendants = {}; + if (domain.length) { + const data = await this.orm.searchRead( + this.resModel, + domain, + this.fieldsToFetch, + { context: this.config.context }, + ); + const children = []; + for (const d of data) { + const parentId = getIdOfMany2oneField(d[this.parentFieldName]); + if (d.id === node.resId) { + node.data = d; + } else if (d.id === oldParentNode?.resId) { + oldParentNode.data = d; + } else if (parentNode?.resId === d.id) { + const parentData = fetchParentChildren + ? {} + : pick( + parentNode.data, + this.childFieldName || this.defaultChildFieldName + ); + parentNode.data = { + ...d, + ...parentData, + }; + } else if (fetchParentChildren && parentId === parentNode.resId) { + children.push(d); + } else { + if (!(parentId in descendants)) { + descendants[parentId] = []; + } + descendants[parentId].push(d); + } + } + if (children.length) { + parentNode.data[this.childFieldName || this.defaultChildFieldName] = children; + } + } + const treeExpanded = this._findTreeExpanded(); + if (parentNode) { + if (treeExpanded && treeExpanded.id !== parentNode.tree.id) { + treeExpanded.root.collapseChildNodes(); + } else if (treeExpanded) { + const nodeToCollapse = this._searchNodeToCollapse( + parentNode.nodes.length ? parentNode.nodes[0] : parentNode + ); + if ( + nodeToCollapse && + (descendants[node.resId]?.length || !parentNode.nodes.length) + ) { + nodeToCollapse.collapseChildNodes(); + } + } + if (fetchParentChildren) { + parentNode.populateChildNodes(); + } + node.setParentNode(parentNode); + } else if (treeExpanded && descendants[node.resId]?.length) { + treeExpanded.root.collapseChildNodes(); + } + let descendantsParent = node; + const handledParents = new Set([node.resId]); + while (descendantsParent) { + const parentId = descendantsParent.resId; + const childNodesData = descendants[parentId]; + if (!childNodesData) { + break; + } + descendantsParent.data[this.childFieldName || this.defaultChildFieldName] = + childNodesData; + descendantsParent.populateChildNodes(); + handledParents.add(descendantsParent.resId); + descendantsParent = descendantsParent.nodes.find((n) => { + return !handledParents.has(n.resId) && n.resId in descendants; + }); + } + this.notify({ scrollTarget: nodeId }); + } + } +} diff --git a/static/src/hierarchy_node_draggable.js b/static/src/hierarchy_node_draggable.js new file mode 100644 index 0000000..f1bc428 --- /dev/null +++ b/static/src/hierarchy_node_draggable.js @@ -0,0 +1,103 @@ +/** @odoo-module */ + +import { onWillUnmount, reactive, useEffect, useExternalListener } from "@odoo/owl"; +import { useThrottleForAnimation } from "@web/core/utils/timing"; +import { pick } from "@web/core/utils/objects"; +import { makeDraggableHook } from "@web/core/utils/draggable_hook_builder"; + +const hookParams = { + name: "useHierarchyNodeDraggable", + acceptedParams: { + rows: [String], + }, + defaultParams: { + edgeScrolling: { speed: 20, threshold: 60 }, + rows: null, + }, + onComputeParams({ ctx, params }) { + // Row selector + ctx.rowSelector = params.rows || null; + if (ctx.rowSelector) { + ctx.fullSelector = `${ctx.rowSelector} ${ctx.fullSelector}`; + } + }, + onDragStart(params) { + const { ctx, addListener, callHandler } = params; + + const onElementPointerEnter = (ev) => { + const element = ev.currentTarget; + current.hierarchyElement = element; + callHandler("onElementEnter", { element }); + }; + + const onElementPointerLeave = (ev) => { + const element = ev.currentTarget; + current.hierarchyElement = null; + callHandler("onElementLeave", { element }); + }; + + const onRowPointerEnter = (ev) => { + const row = ev.currentTarget; + current.hierarchyRow = row; + callHandler("onRowEnter", { row }); + }; + + const onRowPointerLeave = (ev) => { + const row = ev.currentTarget; + current.hierarchyRow = null; + callHandler("onRowLeave", { row }); + }; + + const { ref, current, elementSelector, rowSelector } = ctx; + + for (const rowEl of ref.el.querySelectorAll(rowSelector)) { + addListener(rowEl, "pointerenter", onRowPointerEnter); + addListener(rowEl, "pointerleave", onRowPointerLeave); + } + + for (const siblingEl of ref.el.querySelectorAll(elementSelector)) { + if (siblingEl !== current.element) { + addListener(siblingEl, "pointerenter", onElementPointerEnter); + addListener(siblingEl, "pointerleave", onElementPointerLeave); + } + } + + return pick(current, "element", "row"); + }, + onDragEnd({ ctx }) { + return pick(ctx.current, "element", "row", "hierarchyRow"); + }, + onDrop({ ctx }) { + const { current } = ctx; + const rowElement = current.hierarchyRow; + const element = current.hierarchyElement; + if ((rowElement && rowElement !== current.row) || element) { + return { + element: current.element, + row: current.row, + nextRow: rowElement && current.row !== rowElement ? rowElement : null, + newParentNode: element, + }; + } + }, + onWillStartDrag({ ctx }) { + const { current, rowSelector } = ctx; + + if (rowSelector) { + current.row = current.element.closest(rowSelector); + } + + return pick(current, "element", "row"); + }, +}; + +export function useHierarchyNodeDraggable(params) { + const setupHooks = { + addListener: useExternalListener, + setup: useEffect, + teardown: onWillUnmount, + throttle: useThrottleForAnimation, + wrapState: reactive, + } + return makeDraggableHook({ ...hookParams, setupHooks })(params); +} diff --git a/static/src/hierarchy_renderer.js b/static/src/hierarchy_renderer.js new file mode 100644 index 0000000..1823114 --- /dev/null +++ b/static/src/hierarchy_renderer.js @@ -0,0 +1,145 @@ +/** @odoo-module */ + +import { Component, useRef, onPatched } from "@odoo/owl"; + +import { _t } from "@web/core/l10n/translation"; +import { useBus, useService } from "@web/core/utils/hooks"; +import { scrollTo } from "@web/core/utils/scrolling"; + +import { HierarchyCard } from "./hierarchy_card"; +import { useHierarchyNodeDraggable } from "./hierarchy_node_draggable"; + +export class HierarchyRenderer extends Component { + static components = { + HierarchyCard, + }; + static props = { + model: Object, + openRecord: Function, + archInfo: Object, + templates: Object, + }; + static template = "web_hierarchy.HierarchyRenderer"; + + setup() { + this.rendererRef = useRef("renderer"); + this.notification = useService("notification"); + if (this.canDragAndDropRecord) { + useHierarchyNodeDraggable({ + ref: this.rendererRef, + enable: this.draggable, + elements: ".o_hierarchy_node_container", + handle: ".o_hierarchy_node", + rows: ".o_hierarchy_row", + ignore: "button", + onDragStart: ({ addClass, element }) => { + addClass(element, "o_hierarchy_dragged"); + addClass(element.querySelector(".o_hierarchy_node"), "shadow"); + }, + onDragEnd: ({ removeClass, element, row, hierarchyRow }) => { + removeClass(element, "o_hierarchy_dragged"); + if (row) { + removeClass(row, "o_hierarchy_hover"); + } + if (hierarchyRow) { + removeClass(hierarchyRow, "o_hierarchy_hover"); + } + }, + onDrop: (params) => { + this.nodeDrop(params); + }, + onElementEnter: ({ addClass, element }) => { + addClass(element, "o_hierarchy_hover"); + }, + onElementLeave: ({ removeClass, element }) => { + removeClass(element, "o_hierarchy_hover"); + }, + onRowEnter: ({ addClass, row }) => { + addClass(row, "o_hierarchy_hover"); + }, + onRowLeave: ({ removeClass, row }) => { + removeClass(row, "o_hierarchy_hover"); + }, + }); + } + this.scrollTarget = "none"; + useBus(this.props.model.bus, "hierarchyScrollTarget", (ev) => { + this.scrollTarget = ev.detail?.scrollTarget || "none"; + }); + onPatched(this.onPatched); + } + + onPatched() { + if (this.scrollTarget === "none") { + return; + } + const row = + this.scrollTarget === "bottom" + ? this.rendererRef.el.querySelector(":scope .o_hierarchy_row:last-child") + : this.rendererRef.el + .querySelector( + `:scope .o_hierarchy_node[data-node-id="${this.scrollTarget}"]` + ) + ?.closest(".o_hierarchy_row"); + this.scrollTarget = "none"; + if (!row) { + return; + } + scrollTo(row, { behavior: "smooth" }); + } + + get canDragAndDropRecord() { + return this.draggable && !this.env.isSmall; + } + + get draggable() { + return this.props.archInfo.draggable; + } + + get rows() { + const rootNodes = this.props.model.root.rootNodes; + const rows = [{ nodes: rootNodes }]; + const processNode = (node) => { + if (!node.isLeaf) { + rows.push({ parentNode: node, nodes: node.nodes}); + for (const subNode of node.nodes) { + processNode(subNode); + } + } + }; + + for (const node of this.props.model.root.rootNodes) { + processNode(node); + } + + return rows; + } + + async nodeDrop({ element, row, nextRow, newParentNode }) { + let parentNodeId, parentResId; + if (newParentNode) { + parentNodeId = newParentNode.dataset.nodeId; + } else if (nextRow?.dataset.rowId !== row.dataset.rowId) { + parentNodeId = nextRow.dataset.parentNodeId; + if (!parentNodeId) { + const nodes = this.rows[nextRow.dataset.rowId].nodes || []; + if (nodes) { + parentNodeId = nodes[0].parentNode?.id; + if (!parentNodeId) { + parentResId = nodes[0].parentResId; + if (!nodes.every((node) => node.parentResId === parentResId)) { + this.notification.add( + _t("Impossible to update the parent node of the dragged node because no parent has been found."), + { + type: "danger", + } + ); + return; + } + } + } + } + } + await this.props.model.updateParentNode(element.dataset.nodeId, { parentResId, parentNodeId }); + } +} diff --git a/static/src/hierarchy_renderer.scss b/static/src/hierarchy_renderer.scss new file mode 100644 index 0000000..5ab94b0 --- /dev/null +++ b/static/src/hierarchy_renderer.scss @@ -0,0 +1,74 @@ +$o-chart-line-color: #ababb1; + +.o_hierarchy_renderer { + .o_hierarchy_container { + gap: 25px; + + .o_hierarchy_row { + &.o_hierarchy_hover { + background-color: $hierarchy_element_hover-background; + box-shadow: -1px -1px 0px 0px $hierarchy_element_hover-border inset, + 1px 1px 0px 0px $hierarchy_element_hover-border inset; + } + + &:has(.o_hierarchy_node_unfolded) .o_hierarchy_node_container:not(.o_hierarchy_node_unfolded) { + opacity: 50%; + } + } + + .o_hierarchy_separator { + position: relative; + width: 100%; + + .o_hierarchy_line_left { + &:before { + border-top: 2px solid $o-chart-line-color; + border-left: 2px solid $o-chart-line-color; + border-top-left-radius: 8px; + margin-left: -10%; + margin-top: -2px; + } + + &:after { + border-bottom: 2px solid $o-chart-line-color; + border-right: 2px solid $o-chart-line-color; + border-bottom-right-radius: 6px; + margin-left: 30%; + margin-top: -12px; + } + } + + .o_hierarchy_line_right { + &:before { + border-bottom: 2px solid $o-chart-line-color; + border-left: 2px solid $o-chart-line-color; + border-bottom-left-radius: 6px; + margin-left: calc(-10% - 1px); + margin-top: -12px; + } + + &:after { + border-top: 2px solid $o-chart-line-color; + border-right: 2px solid $o-chart-line-color; + border-top-right-radius: 8px; + margin-left: 30%; + margin-top: -2px; + } + } + + .o_hierarchy_line_part { + border-top: 2px solid $o-chart-line-color; + margin: 0 10%; + width: 30%; + } + + .o_hierarchy_line_part:before, .o_hierarchy_line_part:after { + content: ""; + width: calc(10% + 1px); + height: 12px; + position: absolute; + display: block; + } + } + } +} diff --git a/static/src/hierarchy_renderer.xml b/static/src/hierarchy_renderer.xml new file mode 100644 index 0000000..46a4bed --- /dev/null +++ b/static/src/hierarchy_renderer.xml @@ -0,0 +1,38 @@ + + + + +
+
+ + + +
+ +
+
+
+
+
+
+
+ + + +
+
+
+
+
+ +
diff --git a/static/src/hierarchy_view.js b/static/src/hierarchy_view.js new file mode 100644 index 0000000..a868252 --- /dev/null +++ b/static/src/hierarchy_view.js @@ -0,0 +1,36 @@ +/** @odoo-module */ + +import { _t } from "@web/core/l10n/translation"; +import { registry } from "@web/core/registry"; +import { HierarchyArchParser } from "./hierarchy_arch_parser"; +import { HierarchyController } from "./hierarchy_controller"; +import { HierarchyModel } from "./hierarchy_model"; +import { HierarchyRenderer } from "./hierarchy_renderer"; + +export const hierarchyView = { + type: "hierarchy", + display_name: _t("Hierarchy"), + icon: "fa fa-share-alt o_hierarchy_icon", + isMobileFriendly: false, + multiRecord: true, + ArchParser: HierarchyArchParser, + Controller: HierarchyController, + Model: HierarchyModel, + Renderer: HierarchyRenderer, + buttonTemplate: "web_hierarchy.HierarchyButtons", + searchMenuTypes: [], + + props: (genericProps, view) => { + const { ArchParser, Model, Renderer, buttonTemplate: viewButtonTemplate } = view; + const { arch, relatedModels, resModel, buttonTemplate } = genericProps; + return { + ...genericProps, + archInfo: new ArchParser().parse(arch, relatedModels, resModel), + buttonTemplate: buttonTemplate || viewButtonTemplate, + Model, + Renderer, + }; + } +} + +registry.category("views").add("hierarchy", hierarchyView); diff --git a/static/src/hierarchy_view.scss b/static/src/hierarchy_view.scss new file mode 100644 index 0000000..1683527 --- /dev/null +++ b/static/src/hierarchy_view.scss @@ -0,0 +1,3 @@ +.o_hierarchy_icon { // hierarchy icon + rotate: 90deg; +} diff --git a/static/tests/hierarchy_view_tests.js b/static/tests/hierarchy_view_tests.js new file mode 100644 index 0000000..4a01bb4 --- /dev/null +++ b/static/tests/hierarchy_view_tests.js @@ -0,0 +1,1104 @@ +/** @odoo-module **/ + +import { browser } from "@web/core/browser/browser"; +import { + click, + drag, + dragAndDrop, + getFixture, + getNodesTextContent, + mockAnimationFrame, + nextTick, + patchWithCleanup, + triggerHotkey, +} from "@web/../tests/helpers/utils"; +import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; + +let serverData, target; + +QUnit.module("Views", (hooks) => { + hooks.beforeEach(() => { + serverData = { + models: { + "hr.employee": { + fields: { + parent_id: { string: "Manager", type: "many2one", relation: "hr.employee" }, + name: { string: "Name" }, + child_ids: { string: "Subordinates", type: "one2many", relation: "hr.employee", relation_field: "parent_id" }, + }, + records: [ + { id: 1, name: "Albert", parent_id: false, child_ids: [2, 3] }, + { id: 2, name: "Georges", parent_id: 1, child_ids: [] }, + { id: 3, name: "Josephine", parent_id: 1, child_ids: [4] }, + { id: 4, name: "Louis", parent_id: 3, child_ids: [] }, + ], + }, + }, + views: { + "hr.employee,false,hierarchy": ` + + + +
+ +
+
+ +
+
+
+
+ `, + "hr.employee,1,hierarchy": ` + + + + +
+ +
+
+ +
+
+
+
+ `, + "hr.employee,false,form": ` +
+ + + + + + +
+ `, + }, + }; + setupViewRegistries(); + target = getFixture(); + }); + + QUnit.module("Hierarchy View"); + + QUnit.test("load hierarchy view", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsOnce(target, ".o_hierarchy_view"); + assert.containsN(target, ".o_hierarchy_button_add", 2); + assert.containsOnce(target, ".o_hierarchy_view .o_hierarchy_renderer"); + assert.containsOnce(target, ".o_hierarchy_view .o_hierarchy_renderer > .o_hierarchy_container"); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsOnce(target, ".o_hierarchy_separator"); + assert.containsN(target, ".o_hierarchy_line_part", 2); + assert.containsOnce(target, ".o_hierarchy_line_left"); + assert.containsOnce(target, ".o_hierarchy_line_right"); + assert.containsN(target, ".o_hierarchy_node_container", 3); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.containsN(target, ".o_hierarchy_node_button", 2); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary.d-grid"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary.rounded-0"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary .o_hierarchy_icon"); + assert.strictEqual(target.querySelector(".o_hierarchy_node_button.btn-primary").textContent.trim(), "Unfold 1"); + // check nodes in each row + const row = target.querySelector(".o_hierarchy_row"); + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "Albert"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-secondary"); + assert.strictEqual(target.querySelector(".o_hierarchy_node_button.btn-secondary").textContent.trim(), "Fold"); + }); + + QUnit.test("display child nodes", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + async mockRPC(route, args) { + if (args.method === "read") { + assert.step("get child data"); + } else if (args.method === "read_group") { + assert.step("fetch descendants"); + } + } + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node_button", 2); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-secondary"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary"); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_separator", 2); + assert.containsN(target, ".o_hierarchy_line_part", 4); + assert.containsN(target, ".o_hierarchy_line_left", 2); + assert.containsN(target, ".o_hierarchy_line_right", 2); + assert.containsN(target, ".o_hierarchy_node_container", 4); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.containsN(target, ".o_hierarchy_node_button", 2); + assert.containsNone(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_node_button.btn-secondary", 2); + assert.strictEqual(target.querySelector(".o_hierarchy_node_button.btn-secondary").textContent.trim(), "Fold"); + // check nodes in each row + const rows = target.querySelectorAll(".o_hierarchy_row"); + let row = rows[0]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "Albert"); + row = rows[1]; + assert.containsN(row, ".o_hierarchy_node", 2); + assert.deepEqual( + getNodesTextContent(row.querySelectorAll(".o_hierarchy_node_content")), + [ // Name + Parent name + "GeorgesAlbert", + "JosephineAlbert", + ], + ); + row = rows[2]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "LouisJosephine"); + assert.verifySteps([ + "get child data", + "fetch descendants", + ]); + }); + + QUnit.test("display child nodes with child_field set on the view", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + viewId: 1, + async mockRPC(route, args) { + if (args.method === "read") { + assert.step("get child data with descendants"); + } + } + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node_button", 2); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-secondary"); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary"); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_separator", 2); + assert.containsN(target, ".o_hierarchy_line_part", 4); + assert.containsN(target, ".o_hierarchy_line_left", 2); + assert.containsN(target, ".o_hierarchy_line_right", 2); + assert.containsN(target, ".o_hierarchy_node_container", 4); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.containsN(target, ".o_hierarchy_node_button", 2); + assert.containsNone(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_node_button.btn-secondary", 2); + assert.verifySteps([ + "get child data with descendants", + ]); + }); + + QUnit.test("collapse child nodes", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsOnce(target, ".o_hierarchy_separator"); + assert.containsN(target, ".o_hierarchy_line_part", 2); + assert.containsOnce(target, ".o_hierarchy_line_left"); + assert.containsOnce(target, ".o_hierarchy_line_right"); + assert.containsN(target, ".o_hierarchy_node_container", 3); + assert.containsN(target, ".o_hierarchy_node", 3); + await click(target, ".o_hierarchy_node_button.btn-secondary"); + assert.containsOnce(target, ".o_hierarchy_row"); + assert.containsNone(target, ".o_hierarchy_separator"); + assert.containsNone(target, ".o_hierarchy_line_part", 2); + assert.containsNone(target, ".o_hierarchy_line_left"); + assert.containsNone(target, ".o_hierarchy_line_right"); + assert.containsOnce(target, ".o_hierarchy_node_container"); + assert.containsOnce(target, ".o_hierarchy_node"); + assert.containsNone(target, ".o_hierarchy_node_button.btn-secondary"); + assert.containsOnce(target, ".o_hierarchy_node_button"); + assert.containsOnce(target, ".o_hierarchy_node_container:not(.o_hierarchy_node_button)"); + assert.deepEqual(getNodesTextContent(target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content")), ["Albert"]); + }); + + QUnit.test("display the parent above the line when many records on the parent row", async function (assert) { + serverData.models["hr.employee"].records.push({ + name: "Alfred", + parent_id: false, + child_ids: [], + }) + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsOnce(target, ".o_hierarchy_row"); + assert.containsNone(target, ".o_hierarchy_separator"); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.containsOnce(target, ".o_hierarchy_node_button.btn-primary"); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsOnce(target, ".o_hierarchy_separator"); + assert.containsOnce(target, ".o_hierarchy_line_left"); + assert.containsOnce(target, ".o_hierarchy_line_right"); + assert.containsOnce(target, ".o_hierarchy_parent_node_container"); + assert.strictEqual(target.querySelector(".o_hierarchy_parent_node_container").textContent, "Albert"); + }); + + QUnit.test("search record in hierarchy view", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + domain: [["id", "=", 4]], // simulate a search + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.containsN(target, ".o_hierarchy_separator", 1); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["JosephineAlbert", "LouisJosephine"], + ); + }); + + QUnit.test("search record in hierarchy view with child field name defined in the arch", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + viewId: 1, + serverData, + domain: [["id", "=", 4]], // simulate a search + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.containsN(target, ".o_hierarchy_separator", 1); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["JosephineAlbert", "LouisJosephine"], + ); + }); + + QUnit.test("fetch parent record", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + domain: [["id", "=", 4]], // simulate a search + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.containsN(target, ".o_hierarchy_separator", 1); + let rows = target.querySelectorAll(".o_hierarchy_row"); + let row = rows[0]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "JosephineAlbert"); + row = rows[1]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "LouisJosephine"); + assert.containsOnce( + target, + ".o_hierarchy_node_container button .fa-chevron-up", + "Button to fetch the parent node should be visible on the first node displayed in the view." + ); + await click(target, ".o_hierarchy_node_container button .fa-chevron-up"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.containsN(target, ".o_hierarchy_separator", 2); + rows = target.querySelectorAll(".o_hierarchy_row"); + row = rows[0]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "Albert"); + row = rows[1]; + assert.containsN(row, ".o_hierarchy_node", 2); + assert.deepEqual( + getNodesTextContent(row.querySelectorAll(".o_hierarchy_node_content")), + ["GeorgesAlbert", "JosephineAlbert"], + ); + row = rows[2]; + assert.containsOnce(row, ".o_hierarchy_node"); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "LouisJosephine"); + }); + + QUnit.test("fetch parent when there are many records without the same parent in the same row", async function (assert) { + serverData.models["hr.employee"].records.push( + { id: 5, name: "Lisa", parent_id: 2, child_ids: []}, + ); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + domain: [["name", "ilike", "l"]], // simulate a search + }); + assert.containsOnce(target, ".o_hierarchy_row"); + assert.containsN(target, ".o_hierarchy_node_container", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + [ + "LisaGeorges", "LouisJosephine", "Albert", + ], + ); + assert.containsN(target, ".o_hierarchy_node_container button .fa-chevron-up", 2); + const firstNode = target.querySelector(".o_hierarchy_node_container"); + await click(firstNode, ".o_hierarchy_node_container button .fa-chevron-up"); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + [ + "GeorgesAlbert", "LisaGeorges", + ], + ); + assert.containsOnce(target, ".o_hierarchy_node_container button .fa-chevron-up"); + await click(target, ".o_hierarchy_node_container button .fa-chevron-up"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + }); + + QUnit.test("fetch parent when parent record is in the same row", async function (assert) { + serverData.models["hr.employee"].records.push( + { id: 5, name: "Lisa", parent_id: 2, child_ids: []}, + ); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + domain: [["id", "in", [1, 2, 3, 4, 5]]], // simulate a search + }); + assert.containsOnce(target, ".o_hierarchy_row"); + assert.containsN(target, ".o_hierarchy_node_container", 5); + assert.containsN(target, ".o_hierarchy_node_container button .fa-chevron-up", 4); + const firstNodeWithParentBtn = target.querySelector(".o_hierarchy_node_container:has(button .fa-chevron-up)"); + await click(firstNodeWithParentBtn, ".o_hierarchy_node_container button .fa-chevron-up"); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + [ + "Albert", "GeorgesAlbert", "JosephineAlbert", + ], + ); + }); + + QUnit.test("fetch parent of node with children displayed", async function (assert) { + serverData.models["hr.employee"].records.push( + { id: 5, name: "Lisa", parent_id: 2, child_ids: []}, + ); + serverData.models["hr.employee"].records.find((rec) => rec.id === 2).child_ids.push(5); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + domain: [["id", "in", [1, 2, 3, 4, 5]]], // simulate a search + }); + assert.containsOnce(target, ".o_hierarchy_row"); + assert.containsN(target, ".o_hierarchy_node_container", 5); + assert.containsN(target, ".o_hierarchy_node_container button .fa-chevron-up", 4); + const georgesNode = target.querySelector(".o_hierarchy_node_container:has(button[name=hierarchy_search_parent_node])"); + assert.strictEqual(georgesNode.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + await click(georgesNode, "button[name=hierarchy_search_subsidiaries]"); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 5); + const rows = target.querySelectorAll(".o_hierarchy_row"); + let row = rows[0]; + assert.containsN(row, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(row.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisJosephine"], + ); + row = rows[1]; + assert.containsN(row, ".o_hierarchy_node", 1); + assert.strictEqual(row.querySelector(".o_hierarchy_node_content").textContent, "LisaGeorges"); + const firstNodeWithParentBtn = target.querySelector(".o_hierarchy_node_container:has(button .fa-chevron-up)"); + await click(firstNodeWithParentBtn, ".o_hierarchy_node_container button .fa-chevron-up"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + }); + + QUnit.test("drag and drop is disabled by default", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + + await dragAndDrop( + georgesNodeContainer.querySelector(".o_hierarchy_node"), + ".o_hierarchy_row:first-child" + ); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + }); + + QUnit.test("drag and drop record on another row", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + + await dragAndDrop( + georgesNodeContainer.querySelector(".o_hierarchy_node"), + ".o_hierarchy_row:first-child" + ); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "Georges", "JosephineAlbert"], + "Georges should no longer have a manager" + ); + }); + + QUnit.test("drag and drop record on sibling node", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + const josephineNodeContainer = nodeContainers[2]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + assert.strictEqual(josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "JosephineAlbert"); + + await dragAndDrop( + georgesNodeContainer.querySelector(".o_hierarchy_node"), + josephineNodeContainer, + ); + + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "JosephineAlbert", "LouisJosephine", "GeorgesJosephine"], + "Georges should have Josephine as manager" + ); + }); + + QUnit.test("drag and drop record on node of another tree", async function (assert) { + serverData.views["hr.employee,1,hierarchy"] = serverData.views[ + "hr.employee,1,hierarchy" + ].replace(``, ``); + serverData.models["hr.employee"].records = [ + { id: 1, name: "A", parent_id: false, child_ids: [3, 4] }, + { id: 2, name: "B", parent_id: false, child_ids: [] }, + { id: 3, name: "C", parent_id: 1, child_ids: [5] }, + { id: 4, name: "D", parent_id: 1, child_ids: [] }, + { id: 5, name: "E", parent_id: 3, child_ids: [] }, + ]; + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + viewId: 1, + }); + + assert.containsN(target, ".o_hierarchy_row", 1); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 2); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + let rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual(getNodesTextContent(rowsContent), ["A", "B", "CA", "DA", "EC"]); + + let nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const bNode = nodeContainers[1]; + const dNode = nodeContainers[3]; + assert.strictEqual(bNode.querySelector(".o_hierarchy_node_content").textContent, "B"); + assert.strictEqual(dNode.querySelector(".o_hierarchy_node_content").textContent, "DA"); + + await dragAndDrop( + dNode.querySelector(".o_hierarchy_node"), + bNode, + ); + + assert.containsN(target, ".o_hierarchy_row", 2); + rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual(getNodesTextContent(rowsContent), ["A", "B", "DB"]); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const aNode = nodeContainers[0]; + assert.strictEqual(aNode.querySelector(".o_hierarchy_node_content").textContent, "A"); + + await click(aNode, ".o_hierarchy_node_button.btn-primary"); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const cNode = nodeContainers[2]; + assert.strictEqual(cNode.querySelector(".o_hierarchy_node_content").textContent, "CA"); + + await click(cNode, ".o_hierarchy_node_button.btn-primary"); + + rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual( + getNodesTextContent(rowsContent), + ["A", "B", "CA", "EC"], + "Nodes that were folded as a result of the drop operation should all still be unfoldable" + ); + }); + + QUnit.test("drag and drop node unfolded on first row", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + + let nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const josephineNodeContainer = nodeContainers[2]; + assert.strictEqual(josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "JosephineAlbert"); + await click(josephineNodeContainer, "button[name='hierarchy_search_subsidiaries']"); + + await dragAndDrop( + josephineNodeContainer.querySelector(".o_hierarchy_node"), + ".o_hierarchy_row:first-child" + ); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "Josephine", "LouisJosephine"], + "Georges should have Josephine as manager" + ); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const louisNodeContainer = nodeContainers[2]; + assert.strictEqual( + louisNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "LouisJosephine" + ); + + await dragAndDrop( + louisNodeContainer.querySelector(".o_hierarchy_node"), + ".o_hierarchy_row:first-child" + ); + + assert.containsN(target, ".o_hierarchy_row", 1); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "Josephine", "Louis"], + "Louis should still be draggable after being dragged along with Josephine" + ); + }); + + QUnit.test("drag and drop node when other node is unfolded on first row", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"], + ); + + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + const josephineNodeContainer = nodeContainers[2]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + assert.strictEqual(josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "JosephineAlbert"); + await click(josephineNodeContainer, "button[name='hierarchy_search_subsidiaries']"); + + await dragAndDrop( + georgesNodeContainer.querySelector(".o_hierarchy_node"), + ".o_hierarchy_row:first-child" + ); + + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "Georges", "JosephineAlbert", "LouisJosephine"], + "Georges should no longer have a manager" + ); + }); + + QUnit.test("drag and drop node unfolded on another row", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views[ + "hr.employee,false,hierarchy" + ].replace("", ""); + serverData.models["hr.employee"].records = [ + { id: 1, name: "Albert", parent_id: false, child_ids: [2] }, + { id: 2, name: "Georges", parent_id: 1, child_ids: [3] }, + { id: 3, name: "Josephine", parent_id: 2, child_ids: [4] }, + { id: 4, name: "Louis", parent_id: 3, child_ids: [] }, + { id: 5, name: "Kelly", parent_id: 2, child_ids: [] }, + ]; + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 2); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert"] + ); + + let nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgeNodeContainer = nodeContainers[1]; + assert.strictEqual( + georgeNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "GeorgesAlbert" + ); + await click(georgeNodeContainer, "button[name='hierarchy_search_subsidiaries']"); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + let josephineNodeContainer = nodeContainers[2]; + assert.strictEqual( + josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "JosephineGeorges" + ); + await click(josephineNodeContainer, "button[name='hierarchy_search_subsidiaries']"); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + josephineNodeContainer = nodeContainers[2]; + assert.strictEqual( + josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "JosephineGeorges" + ); + let louisNodeContainer = nodeContainers[4]; + assert.strictEqual( + louisNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "LouisJosephine" + ); + assert.containsN(target, ".o_hierarchy_row", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineGeorges", "KellyGeorges", "LouisJosephine"], + "Kelly should be displayed" + ); + + await dragAndDrop( + josephineNodeContainer.querySelector(".o_hierarchy_node"), + ":nth-child(2 of .o_hierarchy_row)" + ); + + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisJosephine"], + "Josephine should have Albert as a manager and Kelly should be hidden" + ); + + nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + louisNodeContainer = nodeContainers[3]; + assert.strictEqual( + louisNodeContainer.querySelector(".o_hierarchy_node_content").textContent, + "LouisJosephine" + ); + + await dragAndDrop( + louisNodeContainer.querySelector(".o_hierarchy_node"), + ":nth-child(2 of .o_hierarchy_row)" + ); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisAlbert"], + "Louis should still be draggable after being dragged along with Josephine" + ); + }); + + QUnit.test("drag and drop node as a child of a sibling of its parent", async function (assert) { + serverData.views["hr.employee,1,hierarchy"] = serverData.views[ + "hr.employee,1,hierarchy" + ].replace(``, ``); + serverData.models["hr.employee"].records = [ + { id: 1, name: "A", parent_id: false, child_ids: [2, 3] }, + { id: 2, name: "B", parent_id: 1, child_ids: [4, 5] }, + { id: 3, name: "C", parent_id: 1, child_ids: [] }, + { id: 4, name: "D", parent_id: 2, child_ids: [] }, + { id: 5, name: "E", parent_id: 2, child_ids: [] }, + ]; + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + viewId: 1, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + let rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual(getNodesTextContent(rowsContent), ["A", "BA", "CA", "DB", "EB"]); + + let nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const cNode = nodeContainers[2]; + const eNode = nodeContainers[4]; + assert.strictEqual(cNode.querySelector(".o_hierarchy_node_content").textContent, "CA"); + assert.strictEqual(eNode.querySelector(".o_hierarchy_node_content").textContent, "EB"); + + await dragAndDrop( + eNode.querySelector(".o_hierarchy_node"), + cNode, + ); + assert.containsN(target, ".o_hierarchy_row", 3); + rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual( + getNodesTextContent(rowsContent), ["A", "BA", "CA", "EC"], + "B should be folded and C unfolded" + ); + }); + + QUnit.test("drag node and move it on a row", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsN(target, ".o_hierarchy_node", 3); + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + + const { drop, moveTo } = await drag(georgesNodeContainer.querySelector(".o_hierarchy_node")); + + await moveTo(".o_hierarchy_row:first-child"); + assert.hasClass(georgesNodeContainer, "o_hierarchy_dragged"); + assert.hasClass(target.querySelector(".o_hierarchy_row"), "o_hierarchy_hover"); + + await drop(); + assert.containsNone(target, ".o_hierarchy_node.o_hierarchy_dragged"); + assert.containsNone(target, ".o_hierarchy_row.o_hierarchy_hover"); + }); + + QUnit.test("drag node and move it on another node", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsN(target, ".o_hierarchy_node", 3); + const nodeContainers = target.querySelectorAll(".o_hierarchy_node_container"); + const georgesNodeContainer = nodeContainers[1]; + const josephineNodeContainer = nodeContainers[2]; + assert.strictEqual(georgesNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "GeorgesAlbert"); + assert.strictEqual(josephineNodeContainer.querySelector(".o_hierarchy_node_content").textContent, "JosephineAlbert"); + + const { drop, moveTo } = await drag(georgesNodeContainer.querySelector(".o_hierarchy_node")); + + await moveTo(josephineNodeContainer.querySelector(".o_hierarchy_node")); + assert.hasClass(georgesNodeContainer, "o_hierarchy_dragged"); + assert.hasClass(georgesNodeContainer.querySelector(".o_hierarchy_node"), "shadow"); + assert.hasClass(josephineNodeContainer, "o_hierarchy_hover"); + + await drop(); + assert.containsNone(target, ".o_hierarchy_node.o_hierarchy_dragged"); + assert.containsNone(target, ".o_hierarchy_node.o_hierarchy_hover"); + assert.containsNone(target, ".o_hierarchy_node.shadow"); + }); + + QUnit.test("drag node to scroll", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views[ + "hr.employee,false,hierarchy" + ].replace("", ""); + serverData.models["hr.employee"].records = [ + { id: 1, name: "A", parent_id: false, child_ids: [2] }, + { id: 2, name: "B", parent_id: 1, child_ids: [3] }, + { id: 3, name: "C", parent_id: 2, child_ids: [4] }, + { id: 4, name: "D", parent_id: 3, child_ids: [5] }, + { id: 5, name: "E", parent_id: 4, child_ids: [] }, + { id: 6, name: "F", parent_id: false, child_ids: [] }, + ]; + const { advanceFrame } = mockAnimationFrame(); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + // Fully open the view + assert.containsN(target, ".o_hierarchy_row", 1); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 2); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 4); + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 5); + const rowsContent = target.querySelectorAll(".o_hierarchy_row .o_hierarchy_node_content"); + assert.deepEqual(getNodesTextContent(rowsContent), ["A", "F", "BA", "CB", "DC", "ED"]); + await nextTick(); + + // Limit the height and enable scrolling + const content = target.querySelector(".o_content"); + content.setAttribute("style", "min-height:600px;max-height:600px;overflow-y:auto;"); + assert.strictEqual(content.scrollTop, 0); + assert.strictEqual(content.getBoundingClientRect().height, 600); + + const nodes = [...content.querySelectorAll(".o_hierarchy_node")]; + const fNode = nodes.find((n) => n.textContent === "F"); + const dragActions = await drag(fNode); + await dragActions.moveTo(".o_hierarchy_row:last-child"); + assert.strictEqual(content.scrollTop, 0); + + await advanceFrame(); + + // default speed of 20px per frame + assert.strictEqual(content.scrollTop, 20); + assert.containsOnce(target, ".o_hierarchy_node_container.o_hierarchy_dragged"); + + // next 100 frames (2000px of scrolling) + await advanceFrame(100); + + // should be at the end of the content + assert.strictEqual(content.clientHeight + content.scrollTop, content.scrollHeight); + + await dragActions.moveTo(".o_hierarchy_row:first-child"); + assert.strictEqual(content.clientHeight + content.scrollTop, content.scrollHeight); + + await advanceFrame(); + + // default speed of 20px per frame + assert.strictEqual(content.clientHeight + content.scrollTop, content.scrollHeight - 20); + assert.containsOnce(target, ".o_hierarchy_node_container.o_hierarchy_dragged"); + + // next 100 frames (2000px of scrolling) + await advanceFrame(100); + + // should be at the top of the content + assert.strictEqual(content.scrollTop, 0); + + // cancel drag: press "Escape" + triggerHotkey("Escape"); + await nextTick(); + + assert.containsNone(target, ".o_hierarchy_node_container.o_hierarchy_dragged"); + }); + + QUnit.test("check default icon is correctly used inside button to display child nodes", async function (assert) { + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsOnce(target, ".o_hierarchy_node button[name=hierarchy_search_subsidiaries].btn-primary"); + assert.strictEqual(target.querySelector(".o_hierarchy_node button[name=hierarchy_search_subsidiaries].btn-primary").textContent.trim(), "Unfold 1"); + assert.containsOnce( + target, + ".o_hierarchy_node button[name=hierarchy_search_subsidiaries] i.fa-share-alt.o_hierarchy_icon", + "The default icon of the hierarchy view should be displayed inside the button to unfold the node." + ); + }); + + QUnit.test("use other icon used next to Unfold string displayed inside the button", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + }); + + assert.containsOnce(target, ".o_hierarchy_node button[name=hierarchy_search_subsidiaries].btn-primary"); + assert.strictEqual(target.querySelector(".o_hierarchy_node button[name=hierarchy_search_subsidiaries].btn-primary").textContent.trim(), "Unfold 1"); + assert.containsOnce( + target, + ".o_hierarchy_node button[name=hierarchy_search_subsidiaries] i.fa-users", + "The icon defined in the attribute icon in hierarchy tag should be displayed inside the button to unfold the node instead of the default one." + ); + }); + + QUnit.test("use `hierarchy_res_id` context to load the view at that specific node with its siblings and parent node", async function (assert) { + serverData.models["hr.employee"].records.push( + { id: 5, name: "Lisa", parent_id: 3, child_ids: []}, + ); + serverData.models["hr.employee"].records.find((rec) => rec.id === 3).child_ids.push(5); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + context: { + hierarchy_res_id: 5, + }, + }); + + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["JosephineAlbert", "LisaJosephine", "LouisJosephine"] + ); + assert.containsOnce(target, ".o_hierarchy_node_container button[name=hierarchy_search_parent_node]"); + }); + + QUnit.test("cannot set the record dragged as parent", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + mockRPC(route, { method, model }) { + if (method === "write" && model === "hr.employee") { + assert.step("setManager"); + } + }, + }); + + patchWithCleanup(browser, { + setTimeout: () => 1, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"] + ); + const rows = target.querySelectorAll(".o_hierarchy_row"); + await dragAndDrop( + target.querySelector(".o_hierarchy_node"), // select first node (Albert) + rows[1] + ); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"] + ); + assert.containsOnce(target, ".o_notification"); + assert.containsOnce(target, ".o_notification.border-danger"); + + assert.verifySteps([]); + }); + + QUnit.test("cannot create cyclic", async function (assert) { + serverData.views["hr.employee,false,hierarchy"] = serverData.views["hr.employee,false,hierarchy"].replace("", ""); + await makeView({ + type: "hierarchy", + resModel: "hr.employee", + serverData, + mockRPC(route, { method, model }) { + if (method === "write" && model === "hr.employee") { + assert.step("setManager"); + } + }, + }); + + patchWithCleanup(browser, { + setTimeout: () => 1, + }); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"] + ); + let nodes = target.querySelectorAll(".o_hierarchy_node"); + await dragAndDrop( + nodes[0], // albert node + nodes[1] // georges node + ); + assert.containsN(target, ".o_hierarchy_row", 2); + assert.containsN(target, ".o_hierarchy_node", 3); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert"] + ); + assert.containsOnce(target, ".o_notification"); + assert.containsOnce(target, ".o_notification.border-danger"); + + await click(target, ".o_hierarchy_node_button.btn-primary"); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisJosephine"] + ); + nodes = target.querySelectorAll(".o_hierarchy_node"); + await dragAndDrop( + nodes[0], + nodes[3] + ); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisJosephine"] + ); + assert.containsN(target, ".o_notification", 2); + assert.containsN(target, ".o_notification.border-danger", 2); + + const rows = target.querySelectorAll(".o_hierarchy_row"); + await dragAndDrop( + nodes[0], + rows[2] + ); + assert.containsN(target, ".o_hierarchy_row", 3); + assert.containsN(target, ".o_hierarchy_node", 4); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_hierarchy_node_content")), + ["Albert", "GeorgesAlbert", "JosephineAlbert", "LouisJosephine"] + ); + assert.containsN(target, ".o_notification", 3); + assert.containsN(target, ".o_notification.border-danger", 3); + + assert.verifySteps([]); + }); +}); diff --git a/static/tests/mock_server.js b/static/tests/mock_server.js new file mode 100644 index 0000000..d047ebc --- /dev/null +++ b/static/tests/mock_server.js @@ -0,0 +1,78 @@ +/** @odoo-module **/ + +import { patch } from "@web/core/utils/patch"; +import { MockServer } from "@web/../tests/helpers/mock_server"; + +patch(MockServer.prototype, { + async _performRPC(route, args) { + if (args.method === "hierarchy_read") { + return this.mockHierarchyRead(args.model, args.args, args.kwargs); + } + return super._performRPC(route, args); + }, + + mockHierarchyRead(modelName, args, kwargs) { + const [domain, fields, parentFieldName, childFieldName] = args; + if (!(parentFieldName in fields)) { + fields.push(parentFieldName); + } + let records = this.mockSearchRead(modelName, [domain, fields], kwargs); + let focusedRecordId = false; + let fetchChildIdsForAllRecords = false; + if (records.length === 1) { + const record = records[0]; + let domain = [[parentFieldName, "=", record.id], ["id", "!=", record.id]]; + if (record[parentFieldName]) { + focusedRecordId = record.id; + const parentResId = record[parentFieldName][0]; + domain = [ + ["id", "!=", record.id], + "|", + ["id", "=", parentResId], + [parentFieldName, "in", [parentResId, record.id]], + ]; + } + records.push(...this.mockSearchRead(modelName, [domain, fields], kwargs)); + } else if (!records.length) { + records = this.mockSearchRead( + modelName, + [ + [[parentFieldName, "=", false]], + fields, + ], + kwargs, + ); + } else { + fetchChildIdsForAllRecords = true + } + const childrenIdsPerRecordId = {}; + if (!childFieldName) { + const parentResIds = []; + for (const rec of records) { + if (rec[parentFieldName]) { + parentResIds.push(rec[parentFieldName][0]); + } + } + const recordIds = records.map((rec) => rec.id); + const data = this.mockReadGroup(modelName, { + domain: [[parentFieldName, "in", fetchChildIdsForAllRecords ? recordIds : recordIds.filter((id) => !parentResIds.includes(id))]], + groupby: [parentFieldName], + fields: ["id:array_agg"], + }); + for (const d of data) { + childrenIdsPerRecordId[d[parentFieldName][0]] = d.id; + } + } + if (focusedRecordId || Object.keys(childrenIdsPerRecordId).length) { + for (const record of records) { + if (record.id in childrenIdsPerRecordId) { + record.__child_ids__ = childrenIdsPerRecordId[record.id]; + } + if (record.id === focusedRecordId) { + record.__focus__ = true; + } + } + } + return records; + }, +})