合并企业版代码(未测试,先提交到测试分支)

This commit is contained in:
qihao.gong@jikimo.com
2023-04-14 17:42:23 +08:00
parent 7a7b3d7126
commit d28525526a
1300 changed files with 513579 additions and 5426 deletions

4
web_gantt/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models

32
web_gantt/__manifest__.py Normal file
View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Web Gantt',
'category': 'Hidden',
'description': """
Odoo Web Gantt chart view.
=============================
""",
'version': '2.0',
'depends': ['web'],
'assets': {
'web._assets_primary_variables': [
'web_gantt/static/src/scss/web_gantt.variables.scss',
],
'web.assets_backend': [
'web_gantt/static/src/**/*',
'web_gantt/static/src/xml/**/*',
],
'web.qunit_suite_tests': [
'web_gantt/static/tests/**/*',
('remove', 'web_gantt/static/tests/gantt_mobile_tests.js'),
],
'web.qunit_mobile_suite_tests': [
'web_gantt/static/tests/gantt_mobile_tests.js',
],
},
'auto_install': True,
'license': 'OEEL-1',
}

274
web_gantt/i18n/ar.po Normal file
View File

@@ -0,0 +1,274 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Malaz Abuidris <msea@odoo.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Arabic (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "إضافة"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "إضافة سجل "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "هل أنت متأكد من أنك ترغب في حذف هذا السجل؟ "
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "أساس"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "تصغير الصفوف "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "إنشاء"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "اليوم"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "تكبير الصفوف "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "جانت"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "أداة عرض جانت"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "يمكن أن يكون تابع غانت إما حقل أو قالب فقط، به %s "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "يجب أن يكون لعرض غانت خاصية 'date_start' "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "يجب أن يكون لعرض غانت خاصية 'date_stop' "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "يمكن أن يحتوي عرض غانت على علامة تصنيف قوالب واحدة فقط "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "خاصية التجميع حسب التاريخ غير مدعومة "
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "لا توجد حقول كافية لعرض غانت! "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr "خواص غير صالحة (%s) في عرض غانت. يجب أن تكون الخواص في (%s) "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "default_scale '%s' غير صالح في عرض غانت "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "الشهر"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "الاسم:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "التالي"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "فتح"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "الخطة "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "تخطيط الموجود "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "السابق"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "بدء: "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "إيقاف: "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "اليوم"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "غير محدد %s "
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "عرض "
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "الأسبوع"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "السنة"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

274
web_gantt/i18n/az.po Normal file
View File

@@ -0,0 +1,274 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Jumshud Sultanov <cumshud@gmail.com>, 2022
# erpgo translator <jumshud@erpgo.az>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: erpgo translator <jumshud@erpgo.az>, 2022\n"
"Language-Team: Azerbaijani (https://www.transifex.com/odoo/teams/41243/az/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: az\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Əlavə edin"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Baza"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Yaradın"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Gün"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gant"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Ay"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Ad:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Açın"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Bu gün"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Baxın"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "İL"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

278
web_gantt/i18n/ca.po Normal file
View File

@@ -0,0 +1,278 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# M Palau <mpalau@tda.ad>, 2022
# marcescu, 2022
# jabelchi, 2022
# Martin Trigaux, 2022
# Manel Fernandez Ramirez <manelfera@outlook.com>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Manel Fernandez Ramirez <manelfera@outlook.com>, 2022\n"
"Language-Team: Catalan (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Afegir"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Afegeix un registre"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "¿Està segur d'eliminar aquest registre?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Col·lapsar files"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Crear"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dia"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Expandeix les files"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gràfic de Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vista Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "El fill de Gantt només pot ser un camp o una plantilla, té %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt ha de tenir un atribut 'date_start'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt ha de tenir un atribut \"date_stop\"."
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "La vista de Gantt només pot contenir una etiqueta de plantilles"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "L'agrupament per data no és compatible"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "¡Camps insuficients per a la vista de Gantt!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Atributs no vàlids (%s) a la vista gantt. Els atributs han d'estar a (%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Escala_per defecte invàlida '%s'a gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nom:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Següent"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Oberts"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Pla"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Pla existent"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Anterior"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Comença:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Atura:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Avui"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "No definit %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Vista"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Setmana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Any"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

276
web_gantt/i18n/cs.po Normal file
View File

@@ -0,0 +1,276 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# karolína schusterová <karolina.schusterova@vdp.sk>, 2022
# Michal Veselý <michal@veselyberanek.net>, 2022
# trendspotter <jirka.p@volny.cz>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Czech (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Přidat"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Přidat záznam"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Opravdu chcete tento záznam smazat?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Základní část"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Sbalit řádky"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Vytvořit"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Den"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Rozbalte řádky"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantův diagram"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Seskupování podle data není podporováno"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Měsíc"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Název:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Další"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Otevřít"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plán"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Předchozí"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Dnes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Pohled"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Týden"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Rok"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

204
web_gantt/i18n/da.po Normal file
View File

@@ -0,0 +1,204 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Kenneth Hansen <kenneth@vkdata.dk>, 2019
# Sanne Kristensen <sanne@vkdata.dk>, 2019
# Ejner Sønniksen <ejner@vkdata.dk>, 2019
# lhmflexerp <lhm@flexerp.dk>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: lhmflexerp <lhm@flexerp.dk>, 2019\n"
"Language-Team: Danish (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Tilføj"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Basis"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Opret"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt visning"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Måned"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Navn:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Næste"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Åben"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Planlæg"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Forrige"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "I dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Uge"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "År"

275
web_gantt/i18n/de.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: German (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Hinzufügen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Datensatz hinzufügen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Sind Sie sicher, dass Sie diesen Datensatz löschen wollen?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Basis"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Zeilen ausblenden"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Anlegen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Tag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Zeilen erweitern"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt-Ansicht"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt muss ein 'date_stop'-Attribut haben"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Gruppierung nach Datum wird nicht unterstützt"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Unzureichende Felder für die Gantt-Ansicht!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Ungültige Attribute (%s) in der Gantt-Ansicht. Attribute müssen in (%s) "
"stehen."
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Monat"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Name:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Weiter"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Offen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Planung"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Bestehender Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Zurück"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Start:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Stop:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Heute"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Undefiniert %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Ansicht"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Woche"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Jahr"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

181
web_gantt/i18n/el.po Normal file
View File

@@ -0,0 +1,181 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Kostas Goutoudis <goutoudis@gmail.com>, 2019
# Giota Dandidou <giotadandidou@gmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.2+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-20 14:08+0000\n"
"PO-Revision-Date: 2016-08-05 13:32+0000\n"
"Last-Translator: Giota Dandidou <giotadandidou@gmail.com>, 2019\n"
"Language-Team: Greek (https://www.transifex.com/odoo/teams/41243/el/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:6
#, python-format
msgid "Add"
msgstr "Προσθήκη"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:6
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Βάση"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:27
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:123
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:76
#, python-format
msgid "Create"
msgstr "Δημιουργία"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:32
#, python-format
msgid "Day"
msgstr "Ημέρα"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:24
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:16
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:143
#, python-format
msgid "Gantt View"
msgstr "Προβολή Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:34
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:34
#, python-format
msgid "Month"
msgstr "Μήνας"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:119
#, python-format
msgid "Name:"
msgstr "Όνομα:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:16
#, python-format
msgid "Next"
msgstr "Επόμενο"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:123
#, python-format
msgid "Open"
msgstr "Ανοιχτό"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:150
#, python-format
msgid "Plan"
msgstr "Σχεδίασε"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:77
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:10
#, python-format
msgid "Previous"
msgstr "Προηγούμενο"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:120
#, python-format
msgid "Start Date:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:121
#, python-format
msgid "Stop Date:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:13
#, python-format
msgid "Today"
msgstr "Σήμερα"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:420
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:33
#, python-format
msgid "Week"
msgstr "Εβδομάδα"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:35
#, python-format
msgid "Year"
msgstr "Έτος"

275
web_gantt/i18n/es.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Spanish (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Añadir"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Agregar registro"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "¿Está seguro que quiere eliminar este registro?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Colapsar filas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Crear"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Día"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Expandir filas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vista Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "Gantt hijo solo puede ser campo o plantilla, obtuvo %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt debe tener un atributo \"date_start\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt debe tener un atributo \"date_stopt\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "La vista de Gantt solo puede contener una etiqueta de plantilla"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "No se puede agrupar por fecha"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "¡Campos insuficientes para la vista de Gantt!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Atributos no válidos (%s) en la vista gantt. Los atributos deben estar en "
"(%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Default_scale '%s' no válida en vista gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nombre:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Siguiente"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Abierto"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Plan existente"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Anterior"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Iniciar:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Parar:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Hoy"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Indefinida %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Ver"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Semana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Año"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

280
web_gantt/i18n/es_MX.po Normal file
View File

@@ -0,0 +1,280 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
# Lucia Pacheco <lpo@odoo.com>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Lucia Pacheco <lpo@odoo.com>, 2022\n"
"Language-Team: Spanish (Mexico) (https://www.transifex.com/odoo/teams/41243/es_MX/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: es_MX\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Agregar"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Agregar registro"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "¿Estás seguro de que desea eliminar este registro?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Contraer filas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Crear"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Día"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Expandir filas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vista de gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "Gantt hijo solo puede ser campo o plantilla, obtuvo %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt debe tener un atributo \"date_start\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt debe tener un atributo \"date_stopt\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
"Gantt debe tener un atributo 'dependency_inverted_field' cuando se "
"especifique el campo 'dependency_field'."
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "La vista de Gantt solo puede contener una etiqueta de plantilla"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "No se puede agrupar por fecha"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Campos insuficientes para la vista de Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Atributos no válidos (%s) en la vista gantt. Los atributos deben estar en "
"(%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Default_scale '%s' no válida en vista gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nombre:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Siguiente"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Abierto"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Plan existente"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Anterior"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Empezar:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Parar:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Hoy"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Indefinida %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Ver"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Semana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Año"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr "No puede reprogramar %s a %s"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""
"No se pueden reprogramar tareas que no sigan una ruta de dependencia "
"directa. Solo se ha reprogramado de forma automática la primera tarea."

286
web_gantt/i18n/fr.po Normal file
View File

@@ -0,0 +1,286 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
# Cécile Collart <cco@odoo.com>, 2022
# Jolien De Paepe, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Jolien De Paepe, 2022\n"
"Language-Team: French (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Ajouter"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Ajouter un enregistrement"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Êtes-vous sûr de vouloir supprimer cet enregistrement ?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Plier les lignes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Créer"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Jour"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Déplier les lignes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vue de Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
"Une ligne enfant Gantt peut seulement être un champ ou un modèle, vous avez "
"%s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt doit avoir un attribut 'date_start'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt doit avoir un attribut 'date_stop'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
"Gant doit avoir un attribut 'dependency_inverted_field' dys que le "
"'dependency_field' est défini"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "La vue Gantt peut uniquement contenir une étiquette de modèles"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Grouper par date n'est pas pris en charge."
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Champs insuffisants pour Vue Gantt !"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Des attributs non valides (%s) dans la vue Gantt. Les attributs doivent être"
" en (%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "default_scale '%s' non valide dans le gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mois"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nom :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Suivant"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Ouvertes"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Plan existant"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Précedent"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
"Les enregistrements passés ne peuvent pas être automatiquement reprogrammés."
" Ils doivent être reprogrammés manuellement."
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Début :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Stop :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Aujourd'hui"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "%s indéfini"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Vue"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Semaine"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Année"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr "Vous ne pouvez pas repousser %s à %s."
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""
"Vous ne pouvez pas reprogrammer des tâches qui ne suivent pas une "
"trajectoire de dépendance directe. Seule la première tâche a été "
"automatiquement reprogrammée."

277
web_gantt/i18n/he.po Normal file
View File

@@ -0,0 +1,277 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Lilach Gilliam <lilach.gilliam@gmail.com>, 2022
# Yihya Hugirat <hugirat@gmail.com>, 2022
# שהאב חוסיין <shhab89@gmail.com>, 2022
# ZVI BLONDER <ZVIBLONDER@gmail.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Hebrew (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "ו"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "הוסף"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "הוסף רשומה"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "האם אתה בטוח שברצונך למחוק רשומה זו?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "בסיס"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "צמצם שורות"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "צור"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "יום"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "הרחב שורות"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "גאנט"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "תצוגת גאנט"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "גאנט מחייב הגדרת \"תאריך התחלה\":"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "גאנט מחייב הגדרת \"תאריך סיום\":"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "קיבוץ לפי תאריך אינו נתמך, הימנע מכך"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "אין מספיק שדות לתצוגת גאנט!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "חודש"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "שם:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "הבא"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "פתח"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "תוכנית"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "תכנון קיים"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "קודם"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "התחל:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "עצור:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "היום"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "%s לא מוגדר"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "תצוגה"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "שבוע"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "שנה"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

203
web_gantt/i18n/hr.po Normal file
View File

@@ -0,0 +1,203 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Bole <bole@dajmi5.com>, 2019
# Vladimir Olujić <olujic.vladimir@storm.hr>, 2019
# Karolina Tonković <karolina.tonkovic@storm.hr>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: Karolina Tonković <karolina.tonkovic@storm.hr>, 2019\n"
"Language-Team: Croatian (https://www.transifex.com/odoo/teams/41243/hr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: hr\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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Dodaj"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Osnovica"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Kreiraj"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantogram"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantogram"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mjesec"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Naziv:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Sljedeći"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Otvori"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Prethodni"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Danas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Tjedan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Godina"

202
web_gantt/i18n/hu.po Normal file
View File

@@ -0,0 +1,202 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# krnkris, 2019
# gezza <geza.nagy@oregional.hu>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: gezza <geza.nagy@oregional.hu>, 2019\n"
"Language-Team: Hungarian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Hozzáadás"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Alap"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Létrehozás"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Nap"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt nézet"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Hónap"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Név:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Következő"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Megnyitás"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Terv"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Ma"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Hét"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Év"

275
web_gantt/i18n/id.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
# Wahyu Setiawan <wahyusetiaaa@gmail.com>, 2022
# Bonny Useful <bonny.useful@gmail.com>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Bonny Useful <bonny.useful@gmail.com>, 2022\n"
"Language-Team: Indonesian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Tambah"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Dasar"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Buat"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Hari"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Tampilan Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Bulan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nama:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Next"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Terbuka"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Rencana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Sebelum"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Hari Ini"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Tampilan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Pekan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Tahun"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

273
web_gantt/i18n/it.po Normal file
View File

@@ -0,0 +1,273 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Italian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Aggiungi"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Aggiungi record"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Eliminare veramente questo record?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Imponibile"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Crea"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Giorno"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Espandi righe"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vista Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt deve possedere un attributo \"date_start\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt deve possedere un attributo \"date_stop\""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Raggruppamento per data non supportato"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Campi non sufficienti per la vista Gantt."
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mese"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nome:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Succ"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Apri"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Pianificazione"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Precedente"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Inizio:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Stop:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Oggi"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "%s non definiti"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Vista"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Settimana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Anno"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

275
web_gantt/i18n/ja.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Ryoko Tsuda <ryoko@quartile.co>, 2022
# Martin Trigaux, 2022
# Noma Yuki, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Noma Yuki, 2022\n"
"Language-Team: Japanese (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "追加"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "レコードを追加します。"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "このレコードを削除してもよろしいですか?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "ベース"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "行を折りたたむ"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "作成"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "日"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "行を展開"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "ガント"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "ガントビュー"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "ガントのchildはフィールドまたはテンプレートのみにできますが、%sを取得しました"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "ガントには'date_start'属性が必要です"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "ガントには'date_stop'属性が必要です"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "ガントビューには、テンプレートタグを1つだけ含めることができます"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "日付によるグループ化はサポートされていません"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "ガントビューのフィールドが不十分です!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "ganttのdefault_scale '%s'が無効です"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "月"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "名称:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "次"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "オープン"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "計画"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "既存の計画"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "前"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "開始:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "終了:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "今日"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "未定義の%s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "ビュー"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "週"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "年"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

275
web_gantt/i18n/ko.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Seongseok Shin <shinss61@hotmail.com>, 2022
# Martin Trigaux, 2022
# JH CHOI <hwangtog@gmail.com>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: JH CHOI <hwangtog@gmail.com>, 2022\n"
"Language-Team: Korean (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "추가"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "레코드 추가하기"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "이 레코드를 삭제 하시겠습니까?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "행 축소"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "작성"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "일"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "행 확장"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "간트 차트"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "간트 차트 화면"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "간트 차트 화면에 대한 필드가 충분하지 않습니다!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "월"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "이름 :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "다음"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "열기"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "계획"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "기존 계획"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "이전"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "시작 :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "중지 :"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "오늘"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "정의되지 않은 %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "화면"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "주"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "년"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

196
web_gantt/i18n/lb.po Normal file
View File

@@ -0,0 +1,196 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Language-Team: Luxembourgish (https://www.transifex.com/odoo/teams/41243/lb/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: lb\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr ""

204
web_gantt/i18n/lt.po Normal file
View File

@@ -0,0 +1,204 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Audrius Palenskis <audrius.palenskis@gmail.com>, 2019
# Rolandas <info@paninfo.lt>, 2019
# Edgaras Kriukonis <edgaras@focusate.eu>, 2019
# Linas Versada <linaskrisiukenas@gmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: Linas Versada <linaskrisiukenas@gmail.com>, 2019\n"
"Language-Team: Lithuanian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Pridėti"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Bazė"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Sukurti"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Diena"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Ganto vaizdas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mėnuo"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Vardas:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Kitas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Atidaryti"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Suplanuoti"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Ankstesnis"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Šiandien"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Savaitė"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Metai"

201
web_gantt/i18n/mn.po Normal file
View File

@@ -0,0 +1,201 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Baskhuu Lodoikhuu <baskhuujacara@gmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: Baskhuu Lodoikhuu <baskhuujacara@gmail.com>, 2019\n"
"Language-Team: Mongolian (https://www.transifex.com/odoo/teams/41243/mn/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: mn\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Нэмэх"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Суурь"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Үүсгэх"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Өдөр"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Хүснэгтлэх"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Хүснэгтлэн харах"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Сар"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Нэр:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Дараах"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Нээлттэй"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Төлөвлөгөө"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Өмнөх"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Өнөөдөр"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Долоо хоног"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Жил"

274
web_gantt/i18n/nb.po Normal file
View File

@@ -0,0 +1,274 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Marius Stedjan <marius@stedjan.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Norwegian Bokmål (https://www.transifex.com/odoo/teams/41243/nb/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: nb\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Legg til"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Opprett"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt-visning"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Måned"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Navn:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Neste"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Åpen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Planlegg"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Tilbake"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "I dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Vis"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Uke"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "År"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

275
web_gantt/i18n/nl.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
# Erwin van der Ploeg <erwin@odooexperts.nl>, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Erwin van der Ploeg <erwin@odooexperts.nl>, 2022\n"
"Language-Team: Dutch (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Toevoegen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Voeg record toe"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Ben je zeker dat je dit record wilt verwijderen?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Basis"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Rijen inklappen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Aanmaken"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Rijen uitvouwen"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt weergave"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "Gantt-kind kan alleen een veld of sjabloon zijn, krijg %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt moet een 'date_start' kenmerk hebben"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt moet een 'date_stop' attribuut hebben"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "De Gantt-weergave kan slechts één sjabloon-label bevatten"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Groepeer op datum wordt niet ondersteund."
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Niet genoeg velden voor Gantt weergave!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Ongeldige kenmerken (%s) in Gantt-weergave. Kenmerken moeten zijn in (%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Ongeldige default_scale '%s' in gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Maand"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Naam:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Volgende"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Open"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Plan bestaande"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Vorige"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Start:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Stop:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Vandaag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Niet gedefinieerd %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Weergave"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Week"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Jaar"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

206
web_gantt/i18n/pl.po Normal file
View File

@@ -0,0 +1,206 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2019
# Grzegorz Grzelak <grzegorz.grzelak@openglobe.pl>, 2019
# Judyta Kaźmierczak <judyta.kazmierczak@openglobe.pl>, 2019
# Piotr Szlązak <szlazakpiotr@gmail.com>, 2019
# Marcin Młynarczyk <mlynarczyk@gmail.com>, 2019
# Monika Motyczyńska <m.monia@op.pl>, 2019
# Paweł Wodyński <pw@myodoo.pl>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: Paweł Wodyński <pw@myodoo.pl>, 2019\n"
"Language-Team: Polish (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "dodaj"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Baza"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Utwórz"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dzień"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Wykres Gantta"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Widok Gantta"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Miesiąc"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nazwa:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Następny"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Otwarta"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Poprzedni"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Dzisiaj"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Tydzień"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Rok"

196
web_gantt/i18n/pt.po Normal file
View File

@@ -0,0 +1,196 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Language-Team: Portuguese (https://www.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=2; plural=(n != 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr ""

205
web_gantt/i18n/pt_BR.po Normal file
View File

@@ -0,0 +1,205 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Rodrigo de Almeida Sottomaior Macedo <rmsolucoeseminformatic4@gmail.com>, 2019
# Martin Trigaux, 2019
# Marcel Savegnago <marcel.savegnago@gmail.com>, 2019
# Mateus Lopes <mateus1@gmail.com>, 2019
# grazziano <gra.negocia@gmail.com>, 2019
# Franciele Neiva <franciele.neiva@br.ey.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:39+0000\n"
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
"Last-Translator: Franciele Neiva <franciele.neiva@br.ey.com>, 2019\n"
"Language-Team: Portuguese (Brazil) (https://www.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=2; plural=(n > 1);\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Adicionar"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "base"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Criar"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Dia"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Visualização Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported, ignoring it"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Invalid group by"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Mês"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nome"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Próximo"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Aberto"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plano"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Anterior"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Hoje"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Semana"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Ano"

276
web_gantt/i18n/ro.po Normal file
View File

@@ -0,0 +1,276 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Foldi Robert <foldirobert@nexterp.ro>, 2022
# Hongu Cosmin <cosmin513@gmail.com>, 2022
# Dorin Hongu <dhongu@gmail.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Romanian (https://www.transifex.com/odoo/teams/41243/ro/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: ro\n"
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Adaugă"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Adăugare înregistrare"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Sigur doriți să ștergeți această înregistrare?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Baza"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Reduceți rândurile"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Creează"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Zi"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Extindere Rânduri"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Vizualizare Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Gruparea după dată nu este acceptată"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Luna"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Nume:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Înainte"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Afișare"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Plan"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Anterior"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Start:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Stop:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Astăzi"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Nedefinit %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Afișare"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Săptămână"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "An"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

275
web_gantt/i18n/ru.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Иван Дроздов <hiraetari@gmail.com>, 2022
# Сергей Шебанин <sergey@shebanin.ru>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Russian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Добавить"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Базовый"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Создать"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "День"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Диаграмма Ганта"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Диаграмма Ганта"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Месяц"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Имя:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Далее"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Открытые"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr " В план"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Назад"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Сегодня"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Осмотр"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Неделя"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Год"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

182
web_gantt/i18n/sv.po Normal file
View File

@@ -0,0 +1,182 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Kristoffer Grundström <hamnisdude@gmail.com>, 2019
# Martin Trigaux, 2019
# Anders Wallenquist <anders.wallenquist@vertel.se>, 2019
# Martin Wilderoth <martin.wilderoth@linserv.se>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.2+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-20 14:08+0000\n"
"PO-Revision-Date: 2016-08-05 13:32+0000\n"
"Last-Translator: Martin Wilderoth <martin.wilderoth@linserv.se>, 2019\n"
"Language-Team: Swedish (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:6
#, python-format
msgid "Add"
msgstr "Lägg till"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:6
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Bas"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:27
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:123
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:76
#, python-format
msgid "Create"
msgstr "Skapa"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:32
#, python-format
msgid "Day"
msgstr "Dag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:24
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:16
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:143
#, python-format
msgid "Gantt View"
msgstr "Ganttvy"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:34
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:34
#, python-format
msgid "Month"
msgstr "Månad"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:119
#, python-format
msgid "Name:"
msgstr "Namn:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:16
#, python-format
msgid "Next"
msgstr "Framåt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:123
#, python-format
msgid "Open"
msgstr "Öppna"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:150
#, python-format
msgid "Plan"
msgstr "Plannera"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:77
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:10
#, python-format
msgid "Previous"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:120
#, python-format
msgid "Start Date:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:121
#, python-format
msgid "Stop Date:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:13
#, python-format
msgid "Today"
msgstr "Idag"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:420
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:33
#, python-format
msgid "Week"
msgstr "Vecka"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:35
#, python-format
msgid "Year"
msgstr "År"

277
web_gantt/i18n/th.po Normal file
View File

@@ -0,0 +1,277 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Rockers <sumorock@hotmail.com>, 2022
# Khwunchai Jaengsawang <khwunchai.j@ku.th>, 2022
# Martin Trigaux, 2022
# Wichanon Jamwutthipreecha, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Wichanon Jamwutthipreecha, 2022\n"
"Language-Team: Thai (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "เพิ่ม"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "เพิ่มบันทึก"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "คุณแน่ใจหรือว่าต้องการลบบันทึกนี้?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "ฐาน"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "ย่อแถว"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "สร้าง"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "วัน"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "ขยายแถว"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "แกนต์"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "มุมมองแบบแกนต์"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "แกนต์ย่อยได้เฉพาะฟิลด์หรือเทมเพลตเท่านั้น มี %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "แกนต์ต้องมี 'date_start' แอตทริบิวต์ "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "แกนต์ต้องมี \"date_stop\" แอตทริบิวต์ "
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "มุมมองแกนต์สามารถมีแท็กเทมเพลตได้เพียงแท็กเดียว"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "ไม่รองรับการจัดกลุ่มตามวันที่"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "ฟิลด์ไม่เพียงพอสำหรับมุมมองแกนต์!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"แอตทริบิวต์ที่ไม่ถูกต้อง (%s) ในมุมมองแกนต์ แอตทริบิวต์จะต้องอยู่ใน (%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Invalid default_scale '%s' ในแกนต์"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "เดือน"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "ชื่อ:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "ถัดไป"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "เปิด"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "แผน"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "แผนที่มีอยู่"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "ก่อนหน้า"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "เริ่ม:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "หยุด:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "วันนี้"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "ไม่กำหนด %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "ดู"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "สัปดาห์"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "ปี"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

281
web_gantt/i18n/tr.po Normal file
View File

@@ -0,0 +1,281 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# İmat Yahya Çataklı <yahyacatakli@gmail.com>, 2022
# Ahmet Altinisik <aaltinisik@altinkaya.com.tr>, 2022
# Tugay Hatıl <tugayh@projetgrup.com>, 2022
# Levent Karakaş <levent@mektup.at>, 2022
# Murat Kaplan <muratk@projetgrup.com>, 2022
# Murat Durmuş <muratd@projetgrup.com>, 2022
# abc Def <hdogan1974@gmail.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Turkish (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Ekle"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Kayıt ekle"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Bu kaydı silmek istediğinizden emin misiniz?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Temel"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Satırları daralt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Oluştur"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Gün"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Satırları genişlet"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Gantt Görünümü"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "Gantt child yalnızca alan veya şablon olabilir, %svar"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt'ın bir 'date_start' özelliği olmalıdır"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt'ın bir 'date_stop' özelliği olmalıdır"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "Gantt görünümü yalnızca bir şablon etiketi içerebilir"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Tarihe göre gruplandırma desteklenmiyor"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Gantt görünümü için yetersiz alanlar!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Gantt görünümünde geçersiz nitelikler (%s). Nitelikler (%s) içinde olmalıdır"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Gantt'ta geçersiz default_scale '%s'"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Ay"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Adı:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Sonraki"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Açık"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Planla"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Mevcut planı"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Önceki"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Başlat:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Dur:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Bugün"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Tanımsız %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Görüntüle"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Hafta"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Yıl"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

275
web_gantt/i18n/uk.po Normal file
View File

@@ -0,0 +1,275 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Ukrainian (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Додати"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Додати запис"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Ви впевнені, що хочете видалити цей запис?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "База"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Згорнути рядки"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Створити"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "День"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Розгорнути рядки"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Діаграма Ґанта"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Перегляд діаграми Ґанта"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
"Дочірня діаграма Ганта може бути лише полем або шаблоном, отримайте %s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Діаграма Ганта повинна мати атрибут 'date_start'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Діаграма Ганта повинна мати атрибут 'date_stop'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "Діаграма Ганта може містити лише один тег шаблону"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Групування за датою не підтримується"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "Недостатньо полів для перегляду діаграми Ганта!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
"Недійсні атрибути (%s) у діаграмі Ганта. Атрибути повинні бути в (%s)"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "Недійсне default_scale '%s' у діаграмі Ганта"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Місяць"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Назва:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Наступний"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Відкрито"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "План"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Існуючий план"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Попередній"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Початок:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Зупинка:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Сьогодні"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Невизначений %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Перегляд"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Тиждень"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Рік"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

274
web_gantt/i18n/vi.po Normal file
View File

@@ -0,0 +1,274 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Duy BQ <duybq86@gmail.com>, 2022
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Vietnamese (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "Thêm"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "Thêm bản ghi"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "Bạn có chắc muốn xóa bảng ghi này?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "Cơ bản"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "Thu gọn hàng"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "Tạo"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "Ngày"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "Mở rộng hàng"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "Gantt"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "Biểu đồ Gantt"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "Gantt cần có một thuột tính 'date_start'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "Gantt cần có một thuột tính 'date_stop'"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "Nhóm theo ngày không được hỗ trợ"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "Tháng"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "Tên:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "Kế tiếp"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "Mở"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "Lập kế hoạch"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "Thoát kế hoạch"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "Trước đó"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "Bắt đầu:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "Ngừng:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "Hôm nay"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "Không xác định %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "Xem"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "Tuần"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "Năm"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

273
web_gantt/i18n/zh_CN.po Normal file
View File

@@ -0,0 +1,273 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Chinese (China) (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "添加"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr "添加记录"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr "确定要删除此记录吗?"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "基础"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr "折叠行"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "创建"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "天"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr "展开行"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "甘特"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "甘特视图"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr "甘特儿只能是字段或模板,转到%s"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr "甘特图必须有一个'date_start'属性"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr "甘特图必须有一个'date_stop'属性"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr "甘特图视图只能包含一个模板标签"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr "不支持按日期分组"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr "甘特图视图的字段不足!"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr "甘特图视图中的无效属性(%s。属性必须在%s中。"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr "甘特图中的default_scale'%s无效"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "月"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "名称:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "下一页"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "打开"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "安排"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr "现有计划"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "上一页"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr "开始:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr "停止:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "今天"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr "未定义的 %s"
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "视图"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "周"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "年"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

273
web_gantt/i18n/zh_TW.po Normal file
View File

@@ -0,0 +1,273 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_gantt
#
# Translators:
# Martin Trigaux, 2022
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.5alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-20 09:49+0000\n"
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
"Last-Translator: Martin Trigaux, 2022\n"
"Language-Team: Chinese (Taiwan) (https://www.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_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "&nbsp;"
msgstr "&nbsp;"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add"
msgstr "增加"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Add record"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Are you sure to delete this record?"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_base
msgid "Base"
msgstr "基礎"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Collapse rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Create"
msgstr "建立"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Day"
msgstr "日"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Expand rows"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt"
msgstr "甘特圖"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Gantt View"
msgstr "甘特圖檢視"
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt child can only be field or template, got %s"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_start' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt must have a 'date_stop' attribute"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid ""
"Gantt must have a 'dependency_inverted_field' attribute once the "
"'dependency_field' is specified"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Gantt view can contain only one templates tag"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Grouping by date is not supported"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "Insufficient fields for Gantt View!"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/ir_ui_view.py:0
#, python-format
msgid "Invalid default_scale '%s' in gantt"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Month"
msgstr "月"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Name:"
msgstr "名稱:"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Next"
msgstr "下一個"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Open"
msgstr "打開"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_controller.js:0
#, python-format
msgid "Plan"
msgstr "計劃"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Plan existing"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Previous"
msgstr "前一個"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"Records that are in the past cannot be automatically rescheduled. They "
"should be manually rescheduled instead."
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Start:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Stop:"
msgstr ""
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:0
#, python-format
msgid "Today"
msgstr "今天"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_model.js:0
#, python-format
msgid "Undefined %s"
msgstr ""
#. module: web_gantt
#: model:ir.model,name:web_gantt.model_ir_ui_view
msgid "View"
msgstr "檢視"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Week"
msgstr "周"
#. module: web_gantt
#. openerp-web
#: code:addons/web_gantt/static/src/js/gantt_view.js:0
#, python-format
msgid "Year"
msgstr "年"
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid "You cannot reschedule %s towards %s."
msgstr ""
#. module: web_gantt
#: code:addons/web_gantt/models/models.py:0
#, python-format
msgid ""
"You cannot reschedule tasks that do not follow a direct dependency path. "
"Only the first task has been automatically rescheduled."
msgstr ""

View File

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
from . import ir_ui_view

View File

@@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from lxml import etree
GANTT_VALID_ATTRIBUTES = set([
'__validate__', # ir.ui.view implementation detail
'date_start',
'date_stop',
'default_scale',
'class',
'js_class',
'form_view_id',
'progress',
'consolidation',
'consolidation_max',
'consolidation_exclude',
'string',
'create',
'on_create',
'cell_create',
'edit',
'delete',
'plan',
'default_group_by',
'permanent_group_by',
'dynamic_range',
'display_unavailability',
'disable_drag_drop',
'total_row',
'collapse_first_level',
'offset',
'scales',
'thumbnails',
'precision',
'color',
'decoration-secondary',
'decoration-success',
'decoration-info',
'decoration-warning',
'decoration-danger',
'sample',
'progress_bar',
'dependency_field',
'dependency_inverted_field',
'pill_label',
])
class View(models.Model):
_inherit = 'ir.ui.view'
def _validate_tag_gantt(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 = _('Gantt view can contain only one templates tag')
self._raise_view_error(msg, child)
elif child.tag != 'field':
msg = _('Gantt child can only be field or template, got %s', child.tag)
self._raise_view_error(msg, child)
default_scale = node.get('default_scale')
if default_scale:
if default_scale not in ('day', 'week', 'month', 'year'):
self._raise_view_error(_("Invalid default_scale '%s' in gantt", default_scale), node)
attrs = set(node.attrib)
if 'date_start' not in attrs:
msg = _("Gantt must have a 'date_start' attribute")
self._raise_view_error(msg, node)
if 'date_stop' not in attrs:
msg = _("Gantt must have a 'date_stop' attribute")
self._raise_view_error(msg, node)
if 'dependency_field' in attrs and 'dependency_inverted_field' not in attrs:
msg = _("Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified")
self._raise_view_error(msg, node)
remaining = attrs - GANTT_VALID_ATTRIBUTES
if remaining:
msg = _(
"Invalid attributes (%s) in gantt view. Attributes must be in (%s)",
','.join(remaining), ','.join(GANTT_VALID_ATTRIBUTES),
)
self._raise_view_error(msg, node)

645
web_gantt/models/models.py Normal file
View File

@@ -0,0 +1,645 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
from datetime import datetime, timezone
from lxml.builder import E
from odoo import _, api, models
from odoo.exceptions import UserError
class Base(models.AbstractModel):
_inherit = 'base'
_start_name = 'date_start' # start field to use for default gantt view
_stop_name = 'date_stop' # stop field to use for default gantt view
# action_gantt_reschedule utils
_WEB_GANTT_RESCHEDULE_FORWARD = 'forward'
_WEB_GANTT_RESCHEDULE_BACKWARD = 'backward'
_WEB_GANTT_LOOP_ERROR = 'loop_error'
@api.model
def _get_default_gantt_view(self):
""" Generates a default gantt view by trying to infer
time-based fields from a number of pre-set attribute names
:returns: a gantt view
:rtype: etree._Element
"""
view = E.gantt(string=self._description)
gantt_field_names = {
'_start_name': ['date_start', 'start_date', 'x_date_start', 'x_start_date'],
'_stop_name': ['date_stop', 'stop_date', 'date_end', 'end_date', 'x_date_stop', 'x_stop_date', 'x_date_end', 'x_end_date'],
}
for name in gantt_field_names.keys():
if getattr(self, name) not in self._fields:
for dt in gantt_field_names[name]:
if dt in self._fields:
setattr(self, name, dt)
break
else:
raise UserError(_("Insufficient fields for Gantt View!"))
view.set('date_start', self._start_name)
view.set('date_stop', self._stop_name)
return view
@api.model
def web_gantt_reschedule(
self,
direction,
master_record_id, slave_record_id,
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name
):
""" Reschedule a record according to the provided parameters.
:param direction: The direction of the rescheduling 'forward' or 'backward'
:param master_record_id: The record that the other one is depending on.
:param slave_record_id: The record that is depending on the other one.
:param dependency_field_name: The field name of the relation between the master and slave records.
:param dependency_inverted_field_name: The field name of the relation between the slave and the parent
records.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:return: True if Successful, a client action of notification type if not.
"""
if direction not in (self._WEB_GANTT_RESCHEDULE_FORWARD, self._WEB_GANTT_RESCHEDULE_BACKWARD):
raise ValueError("Invalid direction %r" % direction)
master_record, slave_record = self.env[self._name].browse([master_record_id, slave_record_id])
search_domain = [(dependency_field_name, 'in', master_record.id), ('id', '=', slave_record.id)]
if not self.env[self._name].search(search_domain, limit=1):
raise ValueError("Record '%r' is not a parent record of '%r'" % (master_record.name, slave_record.name))
if not self._web_web_gantt_reschedule_is_relation_candidate(
master_record, slave_record, start_date_field_name, stop_date_field_name):
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'warning',
'message': _('You cannot reschedule %s towards %s.',
master_record.name, slave_record.name),
}
}
is_master_prior_to_slave = master_record[stop_date_field_name] <= slave_record[start_date_field_name]
# When records are in conflict, record that is moved is the other one than when there is no conflict.
# This might seem strange at first sight but has been decided during first implementation as when in conflict,
# and especially when the distance between the pills is big, the arrow is interpreted differently as it comes
# from the right to the left (instead of from the left to the right).
if is_master_prior_to_slave ^ (direction == self._WEB_GANTT_RESCHEDULE_BACKWARD):
trigger_record = master_record
related_record = slave_record
else:
trigger_record = slave_record
related_record = master_record
cache = self._web_gantt_reschedule_get_empty_cache()
new_start_date, new_stop_date = trigger_record._web_gantt_reschedule_record(
related_record, related_record == master_record,
start_date_field_name, stop_date_field_name,
cache
)
result = trigger_record._web_gantt_reschedule_write_new_dates(
new_start_date, new_stop_date, start_date_field_name, stop_date_field_name,
)
sp = self.env.cr.savepoint()
record_ids_to_exclude = defaultdict(list)
result = result is True and trigger_record._web_gantt_action_reschedule_related_records(
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name,
direction,
record_ids_to_exclude,
cache
)
if result is not True:
if result is False:
notification_type = 'warning'
message = _('Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead.')
elif result == self._WEB_GANTT_LOOP_ERROR:
notification_type = 'info'
message = _('You cannot reschedule tasks that do not follow a direct dependency path. '
'Only the first task has been automatically rescheduled.')
else:
raise ValueError('Unsupported result value')
result = {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': notification_type,
'message': message,
}
}
sp.close(rollback=result is not True)
return result
@api.model
def gantt_progress_bar(self, fields, res_ids, date_start_str, date_stop_str):
""" Get progress bar value per record.
This method is meant to be overriden by each related model that want to
implement this feature on Gantt groups. The progressbar is composed
of a value and a max_value given for each groupedby field.
Example:
fields = ['foo', 'bar'],
res_ids = {'foo': [1, 2], 'bar':[2, 3]}
start_date = 01/01/2000, end_date = 01/07/2000,
self = base()
Result:
{
'foo': {
1: {'value': 50, 'max_value': 100},
2: {'value': 25, 'max_value': 200},
},
'bar': {
2: {'value': 65, 'max_value': 85},
3: {'value': 30, 'max_value': 95},
}
}
:param list fields: fields on which there are progressbars
:param dict res_ids: res_ids of related records for which we need to compute progress bar
:param string date_start_str: start date
:param string date_stop_str: stop date
:returns: dict of value and max_value per record
"""
return {}
@api.model
def gantt_unavailability(self, start_date, end_date, scale, group_bys=None, rows=None):
""" Get unavailabilities data to display in the Gantt view.
This method is meant to be overriden by each model that want to
implement this feature on a Gantt view. A subslot is considered
unavailable (and greyed) when totally covered by an unavailability.
Example:
* start_date = 01/01/2000, end_date = 01/07/2000, scale = 'week',
rows = [{
groupedBy: ["project_id", "user_id", "stage_id"],
records: [1, 4, 2],
name: "My Awesome Project",
resId: 8,
rows: [{
groupedBy: ["user_id", "stage_id"],
records: [1, 2],
name: "Marcel",
resId: 18,
rows: [{
groupedBy: ["stage_id"],
records: [2],
name: "To Do",
resId: 3,
rows: []
}, {
groupedBy: ["stage_id"],
records: [1],
name: "Done",
resId: 9,
rows: []
}]
}, {
groupedBy: ["user_id", "stage_id"],
records: [4],
name: "Gilbert",
resId: 22,
rows: [{
groupedBy: ["stage_id"],
records: [4],
name: "Done",
resId: 9,
rows: []
}]
}]
}, {
groupedBy: ["project_id", "user_id", "stage_id"],
records: [3, 5, 7],
name: "My Other Project",
resId: 9,
rows: [{
groupedBy: ["user_id", "stage_id"],
records: [3, 5, 7],
name: "Undefined User",
resId: None,
rows: [{
groupedBy: ["stage_id"],
records: [3, 5, 7],
name: "To Do",
resId: 3,
rows: []
}]
}, {
groupedBy: ["project_id", "user_id", "stage_id"],
records: [],
name: "My group_expanded Project",
resId: 27,
rows: []
}]
* The expected return value of this function is the rows dict with
a new 'unavailabilities' key in each row for which you want to
display unavailabilities. Unavailablitities is a list
(naturally ordered and pairwise disjoint) in the form:
[{
start: <start date of first unavailabity in UTC format>,
stop: <stop date of first unavailabity in UTC format>
}, {
start: <start date of second unavailabity in UTC format>,
stop: <stop date of second unavailabity in UTC format>
}, ...]
To display that Marcel is unavailable January 2 afternoon and
January 4 the whole day in his To Do row, this particular row in
the rows dict should look like this when returning the dict at the
end of this function :
{ ...
{
groupedBy: ["stage_id"],
records: [2],
name: "To Do",
resId: 3,
rows: []
unavailabilities: [{
'start': '2018-01-02 14:00:00',
'stop': '2018-01-02 18:00:00'
}, {
'start': '2018-01-04 08:00:00',
'stop': '2018-01-04 18:00:00'
}]
}
...
}
:param datetime start_date: start date
:param datetime stop_date: stop date
:param string scale: among "day", "week", "month" and "year"
:param None | list[str] group_bys: group_by fields
:param dict rows: dict describing the current rows of the gantt view
:returns: dict of unavailability
"""
return rows
def _web_gantt_action_reschedule_related_records(
self,
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name,
direction,
record_ids_to_exclude,
cache
):
""" Reschedule the related records, that is the records available in both fields dependency_field_name and
dependency_inverted_field_name and which satisfies some conditions which are tested in
_web_gantt_get_rescheduling_candidates
:param dependency_field_name: The field name of the relation between the master and slave records.
:param dependency_inverted_field_name: The field name of the relation between the slave and the parent
records.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:param direction: The direction of the rescheduling 'forward' or 'backward'
:param record_ids_to_exclude: The record Ids that have to be excluded from the return candidates.
:param cache: An object that contains reusable information in the context of gantt record rescheduling.
:return: True if successful, False if not.
:rtype: bool
"""
rescheduling_candidates = self._web_gantt_get_rescheduling_candidates(
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name,
direction,
record_ids_to_exclude
)
if rescheduling_candidates is False:
return self._WEB_GANTT_LOOP_ERROR
if not rescheduling_candidates:
return True
result = True
records_to_propagate = self.env[self._name]
for rescheduling_candidate in rescheduling_candidates:
record, related_record, is_related_record_master = rescheduling_candidate
new_start_date, new_stop_date = record._web_gantt_reschedule_record(
related_record, is_related_record_master,
start_date_field_name, stop_date_field_name,
cache
)
record_write_result = record._web_gantt_reschedule_write_new_dates(
new_start_date, new_stop_date,
start_date_field_name, stop_date_field_name,
)
if record_write_result:
records_to_propagate |= record
record_ids_to_exclude[record.id] = record_ids_to_exclude[related_record.id] + [related_record.id]
result &= record_write_result
for record in self:
record_ids_to_exclude.pop(record.id, None)
related_records_result = records_to_propagate._web_gantt_action_reschedule_related_records(
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name,
direction,
record_ids_to_exclude,
cache
)
if isinstance(related_records_result, bool):
result &= related_records_result
else:
result = related_records_result
return result
def _web_gantt_get_rescheduling_candidates(
self,
dependency_field_name, dependency_inverted_field_name,
start_date_field_name, stop_date_field_name,
direction,
record_ids_to_exclude
):
""" Get the current records' related records rescheduling candidates (the records that depend on them as well
as the records they depend on) for the rescheduling process as well as their reference records (the
furthest record that depends on it, as well as the furthest record it depends on).
:param dependency_field_name: The field name of the relation between the master and slave records.
:param dependency_inverted_field_name: The field name of the relation between the slave and the parent
records.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:param direction: The direction of the rescheduling 'forward' or 'backward'
:param record_ids_to_exclude: The record Ids that have to be excluded from the return candidates.
:return: a list of tuples (record, related_record, is_related_record_master)
where: - record is the record to be rescheduled
- related_record is the record that is the target of the rescheduling
- is_related_record_master informs whether the related_record is a record that the current
record depends on (so-called master) or a record that depends on the current record
(so-called slave)
:rtype: tuple(AbstractModel, AbstractModel, bool)
"""
rescheduling_forward = direction == self._WEB_GANTT_RESCHEDULE_FORWARD
rescheduling_backward = direction == self._WEB_GANTT_RESCHEDULE_BACKWARD
slave_per_record = defaultdict(lambda: self.env[self._name])
master_per_record = defaultdict(lambda: self.env[self._name])
records_to_reschedule = self.env[self._name]
# The goal is to automatically exclude ids from the `dependency_field_name` and `dependency_inverted_field_name`
# fields but not the self.ids. And the later call on _web_gantt_reschedule_is_record_candidate will ensure that
# the self.ids are good candidates.
for record in self:
if record.id in record_ids_to_exclude[record.id] \
or not record._web_gantt_reschedule_is_record_candidate(start_date_field_name, stop_date_field_name):
continue
for master_record in record[dependency_field_name]:
#
# A B C D
# \ \ / /
# ------ F ------
# / \
# G --- --- H
#
# So if we are considering we are rescheduling F towards G then, once F is moved, B will be
# added to the candidates as it will be assessed as being in conflict with F, but A won't.
#
# So if we are considering we are rescheduling F towards H then, once F is moved, A, B and G
# will be added to the candidates as we are rescheduling forward.
if master_record.id in record_ids_to_exclude[record.id] \
or not master_record._web_gantt_reschedule_is_record_candidate(
start_date_field_name, stop_date_field_name) \
or not self._web_web_gantt_reschedule_is_relation_candidate(
master_record, record, start_date_field_name, stop_date_field_name) \
or not self._web_gantt_reschedule_is_in_conflict_or_force(
master_record, record, start_date_field_name, stop_date_field_name, rescheduling_forward):
continue
# If we have two same candidates, it means that we are resolving a `loop`
# with an even number of members.
if master_record in slave_per_record:
return False
slave_per_record[master_record] = record
records_to_reschedule |= master_record
for slave_record in record[dependency_inverted_field_name]:
#
# A B C D
# \ \ / /
# ------ F ------
# / \
# G --- --- H
#
# So if we are considering we are rescheduling F towards H then, once F is moved, C will be
# added to the candidates as it will be assessed as being in conflict with F, but D won't.
#
# So if we are considering we are rescheduling F towards G then C, once F is moved, D and H
# will be added to the candidates as we are rescheduling backward.
if slave_record.id in record_ids_to_exclude[record.id] \
or not slave_record._web_gantt_reschedule_is_record_candidate(
start_date_field_name, stop_date_field_name) \
or not self._web_web_gantt_reschedule_is_relation_candidate(
record, slave_record, start_date_field_name, stop_date_field_name) \
or not self._web_gantt_reschedule_is_in_conflict_or_force(
record, slave_record, start_date_field_name, stop_date_field_name, rescheduling_backward):
continue
# If we have two same candidates, it means that we are resolving a `loop`
# with an even number of members.
if slave_record in master_per_record:
return False
master_per_record[slave_record] = record
records_to_reschedule |= slave_record
# If we have a record that is both a slave and a master candidate, it means that we are resolving a `loop`
# with an even number of members.
if set.intersection(set(slave_per_record.keys()), set(master_per_record.keys())):
if set.intersection(*map(set, [record_ids_to_exclude[rec.id]for rec in self])):
return False
# If we have a record from self that is a slave candidate and a record from self that is a master candidate,
# it means that we are resolving a loop with an odd number of members.
if any(record in slave_per_record.keys() for record in self) and \
any(record in master_per_record.keys() for record in self):
return False
return [
(record_to_reschedule,
slave_per_record[record_to_reschedule] or master_per_record[record_to_reschedule],
bool(master_per_record[record_to_reschedule])
) for record_to_reschedule in records_to_reschedule
]
def _web_gantt_reschedule_compute_dates(
self, date_candidate, search_forward, start_date_field_name, stop_date_field_name, cache
):
""" Compute start_date and end_date according to the provided arguments.
This method is meant to be overridden when we need to add constraints that have to be taken into account
in the computing of the start_date and end_date.
:param date_candidate: The optimal date, which does not take any constraint into account.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:param cache: An object that contains reusable information in the context of gantt record rescheduling.
:return: a tuple of (start_date, end_date)
:rtype: tuple(datetime, datetime)
"""
search_factor = (1 if search_forward else -1)
duration = search_factor * (self[stop_date_field_name] - self[start_date_field_name])
return sorted([date_candidate, date_candidate + duration])
@api.model
def _web_gantt_reschedule_get_empty_cache(self):
""" Get an empty object that would be used in order to prevent successive database calls during the
rescheduling process.
:return: An object that contains reusable information in the context of gantt record rescheduling.
:rtype: dict
"""
return {}
@api.model
def _web_gantt_reschedule_is_in_conflict(self, master, slave, start_date_field_name, stop_date_field_name):
""" Get whether the dependency relation between a master and a slave record is in conflict.
This check is By-passed for slave records if moving records forwards and the for
master records if moving records backwards (see _web_gantt_get_rescheduling_candidates and
_web_gantt_reschedule_is_in_conflict_or_force). In order to add condition that would not be
by-passed, rather consider _web_gantt_reschedule_is_relation_candidate.
:param master: The master record.
:param slave: The slave record.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:return: True if there is a conflict, False if not.
:rtype: bool
"""
return master[stop_date_field_name] > slave[start_date_field_name]
@api.model
def _web_gantt_reschedule_is_in_conflict_or_force(
self, master, slave, start_date_field_name, stop_date_field_name, force
):
""" Get whether the dependency relation between a master and a slave record is in conflict.
This check is By-passed for slave records if moving records forwards and the for
master records if moving records backwards. In order to add condition that would not be
by-passed, rather consider _web_gantt_reschedule_is_relation_candidate.
This def purpose is to be able to prevent the default behavior in some modules by overriding
the def and forcing / preventing the rescheduling il all circumstances if needed.
See _web_gantt_get_rescheduling_candidates.
:param master: The master record.
:param slave: The slave record.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:param force: Force returning True
:return: True if there is a conflict, False if not.
:rtype: bool
"""
return force or self._web_gantt_reschedule_is_in_conflict(
master, slave, start_date_field_name, stop_date_field_name
)
def _web_gantt_reschedule_is_record_candidate(self, start_date_field_name, stop_date_field_name):
""" Get whether the record is a candidate for the rescheduling. This method is meant to be overridden when
we need to add a constraint in order to prevent some records to be rescheduled. This method focuses on the
record itself (if you need to have information on the relation (master and slave) rather override
_web_gantt_reschedule_is_relation_candidate).
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:return: True if record can be rescheduled, False if not.
:rtype: bool
"""
self.ensure_one()
return self[start_date_field_name] and self[stop_date_field_name] \
and self[start_date_field_name].replace(tzinfo=timezone.utc) > datetime.now(timezone.utc)
@api.model
def _web_web_gantt_reschedule_is_relation_candidate(self, master, slave, start_date_field_name, stop_date_field_name):
""" Get whether the relation between master and slave is a candidate for the rescheduling. This method is meant
to be overridden when we need to add a constraint in order to prevent some records to be rescheduled.
This method focuses on the relation between records (if your logic is rather on one record, rather override
_web_gantt_reschedule_is_record_candidate).
:param master: The master record we need to evaluate whether it is a candidate for rescheduling or not.
:param slave: The slave record.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:return: True if record can be rescheduled, False if not.
:rtype: bool
"""
return True
def _web_gantt_reschedule_record(
self, related_record, is_related_record_master, start_date_field_name, stop_date_field_name, cache
):
""" Shift the record in the future or the past according to the passed arguments.
:param related_record: The related record (either the master or slave record).
:param is_related_record_master: Tells whether the related record is the master or slave in the dependency.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:param cache: An object that contains reusable information in the context of gantt record rescheduling.
:return: a tuple of (start_date, end_date)
:rtype: tuple(datetime, datetime)
"""
self.ensure_one()
# If the related_record is the master, then we look for a date after the value of its stop_date_field_name.
# If the related_record is the slave, then we look for a date prior to the value of its start_date_field_name.
search_forward = is_related_record_master
if search_forward:
date_candidate = related_record[stop_date_field_name].replace(tzinfo=timezone.utc)
else:
date_candidate = related_record[start_date_field_name].replace(tzinfo=timezone.utc)
return self.sudo()._web_gantt_reschedule_compute_dates(
date_candidate,
search_forward,
start_date_field_name, stop_date_field_name,
cache
)
def _web_gantt_reschedule_write_new_dates(
self, new_start_date, new_stop_date, start_date_field_name, stop_date_field_name
):
""" Write the dates values if new_start_date is in the future.
:param new_start_date: The start_date to write.
:param new_stop_date: The stop_date to write.
:param start_date_field_name: The start date field used in the gantt view.
:param stop_date_field_name: The stop date field used in the gantt view.
:return: True if successful, False if not.
:rtype: bool
"""
if new_start_date < datetime.now(timezone.utc):
return False
self.write({
start_date_field_name: new_start_date.astimezone(timezone.utc).replace(tzinfo=None),
stop_date_field_name: new_stop_date.astimezone(timezone.utc).replace(tzinfo=None)
})
return True

View File

@@ -0,0 +1,336 @@
/** @odoo-module **/
import { deepMerge } from "./connector_utils";
const { Component, onWillUpdateProps } = owl;
class Connector extends Component {
// -----------------------------------------------------------------------------
// Life cycle hooks
// -----------------------------------------------------------------------------
/**
* @override
*/
setup() {
this._refreshPropertiesFromProps(this.props);
onWillUpdateProps(this.onWillUpdateProps);
}
/**
*
* @override
* @param nextProps
* @returns {Promise<void>}
*/
async onWillUpdateProps(nextProps) {
this._refreshPropertiesFromProps(nextProps);
}
// -----------------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------------
/**
* Refreshes the connector properties from the props.
*
* @param {Object} props
* @private
*/
_refreshPropertiesFromProps(props) {
const defaultStyleProps = {
drawHead: true,
outlineStroke: {
color: 'rgba(255,255,255,0.5)',
hoveredColor: 'rgba(255,255,255,0.9)',
width: 2,
},
slackness: 0.5,
stroke: {
color: 'rgba(0,0,0,0.5)',
hoveredColor: 'rgba(0,0,0,0.9)',
width: 2,
},
};
this.hoverEaseWidth = props.hoverEaseWidth ? props.hoverEaseWidth : 1;
this.style = deepMerge(defaultStyleProps, props.style);
const pathInfo = this._getPathInfo(props.source, props.target, this.style.slackness);
this.path = `M ${pathInfo.singlePath.source.left} ${pathInfo.singlePath.source.top} \
C ${pathInfo.singlePath.sourceControlPoint.left} ${pathInfo.singlePath.sourceControlPoint.top} \
${pathInfo.singlePath.targetControlPoint.left} ${pathInfo.singlePath.targetControlPoint.top} \
${pathInfo.singlePath.target.left} ${pathInfo.singlePath.target.top}`;
this.removeButtonPosition = pathInfo.doublePath.startingPath.target;
}
/**
* Returns the parameters of both the single Bezier curve as well as is decomposition into two beziers curves
* (which allows to get the middle position of the single Bezier curve) for the provided source, target and
* slackness (0 being a straight line).
*
* @param {{ left: number, top: number }} source
* @param {{ left: number, top: number }} target
* @param {number} slackness [0, 1]
* @returns {{
* singlePath: {
* source: {
* top: number,
* left: number
* },
* sourceControlPoint: {
* top: number,
* left: number
* },
* target: {
* top: number,
* left: number
* },
* targetControlPoint: {
* top: number,
* left: number
* }
* },
* doublePath: {
* endingPath: {
* source: {
* top: number,
* left: number
* },
* sourceControlPoint: {
* top: number,
* left: number
* },
* target: {
* top: number,
* left: number
* },
* targetControlPoint: {
* top: number,
* left: number
* }
* },
* startingPath: {
* source: {
* top: number,
* left: number
* },
* sourceControlPoint: {
* top: number,
* left: number
* },
* target: {
* top: number,
* left: number
* },
* targetControlPoint: {
* top: number,
* left: number
* }
* }
* }
* }}
* @private
*/
_getPathInfo(source, target, slackness) {
const b = { left: 0, top: 0 };
const c = { left: 0, top: 0 };
// If the source is on the left of the target, we need to invert the control points.
const directionFactor = source.left < target.left ? 1 : -1;
// What follows can be seen as magic numbers. And those are indeed such numbers as they have been determined
// by observing their shape while creating short and long connectors. These seems to allow keeping the same
// kind of shape amongst short and long connectors.
const xDelta = 100 + directionFactor * (target.left - source.left) * slackness / 10;
const yDelta = Math.abs(source.top - target.top) < 16 && source.left > target.left ? 15 + 0.001 * (source.left - target.left) * slackness : 0;
b.left = source.left + xDelta;
b.top = source.top + yDelta;
// Prevent having the air pin effect when in creation and having target on the left of the source
if (!this.props.inCreation || directionFactor > 0) {
c.left = target.left - xDelta;
} else {
c.left = target.left + xDelta;
}
c.top = target.top + yDelta;
const cuttingDistance = 0.5;
const e = Connector._getLinearInterpolation(source, b, cuttingDistance);
const f = Connector._getLinearInterpolation(b, c, cuttingDistance);
const g = Connector._getLinearInterpolation(c, target, cuttingDistance);
const h = Connector._getLinearInterpolation(e, f, cuttingDistance);
const i = Connector._getLinearInterpolation(f, g, cuttingDistance);
const j = Connector._getLinearInterpolation(h, i, cuttingDistance);
return {
singlePath: {
source: source,
sourceControlPoint: b,
target: target,
targetControlPoint: c,
},
doublePath: {
endingPath: {
source: j,
sourceControlPoint: i,
target: target,
targetControlPoint: g,
},
startingPath: {
source: source,
sourceControlPoint: e,
target: j,
targetControlPoint: h,
},
},
};
}
// -----------------------------------------------------------------------------
// Handlers
// -----------------------------------------------------------------------------
/**
* Handler for connector_stroke_buttons remove click event.
*
* @param {OwlEvent} ev
*/
_onRemoveButtonClick(ev) {
const payload = {
data: deepMerge(this.props.data),
id: this.props.id,
};
this.props.onRemoveButtonClick(payload);
}
/**
* Handler for connector_stroke_buttons reschedule sooner click event.
*
* @param {OwlEvent} ev
*/
_onRescheduleSoonerClick(ev) {
const payload = {
data: deepMerge(this.props.data),
id: this.props.id,
};
this.props.onRescheduleSoonerButtonClick(payload);
}
/**
* Handler for connector_stroke_buttons reschedule later click event.
*
* @param {OwlEvent} ev
*/
_onRescheduleLaterClick(ev) {
const payload = {
data: deepMerge(this.props.data),
id: this.props.id,
};
this.props.onRescheduleLaterButtonClick(payload);
}
}
const endProps = {
shape: {
left: Number,
top: Number,
},
type: Object,
};
const strokeStyleProps = {
optional: true,
shape: {
color: {
optional: true,
type: String,
},
hoveredColor: {
optional: true,
type: String,
},
width: {
optional: true,
type: Number,
},
},
type: Object,
};
Object.assign(Connector, {
props: {
canBeRemoved: {
optional: true,
type: Boolean
},
data: {
optional: true,
type: Object,
},
hoverEaseWidth: {
optional: true,
type: Number,
},
hovered: {
optional: true,
type: Boolean
},
inCreation: {
optional: true,
type: Boolean,
},
id: { type: String | Number },
source: endProps,
style: {
optional: true,
shape: {
drawHead: {
optional: true,
type: Boolean,
},
outlineStroke: strokeStyleProps,
slackness: {
optional: true,
type: Number,
validate: slackness => (0 <= slackness && slackness <= 1),
},
stroke: strokeStyleProps,
},
type: Object,
},
target: endProps,
onRemoveButtonClick: { type: Function, optional: true },
onRescheduleSoonerButtonClick: { type: Function, optional: true },
onRescheduleLaterButtonClick: { type: Function, optional: true },
},
defaultProps: {
onRemoveButtonClick: () => {},
onRescheduleSoonerButtonClick: () => {},
onRescheduleLaterButtonClick: () => {},
},
template: 'connector',
// -----------------------------------------------------------------------------
// Private Static
// -----------------------------------------------------------------------------
/**
* Returns the linear interpolation for a point to be found somewhere between a startingPoint and a endingPoint.
*
* @param {{top: number, left: number}} startingPoint
* @param {{top: number, left: number}} endingPoint
* @param {number} interpolationPercentage [0, 1] the distance (from 0 startingPoint to 1 endingPoint)
* the point has to be computed at.
* @returns {{top: number, left: number}}
* @private
*/
_getLinearInterpolation(startingPoint, endingPoint, interpolationPercentage) {
if (interpolationPercentage < 0 || 1 > interpolationPercentage) {
// Ensures interpolationPercentage is within expected boundaries.
interpolationPercentage = Math.min(Math.max (0, interpolationPercentage), 1);
}
const remaining = 1 - interpolationPercentage;
return {
left: startingPoint.left * remaining + endingPoint.left * interpolationPercentage,
top: startingPoint.top * remaining + endingPoint.top * interpolationPercentage
};
},
});
export default Connector;

View File

@@ -0,0 +1,414 @@
/** @odoo-module **/
import Connector from "./connector";
import { deepMerge } from "./connector_utils";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { onMounted, onWillUnmount, onWillUpdateProps } = owl;
class ConnectorContainer extends LegacyComponent {
// -----------------------------------------------------------------------------
// Life cycle hooks
// -----------------------------------------------------------------------------
/**
* @override
*/
setup() {
this._createsParentListenerHandlers();
/**
* Keeps track of the mouse events related info.
* @type {{ isParentDragging: boolean, hoveredConnector: HTMLElement }}
*/
this.mouseEventsInfo = { };
// Connector component used in order to manage connector creation.
this.newConnector = {
id: "newConnectorId",
canBeRemoved: false,
};
// Apply default styling (if any) to newConnector.
if ('defaultStyle' in this.props) {
this.newConnector = deepMerge(this.newConnector, { style: this.props.defaultStyle });
}
if ('newConnectorStyle' in this.props) {
this.newConnector = deepMerge(this.newConnector, { style: this.props.newConnectorStyle });
}
this._refreshPropertiesFromProps(this.props);
onMounted(this.onMounted);
onWillUnmount(this.onWillUnmount);
onWillUpdateProps(this.onWillUpdateProps);
}
/**
* @override
*/
onMounted() {
if (this.parentElement && this.parentElement !== this.el.parentElement) {
this._removeParentListeners();
}
this.parentElement = this.el.parentElement;
this._addParentListeners();
}
/**
* @override
*/
onWillUnmount() {
this._removeParentListeners();
}
/**
*
* @override
* @param nextProps
* @returns {Promise<void>}
*/
async onWillUpdateProps(nextProps) {
this._refreshPropertiesFromProps(nextProps);
}
// -----------------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------------
/**
* Adds the ConnectorContainer's parent required EventListeners.
*
* @private
*/
_addParentListeners() {
this.parentElement.addEventListener('mousedown', this._onParentMouseDownHandler);
this.parentElement.addEventListener('mousemove', this._throttledOnParentMouseOverHandler);
this.parentElement.addEventListener('mouseup', this._onParentMouseUpHandler);
this.parentElement.addEventListener('mouseleave', this._onParentMouseUpHandler);
}
/**
* Creates the handlers used in _addParentListeners and _removeParentListeners calls.
*
* @private
*/
_createsParentListenerHandlers() {
this._throttledOnParentMouseOverHandler = _.throttle((ev) => this._onParentMouseOver(ev), 50);
this._onParentMouseDownHandler = (ev) => this._onParentMouseDown(ev);
this._onParentMouseUpHandler = (ev) => this._onParentMouseUp(ev);
}
/**
* Gets the element offset against the connectorContainer's parent.
*
* @param {HTMLElement} element the element the offset position has to be calculated for.
*/
_getElementPosition(element) {
// This will not work for css translated elements and this is acceptable at this time.
// If needed in the future, consider using getBoundingClientRect() if getComputedStyle() returns a style
// having a transform (and place this also in the for loop as we would need to do it if the element or any of
// its parent is using css transform).
let left = element.offsetLeft || 0;
let top = element.offsetTop || 0;
for (let el = element.offsetParent; el != null && el !== this.el.parentElement; el = el.offsetParent) {
left += el.offsetLeft || 0;
top += el.offsetTop || 0;
}
return {
left: left,
top: top,
};
}
/**
* Refreshes the connector properties from the props.
*
* @param {Object} props
* @private
*/
_refreshPropertiesFromProps(props) {
this.connectors = deepMerge(props.connectors);
if (this.props.defaultStyle) {
Object.keys(this.connectors)
.forEach((key) => {
this.connectors[key].style = deepMerge(this.props.defaultStyle, this.connectors[key].style);
if (!('hoverEaseWidth' in this.connectors[key]) && 'hoverEaseWidth' in props) {
this.connectors[key].hoverEaseWidth = props.hoverEaseWidth;
}
});
}
const isHoveredConnectorSet = 'hoveredConnector' in this.mouseEventsInfo;
const isHoveredConnectorPartOfProps = isHoveredConnectorSet && this.mouseEventsInfo.hoveredConnector.dataset.id in this.connectors;
if (isHoveredConnectorSet && !isHoveredConnectorPartOfProps) {
// Ensures to reset the mouseEventsInfo in case the hoveredConnector is set but is no more part
// of the new props.
delete this.mouseEventsInfo.hoveredConnector;
}
}
/**
* Removes the ConnectorContainer's parent required EventListeners.
*
*/
_removeParentListeners() {
this.parentElement.removeEventListener('mousedown', this._onParentMouseDownHandler);
this.parentElement.removeEventListener('mousemove', this._throttledOnParentMouseOverHandler);
this.parentElement.removeEventListener('mouseup', this._onParentMouseUpHandler);
this.parentElement.removeEventListener('mouseleave', this._onParentMouseUpHandler);
}
/**
* Updates the hover state of the connector and render
*
* @param {string} id the id of the connector which hover state has to be updated.
* @param {boolean} hovered the hover state to be set.
* @private
*/
_updateConnectorHoverState(id, hovered) {
this.connectors[id].hovered = hovered && !(this.props.preventHoverEffect || this.mouseEventsInfo.isParentDragging);
if (hovered) {
// When a connector is hover we need to ensure it is rendered as last element as svg z-index works
// that way and unfortunately no css can be used to modify it.
const hoverConnector = this.connectors[id];
delete this.connectors[id];
this.connectors[id] = hoverConnector;
}
this.render();
}
// -----------------------------------------------------------------------------
// Public
// -----------------------------------------------------------------------------
/**
* Gets the top, right, bottom and left anchors positions for the provided element with respect to the
* ConnectorContainer's parent.
*
* @param {HTMLElement} element the element the anchors positions have to be calculated for.
* @param {HTMLElement} container the container the anchors positions will be calculated with respect to. In order
* to have a valid result, the container should be an element with position attribute
* set to relative.
* @returns {{
* top: {top: number, left: number},
* left: {top: number, left: number},
* bottom: {top: number, left: number},
* right: {top: number, left: number}
* }}
*/
getAnchorsPositions(element) {
const elementPosition = this._getElementPosition(element);
return {
top: {
top: elementPosition.top,
left: elementPosition.left + element.offsetWidth / 2,
},
right: {
top: elementPosition.top + element.offsetHeight / 2,
left: elementPosition.left + element.offsetWidth,
},
bottom: {
top: elementPosition.top + element.offsetHeight,
left: elementPosition.left + element.offsetWidth / 2,
},
left: {
top: elementPosition.top + element.offsetHeight / 2,
left: elementPosition.left,
},
};
}
// -----------------------------------------------------------------------------
// Handlers
// -----------------------------------------------------------------------------
/**
* Handler for the ConnectorContainer's parent mousedown event. This handle is responsible of managing the start of a possible
* connector creation (depending on whether the event target matches the sourceQuerySelector).
*
* @param {MouseEvent} ev
* @private
*/
_onParentMouseDown(ev) {
const connector_source = ev.target.closest(this.props.sourceQuerySelector);
if (connector_source) {
ev.stopPropagation();
ev.preventDefault();
this.mouseEventsInfo.isParentDragging = true;
const anchors = this.getAnchorsPositions(ev.target);
this.newConnector = deepMerge(
this.newConnector,
{
data: {
sourceElement: connector_source,
},
inCreation: true,
source: {
top: anchors.right.top,
left: anchors.right.left,
},
target: {
top: anchors.right.top + ev.offsetY,
left: anchors.right.left + ev.offsetX,
},
});
this.props.onCreationStart(deepMerge({ }, this.newConnector));
this.render();
}
}
/**
* Handler for the ConnectorContainer's parent mouseover event. This handle is responsible of the update of the newConnector
* component props if a connector creation has started.
*
* @param {MouseEvent} ev
* @private
*/
_onParentMouseOver(ev) {
if (this.mouseEventsInfo.isParentDragging === true) {
ev.stopPropagation();
ev.preventDefault();
const position = this._getElementPosition(ev.target);
this.newConnector = deepMerge(
this.newConnector,
{
target: {
top: position.top + ev.offsetY,
left: position.left + ev.offsetX,
},
});
this.render();
}
}
/**
* Handler for the ConnectorContainer's parent mouseup event. This handle is responsible of triggering either the
* connector-creation-done or connector-creation-abort (depending on whether the event target matches the
* targetQuerySelector) if a connector creation has started.
*
* @param {MouseEvent} ev
* @private
*/
_onParentMouseUp(ev) {
if (this.mouseEventsInfo.isParentDragging === true) {
ev.stopPropagation();
ev.preventDefault();
const connector_target = ev.target.closest(this.props.targetQuerySelector || this.props.sourceQuerySelector);
if (connector_target) {
this.newConnector = deepMerge(
this.newConnector,
{
data: {
targetElement: connector_target,
},
});
this.props.onCreationDone(deepMerge({ }, this.newConnector));
} else {
this.props.onCreationAbort(deepMerge({ }, this.newConnector));
}
this.mouseEventsInfo.isParentDragging = false;
delete this.newConnector.source;
delete this.newConnector.target;
this.render();
}
}
/**
* Handler for the connector_manager svg mouseout event. Its purpose is to handle the hover state of the connectors.
* It has been implemented here in order to manage it globally instead of in each connector (and thus limiting
* the number of listeners).
*
* @param {OwlEvent} ev
* @private
*/
_onMouseOut(ev) {
ev.stopPropagation();
if (!('hoveredConnector' in this.mouseEventsInfo)) {
// If hoverConnector is not set this means were not in a connector. So ignore it.
return;
}
let relatedTarget = ev.relatedTarget;
while (relatedTarget) {
// Go up the parent chain
if (relatedTarget === this.mouseEventsInfo.hoveredConnector) {
// Check that we are still inside hoveredConnector.
// If so it means it is a transition between child elements so ignore it.
return;
}
relatedTarget = relatedTarget.parentElement;
}
this._updateConnectorHoverState(this.mouseEventsInfo.hoveredConnector.dataset.id, false);
this.props.onMouseOut(this.connectors[this.mouseEventsInfo.hoveredConnector.dataset.id]);
delete this.mouseEventsInfo.hoveredConnector;
}
/**
* Handler for the connector_manager svg mouseover event. Its purpose is to handle the hover state of the connectors.
* It has been implemented here in order to manage it globally instead of in each connector (and thus limiting
* the number of listeners).
*
* @param {OwlEvent} ev
* @private
*/
_onMouseOver(ev) {
ev.stopPropagation();
if ('hoveredConnector' in this.mouseEventsInfo) {
// As mouseout is call prior to mouseover, if hoveredConnector is set this means
// that we haven't left it. So it's a mouseover inside it.
return;
}
let target = ev.target.closest('.o_connector');
if (!target) {
// We are not into a connector si ignore.
return;
}
if (!(target.dataset.id in this.connectors) || Object.is(this.connectors[target.dataset.id], this.newConnector)) {
// We ensure that the connector to hover is not this.newConnector
return;
}
this.mouseEventsInfo.hoveredConnector = target;
this._updateConnectorHoverState(target.dataset.id, true);
this.props.onMouseOver(this.connectors[target.dataset.id]);
}
}
Object.assign(ConnectorContainer, {
components: { Connector },
props: {
connectors: { type: Object },
defaultStyle: Connector.props.style,
hoverEaseWidth: {
optional: true,
type: Number,
},
newConnectorStyle: Connector.props.style,
preventHoverEffect: {
optional: true,
type: Boolean
},
sourceQuerySelector: { type: String },
targetQuerySelector: {
optional: true,
type: String,
},
onRemoveButtonClick: { type: Function, optional: true },
onRescheduleSoonerButtonClick: { type: Function, optional: true },
onRescheduleLaterButtonClick: { type: Function, optional: true },
onCreationAbort: { type: Function, optional: true },
onCreationDone: { type: Function, optional: true },
onCreationStart: { type: Function, optional: true },
onMouseOut: { type: Function, optional: true },
onMouseOver: { type: Function, optional: true },
},
defaultProps: {
onRemoveButtonClick: () => {},
onRescheduleSoonerButtonClick: () => {},
onRescheduleLaterButtonClick: () => {},
onCreationAbort: () => {},
onCreationDone: () => {},
onCreationStart: () => {},
onMouseOut: () => {},
onMouseOver: () => {},
},
template: 'connector_container',
});
export default ConnectorContainer;

View File

@@ -0,0 +1,127 @@
/** @odoo-module **/
// -----------------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------------
/**
* Clones the value according to its type and returns it.
*
* @param value
* @return {Object|Array|*} The cloned value.
* @private
*/
function _clone(value) {
if (_isPlainObject(value) || Array.isArray(value)) {
return deepMerge(_getEmptyTarget(value), value);
} else {
return value;
}
}
/**
* Gets an empty value according to value's type.
*
* @param {Object | Array} value
* @return {Object | Array} an empty Array or Object.
* @private
*/
function _getEmptyTarget(value) {
return Array.isArray(value) ? [] : { };
}
/**
* Returns whether the provided argument is a plain object or not.
*
* @param {*} value
* @returns {boolean} true if the provided argument is a plain object, false if not.
*/
function _isPlainObject(value) {
if (typeof value == 'object' && value !== null) {
const proto = Object.getPrototypeOf(value);
return proto === Object.prototype || proto === null;
}
return false;
}
/**
* Deep merges target and source arrays and returns the result.
*
* @param {Array} target
* @param {Array} source
* @return {Array} the result of the merge.
* @private
*/
function _deepMergeArray(target, source) {
return target.concat(source)
.map((entry) => _clone(entry));
}
/**
* Deep merges target and source Objects and returns the result
*
* @param {Object} target
* @param {Object} source
* @return {Object} the result of the merge.
*/
function _mergeObject(target, source) {
const destination = { };
if (_isPlainObject(target)) {
Object.keys(target).forEach((key) => {
destination[key] = _clone(target[key]);
});
}
Object.keys(source).forEach((key) => {
if ((_isPlainObject(target) && key in target) && _isPlainObject(source[key])) {
destination[key] = deepMerge(target[key], source[key]);
} else {
destination[key] = _clone(source[key]);
}
});
return destination;
}
// -----------------------------------------------------------------------------
// Public
// -----------------------------------------------------------------------------
/**
* Deep merges target and source and returns the result.
* This implementation has been added since vanilla JS is now preferred.
* A deep copy is made of all the plain objects and arrays.
* For the other type of objects (like HTMLElement, etc.), the reference is passed.
*
* @param {Object | Array} target
* @param {Object | Array} [source] if source is undefined, target wil be set to an empty value of source type.
* @returns {Object | Array} the result of the merge.
*/
export function deepMerge(target, source) {
if (typeof source === 'undefined') {
source = _getEmptyTarget(source);
}
const isSourceAnArray = Array.isArray(source);
const isTargetAnArray = Array.isArray(target);
if (isSourceAnArray !== isTargetAnArray) {
return _clone(source);
} else if (isSourceAnArray) {
return _deepMergeArray(target, source);
} else {
return _mergeObject(target, source);
}
}
/**
* Deep merges all the entries from the passed array and returns the result.
*
* @param {Array} array the elements to be merged together.
* @return {Object | Array} the result of the merge.
*/
export function deepMergeAll(array) {
if (!Array.isArray(array)) {
throw new Error('deepmergeAll argument must be an Array.');
}
return array.reduce((accumulator, current) => deepMerge(accumulator, current), { });
}

View File

@@ -0,0 +1,684 @@
/** @odoo-module alias=web_gantt.GanttController */
import AbstractController from 'web.AbstractController';
import core from 'web.core';
import config from 'web.config';
import { confirm as confirmDialog } from 'web.Dialog';
import { Domain } from '@web/core/domain';
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
const QWeb = core.qweb;
const _t = core._t;
const { Component } = owl;
export function removeDomainLeaf(domain, keysToRemove) {
function processLeaf(elements, idx, operatorCtx, newDomain) {
const leaf = elements[idx];
if (leaf.type === 10) {
if (keysToRemove.includes(leaf.value[0].value)) {
if (operatorCtx === '&') {
newDomain.ast.value.push(...Domain.TRUE.ast.value);
} else if (operatorCtx === '|') {
newDomain.ast.value.push(...Domain.FALSE.ast.value);
}
} else {
newDomain.ast.value.push(leaf);
}
return 1;
} else if (leaf.type === 1) {
// Special case to avoid OR ('|') that can never resolve to true
if (leaf.value === '|' && elements[idx + 1].type === 10 && elements[idx + 2].type === 10
&& keysToRemove.includes(elements[idx + 1].value[0].value)
&& keysToRemove.includes(elements[idx + 2].value[0].value)
) {
newDomain.ast.value.push(...Domain.TRUE.ast.value);
return 3;
}
newDomain.ast.value.push(leaf);
if (leaf.value === '!') {
return 1 + processLeaf(elements, idx + 1, '&', newDomain);
}
const firstLeafSkip = processLeaf(elements, idx + 1, leaf.value, newDomain);
const secondLeafSkip = processLeaf(elements, idx + 1 + firstLeafSkip, leaf.value, newDomain);
return 1 + firstLeafSkip + secondLeafSkip;
}
return 0;
}
domain = new Domain(domain);
if (domain.ast.value.length === 0) {
return domain;
}
const newDomain = new Domain([]);
processLeaf(domain.ast.value, 0, '&', newDomain);
return newDomain;
}
export default AbstractController.extend({
events: _.extend({}, AbstractController.prototype.events, {
'click .o_gantt_button_add': '_onAddClicked',
'click .o_gantt_button_scale': '_onScaleClicked',
'click .o_gantt_button_prev': '_onPrevPeriodClicked',
'click .o_gantt_button_next': '_onNextPeriodClicked',
'click .o_gantt_button_today': '_onTodayClicked',
'click .o_gantt_button_expand_rows': '_onExpandClicked',
'click .o_gantt_button_collapse_rows': '_onCollapseClicked',
}),
custom_events: _.extend({}, AbstractController.prototype.custom_events, {
add_button_clicked: '_onCellAddClicked',
collapse_row: '_onCollapseRow',
expand_row: '_onExpandRow',
on_connector_end_drag: '_onConnectorEndDrag',
on_connector_highlight: '_onConnectorHighlight',
on_connector_start_drag: '_onConnectorStartDrag',
on_create_connector: '_onCreateConnector',
on_pill_highlight: '_onPillHighlight',
on_remove_connector: '_onRemoveConnector',
on_reschedule_according_to_dependency: '_onRescheduleAccordingToDependency',
pill_clicked: '_onPillClicked',
pill_resized: '_onPillResized',
pill_dropped: '_onPillDropped',
plan_button_clicked: '_onCellPlanClicked',
updating_pill_started: '_onPillUpdatingStarted',
updating_pill_stopped: '_onPillUpdatingStopped',
}),
buttonTemplateName: 'GanttView.buttons',
/**
* @override
* @param {Widget} parent
* @param {GanttModel} model
* @param {GanttRenderer} renderer
* @param {Object} params
* @param {Object} params.context
* @param {Array[]} params.dialogViews
* @param {Object} params.SCALES
* @param {boolean} params.collapseFirstLevel
*/
init(parent, model, renderer, params) {
this._super.apply(this, arguments);
this.model = model;
this.context = params.context;
this.dialogViews = params.dialogViews;
this.SCALES = params.SCALES;
this.allowedScales = params.allowedScales;
this.collapseFirstLevel = params.collapseFirstLevel;
this.createAction = params.createAction;
this.actionDomain = params.actionDomain;
this._draggingConnector = false;
this.isRTL = _t.database.parameters.direction === "rtl";
},
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* @override
* @param {jQuery} [$node] to which the buttons will be appended
*/
renderButtons($node) {
this.$buttons = this._renderButtonsQWeb();
if ($node) {
this.$buttons.appendTo($node);
}
},
_renderButtonsQWeb() {
return $(QWeb.render(this.buttonTemplateName, this._renderButtonQWebParameter()));
},
_renderButtonQWebParameter() {
const state = this.model.get();
const nbGroups = state.groupedBy.length;
const minNbGroups = this.collapseFirstLevel ? 0 : 1;
const displayExpandCollapseButtons = nbGroups > minNbGroups;
return {
groupedBy: state.groupedBy,
widget: this,
SCALES: this.SCALES,
activateScale: state.scale,
allowedScales: this.allowedScales,
displayExpandCollapseButtons: displayExpandCollapseButtons,
isMobile: config.device.isMobile,
};
},
/**
* @override
*/
updateButtons() {
if (!this.$buttons) {
return;
}
this.$buttons.html(this._renderButtonsQWeb());
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {integer} id
* @param {Object} schedule
*/
_copy(id, schedule) {
return this._executeAsyncOperation(
this.model.copy.bind(this.model),
[id, schedule]
);
},
/**
* @private
* @param {function} operation
* @param {Array} args
*/
_executeAsyncOperation(operation, args) {
const prom = new Promise((resolve, reject) => {
const asyncOp = operation(...args);
asyncOp.then(resolve).guardedCatch(resolve);
this.dp.add(asyncOp).guardedCatch(reject);
});
return prom.then(this.reload.bind(this, {}));
},
/**
* @private
* @param {OdooEvent} event
*/
_getDialogContext(date, rowId) {
const state = this.model.get();
const context = {};
context[state.dateStartField] = date.clone();
context[state.dateStopField] = date.clone().endOf(this.SCALES[state.scale].interval);
if (rowId) {
// Default values of the group this cell belongs in
// We can read them from any pill in this group row
for (const fieldName of state.groupedBy) {
const groupValue = Object.assign({}, ...JSON.parse(rowId));
let value = groupValue[fieldName];
if (Array.isArray(value)) {
const { type: fieldType } = state.fields[fieldName];
if (fieldType === "many2many") {
value = [value[0]];
} else if (fieldType === "many2one") {
value = value[0];
}
}
if (value !== undefined) {
context[fieldName] = value;
}
}
}
// moment context dates needs to be converted in server time in view
// dialog (for default values)
for (const k in context) {
const type = state.fields[k].type;
if (context[k] && (type === 'datetime' || type === 'date')) {
context[k] = this.model.convertToServerTime(context[k]);
}
}
return context;
},
/**
* Opens dialog to add/edit/view a record
*
* @private
* @param {Object} props FormViewDialog props
* @param {Object} options
*/
_openDialog(props, options = {}) {
const title = props.title || (props.resId ? _t("Open") : _t("Create"));
const onClose = options.onClose || (() => {});
options = {
...options,
onClose: async () => {
onClose();
await this.reload();
},
};
let removeRecord;
if (this.is_action_enabled('delete') && props.resId) {
removeRecord = this._onDialogRemove.bind(this, props.resId)
}
Component.env.services.dialog.add(FormViewDialog, {
title,
resModel: this.modelName,
viewId: this.dialogViews[0][0],
resId: props.resId,
mode: this.is_action_enabled('edit') ? "edit" : "readonly",
context: _.extend({}, this.context, props.context),
removeRecord
}, options);
},
/**
* Handler called when clicking the
* delete button in the edit/view dialog.
* Reload the view and close the dialog
*
* @returns {function}
*/
_onDialogRemove(resID) {
const confirm = new Promise((resolve) => {
confirmDialog(this, _t('Are you sure to delete this record?'), {
confirm_callback: () => {
resolve(true);
},
cancel_callback: () => {
resolve(false);
},
});
});
return confirm.then((confirmed) => {
if ((!confirmed)) {
return Promise.resolve();
}// else
return this._rpc({
model: this.modelName,
method: 'unlink',
args: [[resID,],],
}).then(() => {
return this.reload();
})
});
},
/**
* Get domain of records for plan dialog in the gantt view.
*
* @private
* @param {Object} state
* @returns {Array[]}
*/
_getPlanDialogDomain(state) {
const newDomain = removeDomainLeaf(
this.actionDomain,
[state.dateStartField, state.dateStopField]
);
return Domain.and([
newDomain,
['|', [state.dateStartField, '=', false], [state.dateStopField, '=', false]],
]).toList({});
},
/**
* Opens dialog to plan records.
*
* @private
* @param {Object} context
*/
_openPlanDialog(context) {
const state = this.model.get();
Component.env.services.dialog.add(SelectCreateDialog, {
title: _t("Plan"),
resModel: this.modelName,
domain: this._getPlanDialogDomain(state),
views: this.dialogViews,
context: Object.assign({}, this.context, context),
onSelected: (resIds) => {
if (resIds.length) {
// Here, the dates are already in server time so we set the
// isUTC parameter of reschedule to true to avoid conversion
this._reschedule(resIds, context, true, this.openPlanDialogCallback);
}
},
});
},
/**
* upon clicking on the create button, determines if a dialog with a formview should be opened
* or if a wizard should be openned, then opens it
*
* @param {object} context
*/
_onCreate(context) {
if (this.createAction) {
const fullContext = Object.assign({}, this.context, context);
this.do_action(this.createAction, {
additional_context: fullContext,
on_close: this.reload.bind(this, {})
});
} else {
this._openDialog({ context });
}
},
/**
* Reschedule records and reload.
*
* Use a DropPrevious to prevent unnecessary reload and rendering.
*
* Note that when the rpc fails, we have to reload and re-render as some
* records might be outdated, causing the rpc failure).
*
* @private
* @param {integer[]|integer} ids
* @param {Object} schedule
* @param {boolean} isUTC
* @returns {Promise} resolved when the record has been reloaded, rejected
* if the request has been dropped by DropPrevious
*/
_reschedule(ids, schedule, isUTC, callback) {
return this._executeAsyncOperation(
this.model.reschedule.bind(this.model),
[ids, schedule, isUTC, callback]
);
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Opens a dialog to create a new record.
*
* @private
* @param {OdooEvent} ev
*/
_onCellAddClicked(ev) {
ev.stopPropagation();
const context = this._getDialogContext(ev.data.date, ev.data.rowId);
for (const k in context) {
context[_.str.sprintf('default_%s', k)] = context[k];
}
this._onCreate(context);
},
/**
* @private
* @param {MouseEvent} ev
*/
_onAddClicked(ev) {
ev.preventDefault();
const context = {};
const state = this.model.get();
context[state.dateStartField] = this.model.convertToServerTime(state.focusDate.clone().startOf(state.scale));
context[state.dateStopField] = this.model.convertToServerTime(state.focusDate.clone().endOf(state.scale));
for (const k in context) {
context[_.str.sprintf('default_%s', k)] = context[k];
}
this._onCreate(context);
},
/**
* @private
* @param {MouseEvent} ev
*/
_onCollapseClicked(ev) {
ev.preventDefault();
this.model.collapseRows();
this.update({}, { reload: false });
},
/**
* @private
* @param {OdooEvent} ev
* @param {string} ev.data.rowId
*/
_onCollapseRow(ev) {
ev.stopPropagation();
this.model.collapseRow(ev.data.rowId);
this.renderer.updateRow(this.model.get(ev.data.rowId));
},
/**
* Handler for renderer on-connector-end-drag event.
*
* @param {OdooEvent} ev
* @private
*/
_onConnectorEndDrag(ev) {
ev.stopPropagation();
this._draggingConnector = false;
this.renderer.set_connector_creation_mode(this._draggingConnector);
},
/**
* Handler for renderer on-connector-highlight event.
*
* @param {OdooEvent} ev
* @private
*/
_onConnectorHighlight(ev) {
ev.stopPropagation();
if (!this._updating && !this._draggingConnector) {
this.renderer.toggleConnectorHighlighting(ev.data.connector, ev.data.highlighted);
}
},
/**
* Handler for renderer on-connector-start-drag event.
*
* @param {OdooEvent} ev
* @private
*/
_onConnectorStartDrag(ev) {
ev.stopPropagation();
this._draggingConnector = true;
this.renderer.set_connector_creation_mode(this._draggingConnector);
},
/**
* Handler for renderer on-create-connector event.
*
* @param {OdooEvent} ev
* @returns {Promise<*>}
* @private
*/
async _onCreateConnector(ev) {
ev.stopPropagation();
await this.model.createDependency(ev.data.masterId, ev.data.slaveId);
await this.reload();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onExpandClicked(ev) {
ev.preventDefault();
this.model.expandRows();
this.update({}, { reload: false });
},
/**
* @private
* @param {OdooEvent} ev
* @param {string} ev.data.rowId
*/
_onExpandRow(ev) {
ev.stopPropagation();
this.model.expandRow(ev.data.rowId);
this.renderer.updateRow(this.model.get(ev.data.rowId));
},
/**
* @private
* @param {MouseEvent} ev
*/
_onNextPeriodClicked(ev) {
ev.preventDefault();
const state = this.model.get();
this.update({ date: state.focusDate.add(1, state.scale) });
},
/**
* Opens dialog when clicked on pill to view record.
*
* @private
* @param {OdooEvent} ev
* @param {jQuery} ev.data.target
*/
async _onPillClicked(ev) {
if (!this._updating) {
ev.data.target.addClass('o_gantt_pill_editing');
// Sync with the mutex to wait for potential changes on the view
await this.model.mutex.getUnlockedDef();
const props = { resId: ev.data.target.data('id') };
const options = { onClose: () => ev.data.target.removeClass('o_gantt_pill_editing') };
this._openDialog(props, options);
}
},
/**
* Saves pill information when dragged.
*
* @private
* @param {OdooEvent} ev
* @param {Object} ev.data
* @param {integer} [ev.data.diff]
* @param {integer} [ev.data.groupLevel]
* @param {string} [ev.data.pillId]
* @param {string} [ev.data.newRowId]
* @param {string} [ev.data.oldRowId]
* @param {'copy'|'reschedule'} [ev.data.action]
*/
_onPillDropped(ev) {
ev.stopPropagation();
const state = this.model.get();
const schedule = {};
let diff = ev.data.diff;
diff = this.isRTL ? -diff : diff;
if (diff) {
const pill = _.findWhere(state.records, { id: ev.data.pillId });
schedule[state.dateStartField] = this.model.dateAdd(pill[state.dateStartField], diff, this.SCALES[state.scale].time);
schedule[state.dateStopField] = this.model.dateAdd(pill[state.dateStopField], diff, this.SCALES[state.scale].time);
} else if (ev.data.action === 'copy') {
// When we copy the info on dates is sometimes mandatory (e.g. working on hr.leave, see copy_data)
const pill = _.findWhere(state.records, { id: ev.data.pillId });
schedule[state.dateStartField] = pill[state.dateStartField].clone();
schedule[state.dateStopField] = pill[state.dateStopField].clone();
}
if (ev.data.newRowId && ev.data.newRowId !== ev.data.oldRowId) {
const groupValue = Object.assign({}, ...JSON.parse(ev.data.newRowId));
// if the pill is dragged in a top level group, we only want to
// write on fields linked to this top level group
const fieldsToWrite = state.groupedBy.slice(0, ev.data.groupLevel + 1);
for (const fieldName of fieldsToWrite) {
// TODO: maybe not write if the value hasn't changed?
let valueToWrite = groupValue[fieldName];
if (Array.isArray(valueToWrite)) {
const { type: fieldType } = state.fields[fieldName];
if (fieldType === "many2many") {
valueToWrite = [valueToWrite[0]];
} else if (fieldType === "many2one") {
valueToWrite = valueToWrite[0];
}
}
schedule[fieldName] = valueToWrite;
}
}
if (ev.data.action === 'copy') {
this._copy(ev.data.pillId, schedule);
} else {
this._reschedule(ev.data.pillId, schedule);
}
},
/**
* Handler for renderer on-connector-end-drag event.
*
* @param {OdooEvent} ev
* @private
*/
async _onPillHighlight(ev) {
ev.stopPropagation();
if (!this._updating || !ev.data.highlighted) {
await this.renderer.togglePillHighlighting(ev.data.element, ev.data.highlighted);
}
},
/**
* Save pill information when resized
*
* @private
* @param {OdooEvent} ev
*/
_onPillResized(ev) {
ev.stopPropagation();
const schedule = {};
schedule[ev.data.field] = ev.data.date;
this._reschedule(ev.data.id, schedule);
},
/**
* @private
* @param {OdooEvent} ev
*/
_onPillUpdatingStarted(ev) {
ev.stopPropagation();
this._updating = true;
this.renderer.togglePreventConnectorsHoverEffect(true);
},
/**
* @private
* @param {OdooEvent} ev
*/
_onPillUpdatingStopped(ev) {
ev.stopPropagation();
this._updating = false;
this.renderer.togglePreventConnectorsHoverEffect(false);
},
/**
* Opens a dialog to plan records.
*
* @private
* @param {OdooEvent} ev
*/
_onCellPlanClicked(ev) {
ev.stopPropagation();
const context = this._getDialogContext(ev.data.date, ev.data.rowId);
this._openPlanDialog(context);
},
/**
* @private
* @param {MouseEvent} ev
*/
_onPrevPeriodClicked(ev) {
ev.preventDefault();
const state = this.model.get();
this.update({ date: state.focusDate.subtract(1, state.scale) });
},
/**
* Handler for renderer on-remove-connector event.
*
* @param {OdooEvent} ev
* @private
*/
async _onRemoveConnector(ev) {
ev.stopPropagation();
await this.model.removeDependency(ev.data.masterId, ev.data.slaveId);
await this.reload();
},
/**
* Handler for renderer on-reschedule-according-to-dependency event.
*
* @param {OdooEvent} ev
* @private
*/
async _onRescheduleAccordingToDependency(ev) {
ev.stopPropagation();
const result = await this.model.rescheduleAccordingToDependency(
ev.data.direction,
ev.data.masterId,
ev.data.slaveId);
if (result === false) {
return
} else {
await this.reload();
if (result.type == 'ir.actions.client') {
this.do_action(result);
}
}
},
/**
* @private
* @param {MouseEvent} ev
*/
_onScaleClicked(ev) {
ev.preventDefault();
const $button = $(ev.currentTarget);
if ($button.hasClass('active')) {
return;
}
this.update({ scale: $button.data('value') });
},
/**
* @private
* @param {MouseEvent} ev
*/
_onTodayClicked(ev) {
ev.preventDefault();
this.update({ date: moment() });
},
});

View File

@@ -0,0 +1,793 @@
/** @odoo-module alias=web_gantt.GanttModel */
import AbstractModel from 'web.AbstractModel';
import { x2ManyCommands } from '@web/core/orm_service';
import concurrency from 'web.concurrency';
import core from 'web.core';
import fieldUtils from 'web.field_utils';
import { findWhere, groupBy } from 'web.utils';
import session from 'web.session';
const _t = core._t;
export default AbstractModel.extend({
/**
* @override
*/
init(parent, params = {}) {
this._super.apply(this, arguments);
this.dp = new concurrency.DropPrevious();
this.mutex = new concurrency.Mutex();
this.dependencyField = params.dependencyField;
this.dependencyInvertedField = params.dependencyInvertedField;
},
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* Collapses the given row.
*
* @param {string} rowId
*/
collapseRow(rowId) {
this.allRows[rowId].isOpen = false;
},
/**
* Collapses all rows (first level only).
*/
collapseRows() {
this.ganttData.rows.forEach((group) => {
group.isOpen = false;
});
},
/**
* Convert date to server timezone
*
* @param {Moment} date
* @returns {string} date in server format
*/
convertToServerTime(date) {
const result = date.clone();
if (!result.isUTC()) {
result.subtract(session.getTZOffset(date), 'minutes');
}
return result.locale('en').format('YYYY-MM-DD HH:mm:ss');
},
/**
* Adds a dependency between masterId and slaveId (slaveId depends
* on masterId).
*
* @param masterId
* @param slaveId
* @returns {Promise<*>}
*/
async createDependency(masterId, slaveId) {
return this.mutex.exec(() => {
const writeCommand = {};
writeCommand[this.dependencyField] = [x2ManyCommands.linkTo(masterId)];
return this._rpc({
model: this.modelName,
method: 'write',
args: [[slaveId], writeCommand],
});
});
},
/**
* Add or subtract value to a moment.
* If we are changing by a whole day or more, adjust the time if needed to keep
* the same local time, if the UTC offset has changed between the 2 dates
* (usually, because of daylight savings)
*
* @param {Moment} date
* @param {integer} offset
* @param {string} unit
*/
dateAdd(date, offset, unit) {
const result = date.clone().add(offset, unit);
if(Math.abs(result.diff(date, 'hours')) >= 24) {
const tzOffsetDiff = result.clone().local().utcOffset() - date.clone().local().utcOffset();
if(tzOffsetDiff !== 0) {
result.subtract(tzOffsetDiff, 'minutes');
}
}
return result;
},
/**
* @override
* @param {string} [rowId]
* @returns {Object} the whole gantt data if no rowId given, the given row's
* description otherwise
*/
__get(rowId) {
if (rowId) {
return this.allRows[rowId];
} else {
return Object.assign({ isSample: this.isSampleModel }, this.ganttData);
}
},
/**
* Expands the given row.
*
* @param {string} rowId
*/
expandRow(rowId) {
this.allRows[rowId].isOpen = true;
},
/**
* Expands all rows.
*/
expandRows() {
Object.keys(this.allRows).forEach((rowId) => {
const row = this.allRows[rowId];
if (row.isGroup) {
this.allRows[rowId].isOpen = true;
}
});
},
/**
* @override
* @param {Object} params
* @param {Object} params.context
* @param {Object} params.colorField
* @param {string} params.dateStartField
* @param {string} params.dateStopField
* @param {string[]} params.decorationFields
* @param {string} params.defaultGroupBy
* @param {string} params.permanentGroupBy
* @param {boolean} params.displayUnavailability
* @param {Array[]} params.domain
* @param {Object} params.fields
* @param {boolean} params.dynamicRange
* @param {string[]} params.groupedBy
* @param {Moment} params.initialDate
* @param {string} params.modelName
* @param {string} params.scale
* @returns {Promise<any>}
*/
async __load(params) {
await this._super(...arguments);
this.modelName = params.modelName;
this.fields = params.fields;
this.domain = params.domain;
this.context = params.context;
this.decorationFields = params.decorationFields;
this.colorField = params.colorField;
this.progressField = params.progressField;
this.consolidationParams = params.consolidationParams;
this.collapseFirstLevel = params.collapseFirstLevel;
this.displayUnavailability = params.displayUnavailability;
this.SCALES = params.SCALES;
this.progressBarFields = params.progressBarFields ? params.progressBarFields.split(",") : false;
this.defaultGroupBy = params.defaultGroupBy ? params.defaultGroupBy.split(',') : [];
this.permanentGroupBy = params.permanentGroupBy
let groupedBy = params.groupedBy;
if (!groupedBy || !groupedBy.length) {
groupedBy = this.defaultGroupBy;
}
if (this.permanentGroupBy && !groupedBy.includes(this.permanentGroupBy)) {
groupedBy.push(this.permanentGroupBy)
}
groupedBy = this._filterDateInGroupedBy(groupedBy);
this.ganttData = {
dateStartField: params.dateStartField,
dateStopField: params.dateStopField,
groupedBy,
fields: params.fields,
dynamicRange: params.dynamicRange,
};
this._setRange(params.initialDate, params.scale);
return this._fetchData().then(() => {
// The 'load' function returns a promise which resolves with the
// handle to pass to the 'get' function to access the data. In this
// case, we don't want to pass any argument to 'get' (see its API).
return Promise.resolve();
});
},
/**
* @param {any} handle
* @param {Object} params
* @param {Array[]} params.domain
* @param {string[]} params.groupBy
* @param {string} params.scale
* @param {Moment} params.date
* @returns {Promise<any>}
*/
async __reload(handle, params) {
await this._super(...arguments);
if ('scale' in params) {
this._setRange(this.ganttData.focusDate, params.scale);
}
if ('date' in params) {
this._setRange(params.date, this.ganttData.scale);
}
if ('domain' in params) {
this.domain = params.domain;
}
if ('groupBy' in params) {
if (params.groupBy && params.groupBy.length) {
this.ganttData.groupedBy = this._filterDateInGroupedBy(params.groupBy);
if(this.ganttData.groupedBy.length !== params.groupBy.length){
this.displayNotification({ message: _t('Grouping by date is not supported'), type: 'danger' });
}
if (this.permanentGroupBy && !this.ganttData.groupedBy.includes(this.permanentGroupBy)) {
this.ganttData.groupedBy.push(this.permanentGroupBy)
}
} else {
this.ganttData.groupedBy = this.defaultGroupBy;
}
}
return this._fetchData().then(() => {
// The 'reload' function returns a promise which resolves with the
// handle to pass to the 'get' function to access the data. In this
// case, we don't want to pass any argument to 'get' (see its API).
return Promise.resolve();
});
},
/**
* Create a copy of a task with defaults determined by schedule.
*
* @param {integer} id
* @param {Object} schedule
* @returns {Promise}
*/
copy(id, schedule) {
const defaults = this.rescheduleData(schedule);
return this.mutex.exec(() => {
return this._rpc({
model: this.modelName,
method: 'copy',
args: [id, defaults],
context: this.context,
});
});
},
/**
* Removes the dependency between masterId and slaveId (slaveId is no
* more dependent on masterId).
*
* @param masterId
* @param slaveId
* @returns {Promise<*>}
*/
async removeDependency(masterId, slaveId) {
return this.mutex.exec(() => {
const writeCommand = {};
writeCommand[this.dependencyField] = [x2ManyCommands.forget(masterId)];
return this._rpc({
model: this.modelName,
method: 'write',
args: [[slaveId], writeCommand],
});
});
},
/**
* Reschedule a task to the given schedule.
*
* @param {integer} id
* @param {Object} schedule
* @param {boolean} isUTC
* @returns {Promise}
*/
reschedule(ids, schedule, isUTC, callback) {
if (!_.isArray(ids)) {
ids = [ids];
}
const data = this.rescheduleData(schedule, isUTC);
return this.mutex.exec(() => {
return this._rpc({
model: this.modelName,
method: 'write',
args: [ids, data],
context: this.context,
}).then((result) => {
if (callback) {
callback(result);
}
});
});
},
/**
* Reschedule masterId or slaveId according to the direction
*
* @param direction
* @param masterId
* @param slaveId
* @returns {Promise<*>}
*/
async rescheduleAccordingToDependency(direction, masterId, slaveId) {
return this.mutex.exec(() => {
return this._rpc({
model: this.modelName,
method: 'web_gantt_reschedule',
args: [
direction,
masterId,
slaveId,
this.dependencyField,
this.dependencyInvertedField,
this.ganttData.dateStartField,
this.ganttData.dateStopField
],
});
});
},
/**
* @param {Object} schedule
* @param {boolean} isUTC
*/
rescheduleData(schedule, isUTC) {
const allowedFields = [
this.ganttData.dateStartField,
this.ganttData.dateStopField,
...this.ganttData.groupedBy
];
const data = _.pick(schedule, allowedFields);
let type;
for (let k in data) {
type = this.fields[k].type;
if (data[k] && (type === 'datetime' || type === 'date') && !isUTC) {
data[k] = this.convertToServerTime(data[k]);
}
};
return data
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Fetches records to display (and groups if necessary).
*
* @private
* @returns {Deferred}
*/
_fetchData() {
const domain = this._getDomain();
const context = Object.assign({}, this.context, { group_by: this.ganttData.groupedBy });
let groupsDef;
if (this.ganttData.groupedBy.length) {
groupsDef = this._rpc({
model: this.modelName,
method: 'read_group',
fields: this._getFields(),
domain: domain,
context: context,
groupBy: this.ganttData.groupedBy,
orderBy: this.ganttData.groupedBy.map((f) => { return {name: f}; }),
lazy: this.ganttData.groupedBy.length === 1,
});
}
const dataDef = this._rpc({
route: '/web/dataset/search_read',
model: this.modelName,
fields: this._getFields(),
context: context,
orderBy: [{name: this.ganttData.dateStartField}],
domain: domain,
});
return this.dp.add(Promise.all([groupsDef, dataDef])).then((results) => {
const groups = results[0] || [];
groups.forEach((g) => (g.fromServer = true));
const searchReadResult = results[1];
const oldRows = this.allRows;
this.allRows = {};
this.ganttData.records = this._parseServerData(searchReadResult.records);
this.ganttData.rows = this._generateRows({
groupedBy: this.ganttData.groupedBy,
groups: groups,
oldRows: oldRows,
parentPath: [],
records: this.ganttData.records,
});
const proms = [];
if (this.displayUnavailability && !this.isSampleModel) {
proms.push(this._fetchUnavailability());
}
if (this.progressBarFields && !this.isSampleModel) {
proms.push(this._fetchProgressBarData());
}
return Promise.all(proms);
});
},
/**
* Compute rows for unavailability rpc call.
*
* @private
* @param {Object} rows in the format of ganttData.rows
* @returns {Object} simplified rows only containing useful attributes
*/
_computeUnavailabilityRows(rows) {
return _.map(rows, (r) => {
if (r) {
return {
groupedBy: r.groupedBy,
records: r.records,
name: r.name,
resId: r.resId,
rows: this._computeUnavailabilityRows(r.rows)
}
} else {
return r;
}
});
},
/**
* Fetches gantt unavailability.
*
* @private
* @returns {Deferred}
*/
_fetchUnavailability() {
return this._rpc({
model: this.modelName,
method: 'gantt_unavailability',
args: [
this.convertToServerTime(this.ganttData.startDate),
this.convertToServerTime(this.ganttData.stopDate),
this.ganttData.scale,
this.ganttData.groupedBy,
this._computeUnavailabilityRows(this.ganttData.rows),
],
context: this.context,
}).then((enrichedRows) => {
// Update ganttData.rows with the new unavailabilities data
this._updateUnavailabilityRows(this.ganttData.rows, enrichedRows);
});
},
/**
* Update rows with unavailabilities from enriched rows.
*
* @private
* @param {Object} original rows in the format of ganttData.rows
* @param {Object} enriched rows as returned by the gantt_unavailability rpc call
* @returns {Object} original rows enriched with the unavailabilities data
*/
_updateUnavailabilityRows(original, enriched) {
_.zip(original, enriched).forEach((rowPair) => {
const o = rowPair[0];
const e = rowPair[1];
o.unavailabilities = _.map(e.unavailabilities, (u) => {
// These are new data from the server, they haven't been parsed yet
u.start = this._parseServerValue({ type: 'datetime' }, u.start);
u.stop = this._parseServerValue({ type: 'datetime' }, u.stop);
return u;
});
if (o.rows && e.rows) {
this._updateUnavailabilityRows(o.rows, e.rows);
}
});
},
/**
* Process groups and records to generate a recursive structure according
* to groupedBy fields. Note that there might be empty groups (filled by
* read_goup with group_expand) that also need to be processed.
*
* @private
* @param {Object} params
* @param {Object[]} params.groups
* @param {Object[]} params.records
* @param {string[]} params.groupedBy
* @param {Object} params.oldRows previous version of this.allRows (prior to
* this reload), used to keep collapsed rows collapsed
* @param {Object[]} params.parentPath used to determine the ancestors of a
* row through their groupedBy field and value.
* The stringification of this must give a unique identifier to the parent row.
* @returns {Object[]}
*/
_generateRows(params) {
const { groupedBy, groups, oldRows, parentPath, records } = params;
const groupLevel = this.ganttData.groupedBy.length - groupedBy.length;
if (!groupedBy.length || !groups.length) {
const row = {
groupLevel,
id: JSON.stringify([...parentPath, {}]),
isGroup: false,
name: "",
records,
};
this.allRows[row.id] = row;
return [row];
}
const rows = [];
// Some groups might be empty (thanks to expand_groups), so we can't
// simply group the data, we need to keep all returned groups
const groupedByField = groupedBy[0];
const currentLevelGroups = groupBy(groups, group => {
if (group[groupedByField] === undefined) {
// Here we change undefined value to false as:
// 1/ we want to group together:
// - groups having an undefined value for groupedByField
// - groups having false value for groupedByField
// 2/ we want to be sure that stringification keeps
// the groupedByField because of:
// JSON.stringify({ key: undefined }) === "{}"
// (see id construction below)
group[groupedByField] = false;
}
return group[groupedByField];
});
const isM2MGrouped = this.ganttData.fields[groupedByField].type === "many2many";
let groupedRecords;
if (isM2MGrouped) {
groupedRecords = {};
for (const [key, currentGroup] of Object.entries(currentLevelGroups)) {
groupedRecords[key] = [];
const value = currentGroup[0][groupedByField];
for (const r of records || []) {
if (
!value && r[groupedByField].length === 0 ||
value && r[groupedByField].includes(value[0])
) {
groupedRecords[key].push(r)
}
}
}
} else {
groupedRecords = groupBy(records || [], groupedByField);
}
for (const key in currentLevelGroups) {
const subGroups = currentLevelGroups[key];
const groupRecords = groupedRecords[key] || [];
// For empty groups (or when groupedByField is a m2m), we can't look at the record to get the
// formatted value of the field, we have to trust expand_groups.
let value;
if (groupRecords && groupRecords.length && !isM2MGrouped) {
value = groupRecords[0][groupedByField];
} else {
value = subGroups[0][groupedByField];
}
const part = {};
part[groupedByField] = value;
const path = [...parentPath, part];
const id = JSON.stringify(path);
const resId = Array.isArray(value) ? value[0] : value;
const minNbGroups = this.collapseFirstLevel ? 0 : 1;
const isGroup = groupedBy.length > minNbGroups;
const fromServer = subGroups.some((g) => g.fromServer);
const row = {
name: this._getRowName(groupedByField, value),
groupedBy,
groupedByField,
groupLevel,
id,
resId,
isGroup,
fromServer,
isOpen: !findWhere(oldRows, { id: JSON.stringify(parentPath), isOpen: false }),
records: groupRecords,
};
if (isGroup) {
row.rows = this._generateRows({
...params,
groupedBy: groupedBy.slice(1),
groups: subGroups,
oldRows,
parentPath: path,
records: groupRecords,
});
row.childrenRowIds = [];
row.rows.forEach((subRow) => {
row.childrenRowIds.push(subRow.id);
row.childrenRowIds = row.childrenRowIds.concat(subRow.childrenRowIds || []);
});
}
rows.push(row);
this.allRows[row.id] = row;
}
return rows;
},
/**
* Get domain of records to display in the gantt view.
*
* @private
* @returns {Array[]}
*/
_getDomain() {
const domain = [
[this.ganttData.dateStartField, '<=', this.convertToServerTime(this.ganttData.stopDate)],
[this.ganttData.dateStopField, '>=', this.convertToServerTime(this.ganttData.startDate)],
];
return this.domain.concat(domain);
},
/**
* Get all the fields needed.
*
* @private
* @returns {string[]}
*/
_getFields() {
let fields = ['display_name', this.ganttData.dateStartField, this.ganttData.dateStopField];
fields = fields.concat(this.ganttData.groupedBy, this.decorationFields);
if (this.progressField) {
fields.push(this.progressField);
}
if (this.colorField) {
fields.push(this.colorField);
}
if (this.consolidationParams.field) {
fields.push(this.consolidationParams.field);
}
if (this.consolidationParams.excludeField) {
fields.push(this.consolidationParams.excludeField);
}
return _.uniq(fields);
},
/**
* Format field value to display purpose.
*
* @private
* @param {any} value
* @param {Object} field
* @returns {string} formatted field value
*/
_getFieldFormattedValue(value, field) {
let options = {};
if (field.type === 'boolean') {
options = {forceString: true};
}
let label;
if (field.type === "many2many") {
label = Array.isArray(value) ? value[1] : value;
} else {
label = fieldUtils.format[field.type](value, field, options);
}
return label || _.str.sprintf(_t('Undefined %s'), field.string);
},
/**
* @param {string} groupedByField
* @param {*} value
* @returns {string}
*/
_getRowName(groupedByField, value) {
const field = this.fields[groupedByField];
return this._getFieldFormattedValue(value, field);
},
/**
* @override
*/
_isEmpty() {
return !this.ganttData.records.length;
},
/**
* Parse in place the server values (and in particular, convert datetime
* field values to moment in UTC).
*
* @private
* @param {Object} data the server data to parse
* @returns {Promise<any>}
*/
_parseServerData(data) {
data.forEach((record) => {
Object.keys(record).forEach((fieldName) => {
record[fieldName] = this._parseServerValue(this.fields[fieldName], record[fieldName]);
});
});
return data;
},
/**
* Set date range to render gantt
*
* @private
* @param {Moment} focusDate current activated date
* @param {string} scale current activated scale
*/
_setRange(focusDate, scale) {
this.ganttData.scale = scale;
this.ganttData.focusDate = focusDate;
if (this.ganttData.dynamicRange) {
this.ganttData.startDate = focusDate.clone().startOf(this.SCALES[scale].interval);
this.ganttData.stopDate = this.ganttData.startDate.clone().add(1, scale);
} else {
this.ganttData.startDate = focusDate.clone().startOf(scale);
this.ganttData.stopDate = focusDate.clone().endOf(scale);
}
},
/**
* Remove date in groupedBy field
*/
_filterDateInGroupedBy(groupedBy) {
return groupedBy.filter(
groupedByField => {
const fieldName = groupedByField.split(':')[0];
return fieldName in this.fields && this.fields[fieldName].type.indexOf('date') === -1;
}
);
},
//----------------------
// Gantt Progress Bars
//----------------------
/**
* Get progress bars info in order to display progress bar in gantt title column
*
* @private
*/
_fetchProgressBarData() {
const progressBarFields = this.progressBarFields.filter(field => this.ganttData.groupedBy.includes(field));
if (this.isSampleModel || !progressBarFields.length) {
return;
}
const resIds = {};
let hasResIds = false;
for (const field of progressBarFields) {
resIds[field] = this._getProgressBarResIds(field, this.ganttData.rows);
hasResIds = hasResIds || resIds[field].length;
}
if (!hasResIds) {
return;
}
return this._rpc({
model: this.modelName,
method: 'gantt_progress_bar',
args: [
progressBarFields,
resIds,
this.convertToServerTime(this.ganttData.startDate),
this.convertToServerTime(this.ganttData.endDate || this.ganttData.startDate.clone().add(1, this.ganttData.scale)),
],
}).then((progressBarInfo) => {
for (const field of progressBarFields) {
this._addProgressBarInfo(field, this.ganttData.rows, progressBarInfo[field]);
}
});
},
/**
* Recursive function to get resIds of groups where the progress bar will be added.
*
* @private
*/
_getProgressBarResIds(field, rows) {
const resIds = [];
for (const row of rows) {
if (row.groupedByField === field) {
if (row.resId !== false) {
resIds.push(row.resId);
}
} else {
resIds.push(...this._getProgressBarResIds(field, row.rows || []));
}
}
return [...new Set(resIds)];
},
/**
* Recursive function to add progressBar info to rows grouped by the field.
*
* @private
*/
_addProgressBarInfo(field, rows, progressBarInfo) {
for (const row of rows) {
if (row.groupedByField === field) {
row.progressBar = progressBarInfo[row.resId];
if (row.progressBar) {
row.progressBar.value_formatted = fieldUtils.format.float(row.progressBar.value, {'digits': [false, 0]});
row.progressBar.max_value_formatted = fieldUtils.format.float(row.progressBar.max_value, {'digits': [false, 0]});
row.progressBar.ratio = row.progressBar.max_value ? row.progressBar.value / row.progressBar.max_value * 100 : 0;
row.progressBar.warning = progressBarInfo.warning;
}
} else {
this._addProgressBarInfo(field, row.rows, progressBarInfo);
}
}
},
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,189 @@
/** @odoo-module alias=web_gantt.GanttView */
import AbstractView from 'web.AbstractView';
import core from 'web.core';
import GanttModel from 'web_gantt.GanttModel';
import GanttRenderer from 'web_gantt.GanttRenderer';
import GanttController from 'web_gantt.GanttController';
import pyUtils from 'web.py_utils';
import view_registry from 'web.view_registry';
const _t = core._t;
const _lt = core._lt;
const GanttView = AbstractView.extend({
display_name: _lt('Gantt'),
icon: 'fa fa-tasks',
config: _.extend({}, AbstractView.prototype.config, {
Model: GanttModel,
Controller: GanttController,
Renderer: GanttRenderer,
}),
jsLibs: [
'/web/static/lib/nearest/jquery.nearest.js',
],
viewType: 'gantt',
/**
* @override
*/
init(viewInfo, params) {
this._super.apply(this, arguments);
const { domain } = params.action || {};
this.controllerParams.actionDomain = domain || [];
this.SCALES = {
day: { string: _t('Day'), hotkey: 'e', cellPrecisions: { full: 60, half: 30, quarter: 15 }, defaultPrecision: 'full', time: 'minutes', interval: 'hour' },
week: { string: _t('Week'), hotkey: 'p', cellPrecisions: { full: 24, half: 12 }, defaultPrecision: 'half', time: 'hours', interval: 'day' },
month: { string: _t('Month'), hotkey: 'm', cellPrecisions: { full: 24, half: 12 }, defaultPrecision: 'half', time: 'hours', interval: 'day' },
year: { string: _t('Year'), hotkey: 'y', cellPrecisions: { full: 1 }, defaultPrecision: 'full', time: 'months', interval: 'month' },
};
const arch = this.arch;
// Decoration fields
const decorationFields = [];
_.each(arch.children, (child) => {
if (child.tag === 'field') {
decorationFields.push(child.attrs.name);
}
});
let collapseFirstLevel = !!arch.attrs.collapse_first_level;
// Unavailability
const displayUnavailability = !!arch.attrs.display_unavailability;
// Colors
const colorField = arch.attrs.color;
// Cell precision
// precision = {'day': 'hour:half', 'week': 'day:half', 'month': 'day', 'year': 'month:quarter'}
const precisionAttrs = arch.attrs.precision ? pyUtils.py_eval(arch.attrs.precision) : {};
const cellPrecisions = {};
_.each(this.SCALES, (vals, key) => {
if (precisionAttrs[key]) {
const precision = precisionAttrs[key].split(':'); // hour:half
// Note that precision[0] (which is the cell interval) is not
// taken into account right now because it is no customizable.
if (precision[1] && _.contains(_.keys(vals.cellPrecisions), precision[1])) {
cellPrecisions[key] = precision[1];
}
}
cellPrecisions[key] = cellPrecisions[key] || vals.defaultPrecision;
});
let consolidationMaxField;
let consolidationMaxValue;
const consolidationMax = arch.attrs.consolidation_max ? pyUtils.py_eval(arch.attrs.consolidation_max) : {};
if (Object.keys(consolidationMax).length > 0) {
consolidationMaxField = Object.keys(consolidationMax)[0];
consolidationMaxValue = consolidationMax[consolidationMaxField];
// We need to display the aggregates even if there is only one groupby
collapseFirstLevel = !!consolidationMaxField || collapseFirstLevel;
}
const consolidationParams = {
field: arch.attrs.consolidation,
maxField: consolidationMaxField,
maxValue: consolidationMaxValue,
excludeField: arch.attrs.consolidation_exclude,
};
// form view which is opened by gantt
let formViewId = arch.attrs.form_view_id ? parseInt(arch.attrs.form_view_id, 10) : false;
if (params.action && !formViewId) { // fallback on form view action, or 'false'
const result = _.findWhere(params.action.views, { type: 'form' });
formViewId = result ? result.viewID : false;
}
const dialogViews = [[formViewId, 'form']];
let allowedScales;
if (arch.attrs.scales) {
const possibleScales = Object.keys(this.SCALES);
allowedScales = _.reduce(arch.attrs.scales.split(','), (allowedScales, scale) => {
if (possibleScales.indexOf(scale) >= 0) {
allowedScales.push(scale.trim());
}
return allowedScales;
}, []);
} else {
allowedScales = Object.keys(this.SCALES);
}
const scale = params.context.default_scale || arch.attrs.default_scale || 'month';
const initialDate = moment(params.context.initialDate || params.initialDate || arch.attrs.initial_date || new Date());
const offset = arch.attrs.offset;
if (offset && scale) {
initialDate.add(offset, scale);
}
// thumbnails for groups (display a thumbnail next to the group name)
const thumbnails = this.arch.attrs.thumbnails ? pyUtils.py_eval(this.arch.attrs.thumbnails) : {};
// plan option
const canPlan = this.arch.attrs.plan ? !!JSON.parse(this.arch.attrs.plan) : true;
// cell create option
const canCellCreate = this.arch.attrs.cell_create ? !!JSON.parse(this.arch.attrs.cell_create) : true;
// Dependencies
const dependencyField = !!this.arch.attrs.dependency_field && this.arch.attrs.dependency_field;
const dependencyInvertedField = !!this.arch.attrs.dependency_inverted_field && this.arch.attrs.dependency_inverted_field;
if (dependencyField) {
decorationFields.push(dependencyField);
}
this.controllerParams.context = params.context || {};
this.controllerParams.dialogViews = dialogViews;
this.controllerParams.SCALES = this.SCALES;
this.controllerParams.allowedScales = allowedScales;
this.controllerParams.collapseFirstLevel = collapseFirstLevel;
this.controllerParams.createAction = arch.attrs.on_create || null;
this.loadParams.initialDate = initialDate;
this.loadParams.collapseFirstLevel = collapseFirstLevel;
this.loadParams.colorField = colorField;
this.loadParams.dateStartField = arch.attrs.date_start;
this.loadParams.dateStopField = arch.attrs.date_stop;
this.loadParams.progressField = arch.attrs.progress;
this.loadParams.decorationFields = decorationFields;
this.loadParams.defaultGroupBy = this.arch.attrs.default_group_by;
this.loadParams.permanentGroupBy = this.arch.attrs.permanent_group_by;
this.loadParams.dynamicRange = this.arch.attrs.dynamic_range;
this.loadParams.displayUnavailability = displayUnavailability;
this.loadParams.fields = this.fields;
this.loadParams.scale = scale;
this.loadParams.SCALES = this.SCALES;
this.loadParams.consolidationParams = consolidationParams;
this.loadParams.progressBarFields = arch.attrs.progress_bar;
this.modelParams.dependencyField = dependencyField;
this.modelParams.dependencyInvertedField = dependencyInvertedField;
this.rendererParams.canCreate = this.controllerParams.activeActions.create;
this.rendererParams.canCellCreate = canCellCreate;
this.rendererParams.canEdit = this.controllerParams.activeActions.edit;
this.rendererParams.canPlan = canPlan && this.rendererParams.canEdit;
this.rendererParams.fieldsInfo = viewInfo.fields;
this.rendererParams.SCALES = this.SCALES;
this.rendererParams.cellPrecisions = cellPrecisions;
this.rendererParams.totalRow = arch.attrs.total_row || false;
this.rendererParams.string = arch.attrs.string || _t('Gantt View');
this.rendererParams.popoverTemplate = _.findWhere(arch.children, {tag: 'templates'});
this.rendererParams.colorField = colorField;
this.rendererParams.disableDragdrop = arch.attrs.disable_drag_drop ? !!JSON.parse(arch.attrs.disable_drag_drop) : false;
this.rendererParams.progressField = arch.attrs.progress;
this.rendererParams.displayUnavailability = displayUnavailability;
this.rendererParams.collapseFirstLevel = collapseFirstLevel;
this.rendererParams.consolidationParams = consolidationParams;
this.rendererParams.thumbnails = thumbnails;
this.rendererParams.progressBarFields = arch.attrs.progress_bar;
this.rendererParams.pillLabel = !!arch.attrs.pill_label;
this.rendererParams.dependencyEnabled = !!this.modelParams.dependencyField
this.rendererParams.dependencyField = this.modelParams.dependencyField
},
});
view_registry.add('gantt', GanttView);
export default GanttView;

View File

@@ -0,0 +1,756 @@
// Define the necessary conditions to provide visual feedback on hover,
// focus, drag, clone and resize.
@mixin o-gantt-hover() {
&:hover, &:focus, &.ui-draggable-dragging, &.ui-resizable-resize {
// Avoid visual feedback if 'o_gantt_view' has class 'o_grabbing' or 'o_copying'.
@at-root #{selector-replace(&, ".o_gantt_view", ".o_gantt_view:not(.o_grabbing):not(.o_copying):not(.o_no_dragging)")} {
@content;
}
}
}
// Generate background and text for each color.
@mixin o-gantt-hoverable-colors($color) {
$color-subdle: mix($color, white, 60%);
color: color-contrast($color-subdle);
background-color: $color-subdle;
cursor: pointer;
@include o-gantt-hover() {
background-color: $color;
color: color-contrast($color);
}
}
// Generate stripes decorations for each color.
@mixin gantt-gradient-decorations($color) {
$color-subdle: mix($color, white, 60%);
background-image: repeating-linear-gradient(-45deg, $color-subdle 0 10px, lighten($color-subdle, 6%) 10px 20px);
@include o-gantt-hover() {
background-image: repeating-linear-gradient(-45deg, $color 0 10px, lighten($color, 6%) 10px 20px);
}
}
@mixin gantt-ribbon-decoration($color) {
content: '';
width: 20px;
height: 16px;
@include o-position-absolute(-11px, $left: -13px);
box-shadow: 1px 1px 0 white;
background: $color;
transform: rotate(45deg);
}
@mixin gant-today-cell() {
&.o_gantt_today {
border-color: mix($gantt-highlight-today-border, $gantt-border-color, 25%);
border-left-color: $gantt-highlight-today-border;
background-color: $gantt-highlight-today-bg;
+ .o_gantt_header_cell, + .o_gantt_cell {
border-left-color: $gantt-highlight-today-border;
}
&.o_gantt_unavailability {
background: mix($gantt-highlight-today-bg, $gantt-unavailability-bg);
}
}
}
.o_gantt_view {
// Allows to use color variables in js
--Gant__Day-background-color: #{$o-view-background-color};
--Gant__DayOff-background-color: #e9ecef;
--Gant__DayOffToday-background-color: #fffaeb;
box-shadow: 0 5px 20px -15px rgba(black, .3);
user-select: none;
@include media-breakpoint-down(md) {
.o_gantt_view_container {
width: max-content;
}
}
#o_gantt_containment {
@include o-position-absolute(0, 0, 1px, percentage(2 / $grid-columns));
}
// =============== Cursors while dragging ==============
// =======================================================
&.o_grabbing, &.o_grabbing .o_gantt_pill {
cursor: move!important;
}
&.o_copying, &.o_copying .o_gantt_pill {
cursor: copy!important;
}
&.o_no_dragging {
.o_gantt_cell_buttons, .ui-resizable-handle {
visibility: hidden;
}
&, .o_gantt_pill {
cursor: not-allowed!important;
}
}
&.o_grabbing, &.o_copying {
.o_gantt_cell_buttons,
.ui-draggable-dragging:before,
.ui-draggable-dragging .ui-resizable-handle {
visibility: hidden;
}
}
.o_dragged_pill {
opacity: .5;
}
.ui-draggable-dragging {
opacity: .8;
transform: rotate(-3deg);
box-shadow: 0 5px 25px -10px black;
transition: transform 0.6s, box-shadow 0.3s;
}
// =============== Header ==============
// =======================================
.o_gantt_header_container {
top: 0;
z-index: 10; // header should overlap the pills
.o_gantt_row_sidebar {
box-shadow: inset 0 -1px 0 $gantt-border-color;
line-height: 4.8rem;
}
.o_gantt_header_slots {
box-shadow: inset 1px 0 0 $gantt-border-color;
}
.o_gantt_header_scale {
border-top: 1px solid $gantt-border-color;
border-bottom: 1px solid $gantt-border-color;
}
.o_gantt_header_cell {
@include gant-today-cell();
border-left: 1px solid transparent;
color: $headings-color;
@include media-breakpoint-down(md) {
min-width: 0;
}
}
}
.o_gantt_row {
&:hover{
.o_gantt_group_hours {
display: initial;
}
}
}
// === All sidebar headers (Regular, Groups and Total) ====
// ========================================================
.o_gantt_row_sidebar {
color: $headings-color;
font-weight: bold;
.o_gantt_row_title {
line-height: $gantt-pill-height + 4px;
position: relative;
}
.o_gantt_progressbar, .o_gantt_text_hoverable {
right: 0;
height: 100%
}
@include media-breakpoint-down(sm) {
.o_gantt_progressbar, .o_gantt_text_mobile {
top: 50%;
height: 50%;
}
}
.o_gantt_group_hours {
display: none;
@include media-breakpoint-down(sm) {
display: block;
}
}
}
// All rows (Regular, Group Header and Total)
// ==========================================
.o_gantt_row, .o_gantt_total_row_container {
.o_gantt_pill {
z-index: 1; // pill should overlap the grid
height: $gantt-pill-height;
p {
// Prevent displaying pill's description when size is smaller than 50px
max-width: calc((100% - 50px) * 9999);
margin: 0 4px;
}
}
}
// ===== "Regular" & "Group Header" rows =====
// ===========================================
.o_gantt_row_container {
.o_gantt_row {
border-bottom: 1px solid $gantt-border-color;
background: #FFFFFF;
&:first-child {
> .o_gantt_slots_container, > .o_gantt_row_sidebar {
box-shadow: inset 0 4px 5px -3px rgba(black, .1);
}
}
.o_gantt_slots_container .o_gantt_cell.ui-drag-hover {
background: rgba(0, 160, 157, 0.3) !important;
.o_gantt_pill {
background: rgba(0, 160, 157, 0.3);
}
}
}
.o_gantt_row_thumbnail_wrapper {
.o_gantt_row_thumbnail {
width: auto;
max-height: $gantt-pill-height - 10px;
}
}
.o_gantt_cell {
@include gant-today-cell();
border-left: 1px solid $gantt-border-color;
}
}
// ============= "Regular" rows ==============
// ===========================================
.o_gantt_row_nogroup {
.o_gantt_cell {
min-height: $gantt-pill-height + 4px;
}
.o_gantt_pill {
@include o-gantt-hoverable-colors(nth($o-colors-complete, 1));
overflow: hidden;
user-select: none;
box-sizing: content-box;
&.ui-resizable-resizing, &.ui-draggable-dragging {
z-index: 2; // other pills show not hide these ones
}
&.decoration-info {
@include gantt-gradient-decorations(nth($o-colors-complete, 1));
}
.ui-resizable-e, .ui-resizable-w {
width: 10px;
}
&:hover {
.ui-resizable-e, .ui-resizable-w {
background-color: rgba(230,230,230, .5);
&:hover {
background-color: rgba(230,230,230, .8);
}
}
}
&.ui-resizable-resizing {
.ui-resizable-e, .ui-resizable-w {
background-color: rgba(black, .5);
}
}
// used for `color` attribute on <gantt>
@for $index from 2 through length($o-colors-complete) - 1 {
// @for $index from 3 through length($o-colors) {
&.o_gantt_color_#{$index - 1} {
$gantt-color: nth($o-colors-complete, $index);
@include o-gantt-hoverable-colors($gantt-color);
&.decoration-info {
@include gantt-gradient-decorations($gantt-color);
}
}
}
@each $color, $value in $theme-colors {
&.decoration-#{$color}:before {
@include gantt-ribbon-decoration($value);
}
}
}
.o_gantt_cell.o_gantt_unavailability {
background: linear-gradient(
$gantt-unavailability-bg,
$gantt-unavailability-bg
) no-repeat;
&.o_gantt_unavailable_first_half {
background-size: 50%;
}
&.o_gantt_unavailable_second_half {
background-position: right;
background-size: 50%;
}
}
.o_gantt_cell.o_gantt_unavailable_second_half.o_gantt_today {
background: linear-gradient(
to right,
$gantt-highlight-today-bg 50%,
$gantt-unavailability-bg 50%
);
background-size: 100%;
}
.o_gantt_cell_buttons {
@include o-position-absolute(0, 0, $left: 0);
display: none;
z-index: 4;
color: $body-color;
.o_gantt_cell_add {
cursor: cell;
}
.o_gantt_cell_plan {
cursor: zoom-in;
}
.o_gantt_cell_add, .o_gantt_cell_plan {
background: $gray-100;
width: 30px;
line-height: 16px;
box-shadow: 0 1px 2px rgba(black, .2);
cursor: pointer;
&:first-child {
border-bottom-left-radius: 4px;
}
&:last-child {
border-bottom-right-radius: 4px;
}
}
}
.o_gantt_pill_wrapper {
line-height: $gantt-pill-height;
margin: 0 2px;
&.o_gantt_pill_wrapper_continuous_left {
padding-left: 0;
}
&.o_gantt_pill_wrapper_continuous_right {
padding-right: 0;
}
.o_gantt_pill_resize_badge {
@include o-position-absolute($bottom: -18px);
box-shadow: 0 1px 2px 0 rgba(black, .28);
background-color: #FFFFFF;
}
&.o_gantt_consolidated_wrapper {
.o_gantt_consolidated_pill {
@include o-position-absolute(0, 0, 0, 0);
height: auto;
}
.o_gantt_consolidated_pill_title {
z-index: 2;
color: white;
}
}
}
// ==== "Regular" row - When it's an opened group's children
&.open .o_gantt_row_sidebar {
font-weight: normal;
}
// ==== "Regular" row - "Hover" State
.o_gantt_cell.o_gantt_hoverable.o_hovered {
.o_gantt_cell_buttons {
display: flex;
}
&.o_gantt_unavailability {
&.o_gantt_unavailable_first_half {
background: linear-gradient(
to right,
rgba($gantt-unavailability-bg, .7) 50%,
$gantt-highlight-hover-row 50%
);
background-size: 100%;
}
&.o_gantt_unavailable_second_half {
background: linear-gradient(
to right,
$gantt-highlight-hover-row 50%,
rgba($gantt-unavailability-bg, .7) 50%
);
background-size: 100%;
}
&.o_gantt_unavailable_full {
background: linear-gradient(
to right,
rgba($gantt-unavailability-bg, .7) 50%,
rgba($gantt-unavailability-bg, .7) 50%
);
background-size: 100%;
}
}
}
.o_gantt_row_sidebar .o_gantt_group_hours {
line-height: $gantt-pill-height + 4px;
}
}
// ==== "Group Header" rows (closed) =====
// =======================================
.o_gantt_row_group {
cursor: pointer;
&, &.open:hover {
.o_gantt_row_sidebar, .o_gantt_slots_container, .o_gantt_text_hoverable.o_gantt_group_none {
background-image: linear-gradient(darken($gantt-row-open-bg, 5%), $gantt-row-open-bg);
}
}
&:hover, &.open {
.o_gantt_row_sidebar, .o_gantt_slots_container, .o_gantt_text_hoverable.o_gantt_group_none {
background-image: linear-gradient($gantt-row-open-bg, darken($gantt-row-open-bg, 5%));
}
}
.o_gantt_row_sidebar, .o_gantt_row_title, .o_gantt_cell {
min-height: $gantt-pill-consolidated-height;
line-height: $gantt-pill-consolidated-height;
}
.o_gantt_row_sidebar .o_gantt_text_hoverable {
&.o_gantt_group_success {
background-image: linear-gradient(#add4bd, #b8dec3);
}
&.o_gantt_group_danger {
background-image: linear-gradient(#e3b2bd, #eebcc3);
}
}
.o_gantt_row_thumbnail_wrapper .o_gantt_row_thumbnail {
max-width: 17px;
}
.o_gantt_cell {
border-color: mix($gantt-row-open-bg, $gantt-border-color, 30%);
&.o_gantt_today {
background-color: mix($gantt-row-open-bg, $gantt-highlight-today-bg);
}
}
.o_gantt_pill {
border-color: $primary;
}
.o_gantt_pill_wrapper.o_gantt_consolidated_wrapper {
margin-top: 0;
line-height: $gantt-pill-consolidated-height;
.o_gantt_consolidated_pill {
@include o-position-absolute($gantt-pill-consolidated-height * .5 - 1px, 0, auto, 0);
background-color: $primary;
height: 2px;
&:before, &:after {
border-top: 4px solid transparent;
border-bottom: 5px solid transparent;
content: '';
}
&:before {
@include o-position-absolute($top: -3px, $left: 0);
border-left: 5px solid;
border-left-color: inherit;
}
&:after {
@include o-position-absolute($top: -3px, $right: 0);
border-right: 5px solid;
border-right-color: inherit;
}
}
}
// === "Group Header" rows (open) ======
// =======================================
&.open .o_gantt_cell {
&, &.o_gantt_today, &.o_gantt_today + .o_gantt_cell {
border-color: transparent;
background-color: transparent;
}
.o_gantt_pill_wrapper.o_gantt_consolidated_wrapper .o_gantt_consolidated_pill {
&:before, &:after {
top: 2px;
border: 2px solid transparent;
border-top-color: inherit;
}
&:before {
border-left-color: inherit;
}
&:after {
border-right-color: inherit;
}
}
}
}
// === "Group Header" & "TOTAL" rows ========
// ===========================================
.o_gantt_row_group, .o_gantt_total {
.o_gantt_consolidated_pill_title {
z-index: 2;
background-color: $o-view-background-color;
color: $body-color;
}
}
// ============= "TOTAL" row =================
// ===========================================
.o_gantt_total {
z-index: 2;
}
.o_gantt_total_row_container .o_gantt_row {
border-bottom: 1px solid $gantt-border-color;
.o_gantt_cell {
@include gant-today-cell();
border-left: 1px solid rgba($gantt-border-color, .25);
&:first-child {
border-left: 1px solid rgba($gantt-border-color, 1);
}
}
.o_gantt_cell, .o_gantt_row_title, .o_gantt_pill_wrapper {
min-height: $gantt-pill-height * 1.6;
line-height: $gantt-pill-height * 1.6;
}
.o_gantt_consolidated_pill_title {
bottom: 2px;
line-height: 1.5;
}
.o_gantt_pill {
@include o-position-absolute(auto, 0, 0, 0);
background-color: rgba($o-brand-odoo, .5);
}
.o_gantt_pill_wrapper:hover {
overflow: visible;
.o_gantt_pill {
background-color: rgba($o-brand-odoo, .8);
}
&:before {
@include o-position-absolute(auto, -1px, 0, -1px);
border: 1px solid $o-brand-odoo;
border-width: 0 1px;
background: rgba($o-brand-odoo, .1);
height: 100vh;
content: '';
pointer-events: none;
z-index: 1;
}
}
.o_gantt_cell:last-child .o_gantt_pill_wrapper:hover:before {
border-right: 0px;
right: 0;
}
}
.o_view_nocontent {
z-index: 11; // as we have z-index: 10 on header container so z-index: header + 1;
}
// Suggest the browsers to print background graphics (IE users will still
// need to go to their settings in order to print them)
-webkit-print-color-adjust: exact; /* Chrome, Safari */
color-adjust: exact; /*Firefox*/
}
.o_gantt_slots_container {
.o_gantt_cell {
.o_gantt_pill_wrapper {
// used for `color` attribute on <gantt>
@for $index from 1 through length($o-colors-complete) - 1 {
// @for $index from 3 through length($o-colors) {
.o_gantt_pill {
&.highlight {
z-index: 2;
}
&.o_gantt_color_#{$index - 1} {
$color: nth($o-colors-complete, $index);
&.highlight {
background-color: $color;
color: color-contrast($color);
}
.o_gantt_progress {
opacity: 0.2;
background-color: darken(nth($o-colors-complete, $index), 30%);
}
}
}
.o_connector_creator_wrapper {
&.o_gantt_color_#{$index - 1} {
$color: nth($o-colors-complete, $index);
.o_connector_creator_bullet {
background-color: $color;
color: color-contrast($color);
@include o-grab-cursor;
}
.o_connector_creator_top {
border-top: solid 1px $color;
}
.o_connector_creator_right {
border-left: solid 1px $color;
}
.o_connector_creator_bottom {
border-bottom: solid 1px $color;
}
.o_connector_creator_left {
border-right: solid 1px $color;
}
}
}
}
}
}
}
.o_connector_container {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.o_connector {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
&.o_connector_hovered {
z-index: 2;
}
.o_connector_stroke_button {
> rect {
cursor: pointer;
stroke: #091124;
stroke-width: 24px;
fill: white;
}
&.o_connector_stroke_reschedule_button {
line {
stroke: #00a09d;
}
&:hover{
> rect {
fill: #00a09d;
}
line {
stroke: white;
}
}
}
&.o_connector_stroke_remove_button {
g {
rect {
fill: #dd3c4f;
}
}
&:hover{
> rect {
fill: #dd3c4f;
}
g {
rect {
fill: white;
}
}
}
}
}
}
.o_connector_creator_wrapper {
z-index: 3;
position: absolute;
height: $o-connector-wrapper-height;
width: 100%
}
.o_connector_creator_wrapper_top {
top: -1 * $o-connector-wrapper-height;
}
.o_connector_creator_wrapper_bottom {
bottom: -1 * $o-connector-wrapper-height;
}
.o_connector_creator {
position: absolute;
height: $o-connector-creator-size;
width: $o-connector-creator-size;
}
.o_connector_creator_bullet {
height: $o-connector-creator-bullet-diameter;
width: $o-connector-creator-bullet-diameter;
position: absolute;
border-radius: $o-connector-creator-bullet-diameter / 2;
}
.o_connector_creator_top {
bottom: 0;
.o_connector_creator_bullet {
top: -0.5 * $o-connector-creator-bullet-diameter;
}
}
.o_connector_creator_right {
right: $o-connector-creator-size;
.o_connector_creator_bullet {
right: -0.5 * $o-connector-creator-bullet-diameter;
}
}
.o_connector_creator_bottom {
top: 0;
.o_connector_creator_bullet {
bottom: -0.5 * $o-connector-creator-bullet-diameter;
}
}
.o_connector_creator_left {
left: $o-connector-creator-size;
.o_connector_creator_bullet {
left: -0.5 * $o-connector-creator-bullet-diameter;
}
}

View File

@@ -0,0 +1,15 @@
// = Gantt View Variables
// ============================================================================
$gantt-border-color: $o-gray-300 !default;
$gantt-pill-height: 31px !default;
$gantt-highlight-today-border: #dca665 !default;
$gantt-highlight-today-bg: #fffaeb !default;
$gantt-highlight-hover-row: rgba($o-brand-primary, .1) !default;
$gantt-row-open-bg: $o-gray-100 !default;
$gantt-pill-consolidated-height: 24px !default;
$gantt-unavailability-bg: $o-gray-200 !default;
$o-connector-creator-bullet-radius: 3px !default;
$o-connector-creator-size: 8px !default;
$o-connector-creator-bullet-diameter: 2 * $o-connector-creator-bullet-radius !default;
$o-connector-wrapper-height: $o-connector-creator-size + $o-connector-creator-bullet-radius !default;

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="connector_stroke_head" owl="1">
<path d="M2,2 L10,6 L2,10 L6,6 L2,2"
class="o_connector_stroke_head"
t-att="{
'fill': color,
'stroke': color,
}"
t-if="width"
version="1.1"
xmlns="http://www.w3.org/2000/svg"/>
</t>
<t t-name="connector_stroke" owl="1">
<path fill="none"
pointer-events="stroke"
t-att="{
'd': path,
'stroke': color,
'stroke-width': width,
'class': 'o_connector_stroke' + (classNameModifier ? classNameModifier : ''),
'marker-end': markerEnd ? 'url(#' + markerEnd + ')' : false,
'pointer-events': props.inCreation ? 'none' : 'stroke',
}"
t-if="width"/>
</t>
<t t-name="connector" owl="1">
<svg class="o_connector"
pointer-events="none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
t-att-class="props.hovered ? 'o_connector_hovered' : ''"
t-att-data-id="props.id">
<t t-set="strokeColor"
t-value="props.hovered and !!style.stroke.hoveredColor ? style.stroke.hoveredColor : style.stroke.color"/>
<t t-set="outlineStrokeColor"
t-value="props.hovered and !!style.outlineStroke.hoveredColor ? style.outlineStroke.hoveredColor : style.outlineStroke.color"/>
<defs t-if="style.drawHead">
<marker markerHeight="6"
markerWidth="6"
markerUnits="strokeWidth"
orient="auto"
refX="9"
refY="6"
stroke-linejoin="round"
t-attf-id="o_connector_arrow_head_{{props.id}}"
viewBox="0 0 12 12">
<t t-call="connector_stroke_head">
<t t-set="color" t-value="strokeColor"/>
<t t-set="width" t-value="style.stroke.width"/>
</t>
</marker>
</defs>
<t t-if="hoverEaseWidth > 0" t-call="connector_stroke">
<t t-set="color" t-value="transparent"/>
<t t-set="classNameModifier" t-value="'_hover_ease'"/>
<t t-set="width"
t-value="style.stroke.width + hoverEaseWidth + style.outlineStroke.width"/>
</t>
<t t-if="style.outlineStroke.width > 0" t-call="connector_stroke">
<t t-set="color" t-value="outlineStrokeColor"/>
<t t-set="classNameModifier" t-value="'_outline'"/>
<t t-set="width" t-value="style.stroke.width + style.outlineStroke.width"/>
</t>
<t t-call="connector_stroke">
<t t-set="color" t-value="strokeColor"/>
<t t-set="markerEnd" t-value="'o_connector_arrow_head_' + props.id"/>
<t t-set="width" t-value="style.stroke.width"/>
</t>
<svg class="o_connector_stroke_buttons"
pointer-events="all"
t-att="{
'height': 16,
'width': 48,
'x': removeButtonPosition.left - 24,
'y': removeButtonPosition.top - 8
}"
t-if="props.canBeRemoved and props.hovered"
version="1.1"
viewBox="0 0 1536 512"
xmlns="http://www.w3.org/2000/svg">
<rect fill="transparent" x="0" y="0" width="1536" height="512"/>
<g t-on-click.stop="_onRescheduleSoonerClick" class="o_connector_stroke_button o_connector_stroke_reschedule_button">
<rect fill="white" x="20" y="20" width="472" height="472" rx="236" ry="236"/>
<g pointer-events="none">
<line x1="192" y1="256" x2="320" y2="128" stroke-width="56"/>
<line x1="192" y1="256" x2="320" y2="384" stroke-width="56"/>
</g>
</g>
<g t-on-click.stop="_onRemoveButtonClick" class="o_connector_stroke_button o_connector_stroke_remove_button">
<rect fill="white" x="532" y="20" width="472" height="472" class="o_connector_stroke_button" rx="236" ry="236"/>
<g transform="rotate(45,768,256)" pointer-events="none">
<rect x="740" y="100" fill="rgb(221, 60, 79)" width="56" height="312"/>
<rect x="612" y="228" fill="rgb(221, 60, 79)" width="312" height="56"/>
</g>
</g>
<g t-on-click.stop="_onRescheduleLaterClick" class="o_connector_stroke_button o_connector_stroke_reschedule_button">
<rect fill="white" x="1044" y="20" width="472" height="472" rx="236" ry="236"/>
<g pointer-events="none">
<line x1="1216" y1="128" x2="1344" y2="256" stroke-width="56"/>
<line x1="1216" y1="384" x2="1344" y2="256" stroke-width="56"/>
</g>
</g>
</svg>
</svg>
</t>
</templates>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="connector_container" owl="1">
<div class="o_connector_container"
t-on-mouseover.stop="_onMouseOver"
t-on-mouseout.stop="_onMouseOut">
<t t-foreach="connectors"
t-as="connector"
t-key="connector_value.id">
<Connector t-props="connector_value"
onRemoveButtonClick="props.onRemoveButtonClick"
onRescheduleSoonerButtonClick="props.onRescheduleSoonerButtonClick"
onRescheduleLaterButtonClick="props.onRescheduleLaterButtonClick"
/>
</t>
<Connector t-props="newConnector" t-if="!!newConnector.source &amp;&amp; !!newConnector.target"/>
</div>
</t>
</templates>

View File

@@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<div t-name="GanttView.buttons">
<button t-if="widget.is_action_enabled('create')" class="o_gantt_button_add btn btn-primary me-3" title="Add record" data-hotkey="r">
Add
</button>
<div class="d-inline-block me-3">
<button class="o_gantt_button_prev btn btn-primary" title="Previous">
<span class="fa fa-arrow-left"/>
</button>
<button class="o_gantt_button_today btn btn-primary" data-hotkey="t">
Today
</button>
<button class="o_gantt_button_next btn btn-primary" title="Next">
<span class="fa fa-arrow-right"/>
</button>
</div>
<div class="btn-group o_gantt_range">
<t t-call="GanttView.RangeButtons"/>
</div>
<div t-attf-class="btn-group #{displayExpandCollapseButtons ? '' : 'd-none'}">
<button class="o_gantt_button_expand_rows btn btn-secondary" title="Expand rows">
<i class="fa fa-expand"/>
</button>
<button class="o_gantt_button_collapse_rows btn btn-secondary" title="Collapse rows">
<i class="fa fa-compress"/>
</button>
</div>
</div>
<t t-name="GanttView.RangeButtons">
<t t-if="isMobile">
<t t-call="GanttView.RangeButtons.Mobile"/>
</t>
<t t-else="">
<t t-call="GanttView.RangeButtons.Loop"/>
</t>
</t>
<t t-name="GanttView.RangeButtons.Mobile">
<a class="btn btn-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
<t t-esc="SCALES[activateScale].string"/>
</a>
<ul class="dropdown-menu" role="menu">
<t t-call="GanttView.RangeButtons.Loop"/>
</ul>
</t>
<t t-name="GanttView.RangeButtons.Loop">
<t t-foreach="allowedScales" t-as="scale">
<button t-attf-class="o_gantt_button_scale btn btn-secondary #{scale == activateScale ? 'active' : ''} #{isMobile ? 'dropdown-item' : ''}" type="button" t-att-data-value="scale" t-att-data-hotkey="SCALES[scale].hotkey" >
<t t-esc="SCALES[scale].string"/>
</button>
</t>
</t>
<div t-name="GanttView" class="o_gantt_view">
<div class="o_gantt_view_container container-fluid p-0">
<div class="row g-0 o_gantt_header_container position-sticky bg-view">
<div class="col-md-2 col-3 position-relative o_gantt_row_sidebar text-center" t-if="widget.state.groupedBy.length">
<span class="fw-bold" t-esc="widget.string"/>
</div>
<div class="col position-relative o_gantt_header_slots">
<div class="row g-0">
<div class="col text-center p-2 fw-bold">
<t t-esc="widget._getFocusDateFormat()"/>
</div>
</div>
<div class="row g-0 o_gantt_header_scale">
<t t-set="formats" t-value="{'week': 'dddd, Do', 'month': 'DD', 'year': isMobile ? 'MMM' : 'MMMM'}"/>
<t t-foreach="widget.viewInfo.slots" t-as="slot">
<t t-set="isToday" t-value="slot.isSame(new Date(), 'day') &amp;&amp; widget.state.scale !== 'day'"/>
<div t-attf-class="col position-relative o_gantt_header_cell text-center p-2 #{isToday? 'o_gantt_today' : ''} ">
<t t-if="widget.state.scale in formats" t-esc="slot.format(formats[widget.state.scale])"/>
<small t-else="">
<b t-esc="slot.format('k')"/>
<span class="d-block d-xl-inline-block" t-esc="slot.format('a')"/>
</small>
</div>
</t>
</div>
</div>
</div>
<div class="row g-0">
<div class="col position-relative o_gantt_row_container">
</div>
</div>
<div class="row g-0 o_gantt_total position-relative" t-if="widget.totalRow">
<div class="col position-relative o_gantt_total_row_container">
</div>
</div>
</div>
</div>
<div t-name="GanttView.Connector" t-attf-class="invisible o_connector_creator_wrapper o_connector_creator_wrapper_{{vertical_alignment}} {{!widget.options.isGroup ? pill.decorations.join(' ') : ''}} {{'_color' in pill ? 'o_gantt_color_' + pill._color : ''}}">
<div t-attf-class="o_connector_creator o_connector_creator_{{vertical_alignment}} o_connector_creator_{{horizontal_alignment}}">
<div t-att-data-id="pill.id" class="o_connector_creator_bullet">
</div>
</div>
</div>
<t t-name="GanttView.PillsConnectors">
<t t-call="GanttView.Connector" t-if="widget.dependencyEnabled">
<t t-set="vertical_alignment" t-value="'top'"></t>
<t t-set="horizontal_alignment" t-value="'left'"></t>
</t>
<t t-out="0"/>
<t t-call="GanttView.Connector" t-if="widget.dependencyEnabled">
<t t-set="vertical_alignment" t-value="'bottom'"></t>
<t t-set="horizontal_alignment" t-value="'right'"></t>
</t>
</t>
<div t-name="GanttView.Row" t-attf-class="row g-0 o_gantt_row bg-view #{widget.isTotal ? 'o_gantt_row_total' : widget.isGroup ? 'o_gantt_row_group' : 'o_gantt_row_nogroup'} #{widget.isOpen ? 'open' : ''}" t-att-data-from-server="widget.fromServer" t-att-data-row-id="widget.rowId">
<div t-if="!widget.options.hideSidebar" t-attf-class="col-md-2 col-3 o_gantt_row_sidebar position-relative #{!widget.name ? 'o_gantt_row_sidebar_empty' : '' }" t-attf-style="padding-left: #{widget.leftPadding}px;">
<t t-if="widget.progressBar">
<t t-if="widget.progressBar.max_value > 0">
<span t-attf-class="position-absolute o_gantt_progressbar bg-opacity-25 {{ widget.progressBar.ratio > 100 ? 'o_gantt_group_danger text-bg-danger' : 'o_gantt_group_success text-bg-success' }}"
t-att-style="'width: ' + Math.min(widget.progressBar.ratio, 100) + '%;'">
&amp;nbsp;
</span>
<span t-attf-class="position-absolute o_gantt_text_hoverable z-index-1 {{widget.progressBar.ratio > 0 ? (widget.progressBar.ratio > 100 ? 'o_gantt_group_danger text-bg-danger' : 'o_gantt_group_success text-bg-success') : 'o_gantt_group_none' }} {{ widget.isMobile ? 'o_gantt_text_mobile': 'o_gantt_text_hoverable'}}">
<span class="o_gantt_group_hours px-1" t-att-style="widget.cellHeight ? 'line-height: ' + (widget.isMobile ? widget.cellHeight / 2 : widget.cellHeight) + 'px;' : ''">
<t t-esc="widget.progressBar.value_formatted"/> / <t t-esc="widget.progressBar.max_value_formatted"/>
</span>
</span>
</t>
<t t-else="">
<span name="progress_bar_no_max_value" class="position-absolute o_gantt_text_hoverable o_gantt_group_none">
<span name="progress_bar_no_max_value_group" class="o_gantt_group_hours px-1"
t-attf-title="#{widget.progressBar.warning} #{widget.progressBar.value_formatted}."
t-att-style="widget.cellHeight ? 'line-height: ' + (widget.isMobile ? widget.cellHeight / 2 : widget.cellHeight) + 'px;' : ''">
<i class="fa fa-exclamation-triangle"></i>
</span>
</span>
</t>
</t>
<div t-attf-class="o_gantt_row_title text-truncate pe-1 #{widget.isTotal ? 'text-end pe-3 h4 my-0 fw-bold' : ''}" t-att-title="widget.name or ''"
t-att-style="widget.cellHeight ? 'line-height: ' + widget.cellHeight + 'px;' : ''">
<i t-if="!widget.isTotal &amp; widget.isGroup"
t-attf-class="fa small #{widget.isOpen ? 'fa-minus' : 'fa-plus'}"/>
<div t-if="widget.thumbnailUrl and widget.resId"
t-attf-class="o_gantt_row_thumbnail_wrapper d-inline #{!widget.options.isGroup ? 'me-1' : ''}">
<img t-att-src="widget.thumbnailUrl" class="rounded-circle o_gantt_row_thumbnail"/>
</div>
<t t-esc="widget.name"/>
</div>
</div>
<div class="o_gantt_slots_container col position-relative">
<div class="row g-0">
<div t-foreach="widget.slots" t-as="slot"
t-attf-class="col position-relative o_gantt_cell #{slot.isToday ? 'o_gantt_today' : ''} #{slot.hasButtons ? 'o_gantt_hoverable' : ''}"
t-att-data-date="slot.start.format('YYYY-MM-DD HH:mm:ss')"
t-attf-style="height: #{widget.cellHeight}px;#{slot.style ? ' ' + slot.style : ''}">
<!-- plan and add buttons -->
<div t-if="slot.hasButtons" class="o_gantt_cell_buttons justify-content-center">
<div class="position-absolute d-flex">
<i t-if="widget.options.canCreate and widget.options.canCellCreate" title="Create" t-attf-class="o_gantt_cell_add fa fa-plus d-flex justify-content-center #{widget.options.canPlan ? 'pe-1' : ''}"/>
<i t-if="widget.options.canPlan" title="Plan existing" class="o_gantt_cell_plan fa fa-search-plus d-flex justify-content-center"/>
</div>
</div>
<!-- pills -->
<t t-foreach="slot.pills" t-as="pill">
<div t-if="widget.isTotal"
class="o_gantt_pill_wrapper position-absolute d-flex justify-content-center"
t-attf-style="width: #{pill.width}; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div t-att-data-id="pill.id"
t-attf-class="o_gantt_pill o_gantt_consolidated_pill"
t-att-title="pill.display_name"
t-att-style="'height:' + pill.totalHeight + '%;'"/>
</t>
<span class="o_gantt_consolidated_pill_title position-absolute text-truncate px-1" t-esc="pill.display_name"/>
</div>
<div t-elif="pill.consolidated"
t-attf-class="o_gantt_pill_wrapper position-absolute o_gantt_consolidated_wrapper #{widget.options.isGroup ? 'o_gantt_pill_wrapper_group' : ''}"
t-attf-style="width: #{pill.width}; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div
t-att-data-id="pill.id"
t-attf-class="o_gantt_pill o_gantt_consolidated_pill #{pill.status? 'bg-' + pill.status + ' border-' + pill.status : ''} #{!widget.options.isGroup ? pill.decorations.join(' ') : ''}"
t-att-title="pill.display_name"
>
<span
t-if="widget.progressField"
t-attf-class="position-absolute o_gantt_progress"
t-attf-data-progress="#{pill._progress}%;"
t-attf-style="width:#{pill._progress}%;"
>
&amp;nbsp;
</span>
</div>
</t>
<span class="o_gantt_consolidated_pill_title position-relative text-truncate px-1" t-esc="pill.display_name"/>
</div>
<div t-else=""
t-attf-class="o_gantt_pill_wrapper position-absolute #{widget.options.isGroup ? 'o_gantt_pill_wrapper_group' : ''}"
t-attf-style="width: #{pill.width}; margin-top: #{pill.topPadding}px; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div
t-att-data-id="pill.id"
t-attf-class="o_gantt_pill position-relative #{!widget.options.isGroup ? pill.decorations.join(' ') : ''} #{'_color' in pill ? 'o_gantt_color_' + pill._color : ''}"
t-attf-style="#{widget.options.isGroup ? pill.style : ''}"
t-att-title="pill.display_name"
>
<span
t-if="widget.progressField"
t-attf-class="position-absolute o_gantt_progress"
t-attf-data-progress="#{pill._progress}%;"
t-attf-style="width:#{pill._progress}%;"
>
&amp;nbsp;
</span>
<!-- README: be careful when modifying the DOM inside the pill ; @_onMouseMove is strongly dependant of it -->
<p class="text-truncate position-relative mb-0 o_gantt_pill_title" t-esc="pill.label ? pill.label : pill.display_name"/>
</div>
</t>
</div>
</t>
</div>
</div>
</div>
</div>
<t t-name="GanttView.ResizeBadge">
<span t-if="diff === 0" class="o_gantt_pill_resize_badge badge rounded-pill" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('%s %s', diff, time)"/>
</span>
<span t-elif="diff &gt; 0" class="o_gantt_pill_resize_badge badge rounded-pill text-success" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('+%s %s', diff, time)"/>
</span>
<span t-else="diff &lt; 0" class="o_gantt_pill_resize_badge badge rounded-pill text-danger" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('%s %s', diff, time)"/>
</span>
</t>
<!-- Default popover template used if none is defined in the Gantt view arch -->
<div t-name="gantt-popover">
<ul class="p-0 mb-0 list-unstyled d-flex flex-row">
<li class="d-flex flex-column pe-2">
<strong>Name:</strong>
<strong>Start:</strong>
<strong>Stop:</strong>
</li>
<li class="d-flex flex-column">
<span t-esc="display_name"/>
<span t-esc="userTimezoneStartDate.format('DD MMM, LT')"/>
<span t-esc="userTimezoneStopDate.format('DD MMM, LT')"/>
</li>
</ul>
</div>
</templates>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
odoo.define('web_gantt.gantt_mobile_tests', function (require) {
"use strict";
const GanttView = require('web_gantt.GanttView');
const testUtils = require('web.test_utils');
const createView = testUtils.createView;
let initialDate = new Date(2018, 11, 20, 8, 0, 0);
initialDate = new Date(initialDate.getTime() - initialDate.getTimezoneOffset() * 60 * 1000);
QUnit.module('LegacyViews', {
beforeEach: function () {
this.data = {
tasks: {
fields: {
id: {string: 'ID', type: 'integer'},
start: {string: 'Start Date', type: 'datetime'},
stop: {string: 'Stop Date', type: 'datetime'},
user_id: {string: 'Assign To', type: 'many2one', relation: 'users'},
},
records: [
{ id: 1, start: '2018-11-30 18:30:00', stop: '2018-12-31 18:29:59', user_id: 1},
{ id: 2, start: '2018-12-17 11:30:00', stop: '2018-12-22 06:29:59', user_id: 2},
{ id: 3, start: '2018-12-27 06:30:00', stop: '2019-01-03 06:29:59', user_id: 2},
{ id: 4, start: '2018-12-19 22:30:00', stop: '2018-12-20 06:29:59', user_id: 1},
{ id: 5, start: '2018-11-08 01:53:10', stop: '2018-12-04 01:34:34', user_id: 1},
],
},
users: {
fields: {
id: {string: 'ID', type: 'integer'},
name: {string: 'Name', type: 'char'},
},
records: [
{id: 1, name: 'User 1'},
{id: 2, name: 'User 2'},
],
},
};
},
}, function () {
QUnit.module('GanttView (legacy) - Mobile');
QUnit.test('Progressbar: check the progressbar percentage visibility.', async function (assert) {
assert.expect(11);
const gantt = await createView({
View: GanttView,
model: 'tasks',
data: this.data,
arch: `<gantt date_start="start" date_stop="stop"
default_scale="week" scales="week"
default_group_by="user_id"
progress_bar="user_id">
<field name="user_id"/>
</gantt>`,
viewOptions: {
initialDate: initialDate,
},
config: {device: {isMobile: true}},
mockRPC: function (route, args) {
if (args.method === 'gantt_progress_bar') {
assert.strictEqual(args.model, "tasks");
assert.deepEqual(args.args[0], ['user_id']);
assert.deepEqual(args.args[1], {user_id: [1, 2]});
return Promise.resolve({
user_id: {
1: {value: 50, max_value: 100},
2: {value: 25, max_value: 200},
}
});
}
return this._super.apply(this, arguments);
},
});
const progressbar = gantt.el.querySelectorAll('.o_gantt_row_sidebar .o_gantt_progressbar');
assert.strictEqual(progressbar.length, 2, "Gantt should include two progressbars");
assert.strictEqual(progressbar[0].style.width, "50%");
assert.strictEqual(progressbar[1].style.width, "12.5%");
assert.hasClass(progressbar[0], 'o_gantt_group_success', "Progress bar should have the success class");
assert.hasClass(progressbar[1], 'o_gantt_group_success', "Progress bar should have the success class");
const progressbarText = gantt.el.querySelectorAll('.o_gantt_row_sidebar .o_gantt_text_mobile');
assert.hasClass(progressbarText[0], 'o_gantt_text_mobile', "Progress bar should be visible.");
assert.hasClass(progressbarText[1], 'o_gantt_text_mobile', "Progress bar should be visible.");
assert.isVisible(gantt.el.querySelector('.o_gantt_row_sidebar .o_gantt_group_hours'), "Progressbar Title should be visible.");
gantt.destroy();
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
/** @odoo-module */
import { Domain } from '@web/core/domain';
import { removeDomainLeaf } from '@web_gantt/js/gantt_controller';
QUnit.module('WebGantt > RemoveDomainLeaf');
QUnit.test('Remove leaf in domain.', function (assert) {
let domain = [
['start_datetime', '!=', false], ['end_datetime', '!=', false],
['sale_line_id', '!=', false],
];
const keysToRemove = ['start_datetime', 'end_datetime'];
let newDomain = removeDomainLeaf(domain, keysToRemove);
let expectedDomain = new Domain([
'&', ...Domain.TRUE.toList({}), ...Domain.TRUE.toList({}),
['sale_line_id', '!=', false],
]);
assert.deepEqual(
newDomain.toList({}),
expectedDomain.toList({}),
);
domain = [
'|', ['role_id', '=', false],
'&', ['resource_id', '!=', false], ['start_datetime', '=', false],
['sale_line_id', '!=', false],
];
newDomain = removeDomainLeaf(domain, keysToRemove);
expectedDomain = new Domain([
'|', ['role_id', '=', false],
'&', ['resource_id', '!=', false], ...Domain.TRUE.toList({}),
['sale_line_id', '!=', false],
]);
assert.deepEqual(
newDomain.toList({}),
expectedDomain.toList({}),
);
domain = [
'|', ['start_datetime', '=', false], ['end_datetime', '=', false],
['sale_line_id', '!=', false],
];
newDomain = removeDomainLeaf(domain, keysToRemove);
expectedDomain = new Domain([
...Domain.TRUE.toList({}),
['sale_line_id', '!=', false],
]);
assert.deepEqual(
newDomain.toList({}),
expectedDomain.toList({}),
);
});

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_acl

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from lxml import etree
from odoo.addons.base.tests.common import TransactionCaseWithUserDemo
class TestACL(TransactionCaseWithUserDemo):
def setUp(self):
super().setUp()
self.user_manager = self.env['res.users'].create({
'login': 'demo123',
'password': 'demo',
'partner_id': self.partner_demo.id,
'groups_id': [(6, 0, [self.env.ref('base.group_system').id])],
})
self.env["ir.ui.view"].create({
"name": "Add delete attribute on gantt view",
"model": "res.company",
"type": 'gantt',
"arch": """
<gantt date_start="date" date_stop="" string="Test">
<field name="partner_id"/>
</gantt>
""",
})
def test_view_delete_button_visibility(self):
# the demo user can't unlink
company_view = self.env['res.company']\
.with_user(self.user_demo)\
.get_view(False, 'gantt')
view_arch = etree.fromstring(company_view['arch'])
self.assertEqual(view_arch.get('delete'), 'false')
# the manager user can unlink
company_view = self.env['res.company']\
.with_user(self.user_manager)\
.get_view(False, 'gantt')
view_arch = etree.fromstring(company_view['arch'])
self.assertIsNone(view_arch.get('delete'))