commit
23f0376727
|
|
@ -373,8 +373,8 @@ this.state.attendance_lines = groupedAttendance;
|
||||||
line.color = 'red';
|
line.color = 'red';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
line.state = 'Refused';
|
line.state = 'Draft';
|
||||||
line.color = 'red';
|
line.color = '#6871f2';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -186,11 +186,11 @@
|
||||||
<h2>
|
<h2>
|
||||||
Attendance
|
Attendance
|
||||||
</h2>
|
</h2>
|
||||||
<button class="action-button" t-on-click="add_attendance">
|
<!-- <button class="action-button" t-on-click="add_attendance">-->
|
||||||
<i class="fa fa-plus">
|
<!-- <i class="fa fa-plus">-->
|
||||||
</i>
|
<!-- </i>-->
|
||||||
Add
|
<!-- Add-->
|
||||||
</button>
|
<!-- </button>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|
@ -280,11 +280,11 @@
|
||||||
<h2>
|
<h2>
|
||||||
Expenses
|
Expenses
|
||||||
</h2>
|
</h2>
|
||||||
<button class="action-button" t-on-click="add_expense">
|
<!-- <button class="action-button" t-on-click="add_expense">-->
|
||||||
<i class="fa fa-plus">
|
<!-- <i class="fa fa-plus">-->
|
||||||
</i>
|
<!-- </i>-->
|
||||||
Add
|
<!-- Add-->
|
||||||
</button>
|
<!-- </button>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- 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/gantt_view.variables.scss',
|
||||||
|
],
|
||||||
|
'web.assets_backend_lazy': [
|
||||||
|
'web_gantt/static/src/**/*',
|
||||||
|
|
||||||
|
# Don't include dark mode files in light mode
|
||||||
|
('remove', 'web_gantt/static/src/**/*.dark.scss'),
|
||||||
|
],
|
||||||
|
'web.assets_backend_lazy_dark': [
|
||||||
|
'web_gantt/static/src/**/*.dark.scss',
|
||||||
|
],
|
||||||
|
'web.assets_unit_tests': [
|
||||||
|
'web_gantt/static/tests/**/*',
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
'auto_install': True,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Arabic (https://app.transifex.com/odoo/teams/41243/ar/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: ar\n"
|
||||||
|
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s ساعات و%(minute)s "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "لا يمكن جدولة %s في الماضي "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s ساعات "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "عرض نافذة الإجراء"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "تطبيق"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "تصغير الصفوف "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "إنشاء"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "تحرير"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "تكبير الصفوف "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "ركّز اليوم "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "من"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "جانت"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "أداة عرض جانت"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "يمكن أن يكون تابع غانت إما حقل أو قالب فقط، به %s "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "يجب أن يكون لعرض غانت خاصية 'date_start' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "يجب أن يكون لعرض غانت خاصية 'date_stop' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"يجب أن يكون لنافذة عرض غانت خاصية 'dependency_inverted_field' بمجرد أن يتم "
|
||||||
|
"تحديد 'dependency_field' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "تاريخ بدء غانت "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "تاريخ انتهاء غانت "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "يمكن أن يحتوي عرض غانت على علامة تصنيف قوالب واحدة فقط "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "لا يمكن القيام بالجدولة في الماضي. "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "لا توجد حقول كافية لعرض غانت! "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"خواص غير صالحة (%(invalid_attributes)s) في عرض غانت. يجب أن تكون الخواص في "
|
||||||
|
"(%(valid_attributes)s) "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' غير صالح في عرض غانت "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "default_scale '%s' غير صالح في عرض غانت "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode '%s' في نافذة عرض غانت غير صالح "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "الاسم"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "جديد"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "فتح"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "الخطة "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "بدء"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "إيقاف"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "التبعيات غير صالحة. لقد تسببت في إحداث دائرة مغلقة. "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "لا يوجد مرشحون صالحون لإعادة التخطيط "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "هذا الشهر"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "ربع السنة هذا "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "هذا الأسبوع "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "هذا العام"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "اليوم "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "قائمة شريط الأدوات "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "الإجمالي"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "غير محدد %s "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "أداة العرض"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "نوع واجهة العرض"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "لا يمكنك تحريك %(record)s نحو %(related_record)s. "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "لا يمكنك إعادة جدولة %(main_record)s نحو %(other_record)s. "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "ساعات"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "دقائق "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "شهور"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "إلى"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,367 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Petko Karamotchev, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
# Rosen Vladimirov <vladimirov.rosen@gmail.com>, 2024
|
||||||
|
# Boyan Rabchev <boyan.rabchev@plana.solutions>, 2024
|
||||||
|
# Rumena Georgieva <rumena.georgieva@gmail.com>, 2024
|
||||||
|
# Vladimir Petrov <vladimir.petrov@gmail.com>, 2024
|
||||||
|
# KeyVillage, 2024
|
||||||
|
# Albena Mincheva <albena_vicheva@abv.bg>, 2024
|
||||||
|
# Maria Boyadjieva <marabo2000@gmail.com>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Maria Boyadjieva <marabo2000@gmail.com>, 2024\n"
|
||||||
|
"Language-Team: Bulgarian (https://app.transifex.com/odoo/teams/41243/bg/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: bg\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Приложи"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Създай"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Редактирай"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "От"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Диаграма на Гант"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Изглед на диаграма на Гант"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Име"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Нов"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Отворен"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Планирайте"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Стартирайте"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Край"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Този месец"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Тази седмица"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Днес"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Обща стойност"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Преглед"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Вид изглед"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "часове"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "минути"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "месеци"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "до"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Arnau Ros, 2024
|
||||||
|
# Ivan Espinola, 2024
|
||||||
|
# jabiri7, 2024
|
||||||
|
# Sandra Franch <sandra.franch@upc.edu>, 2024
|
||||||
|
# Josep Anton Belchi, 2024
|
||||||
|
# marcescu, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
# Quim - eccit <quim@eccit.com>, 2024
|
||||||
|
# RGB Consulting <odoo@rgbconsulting.com>, 2024
|
||||||
|
# Eric Antones <eantones@users.noreply.github.com>, 2024
|
||||||
|
# Manel Fernandez Ramirez <manelfera@outlook.com>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Manel Fernandez Ramirez <manelfera@outlook.com>, 2024\n"
|
||||||
|
"Language-Team: Catalan (https://app.transifex.com/odoo/teams/41243/ca/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: ca\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Vista de la finestra d'acció"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Aplica"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Col·lapsar files"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Crear"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Modificar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Expandeix les files"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Des de"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gràfic de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vista Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt ha de tenir un atribut 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt ha de tenir un atribut \"date_stop\"."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt ha de tenir un atribut 'dependency_inverted_field' una vegada s'hagi "
|
||||||
|
"especificat 'dependency_field' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "¡Camps insuficients per a la vista de Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Escala_per defecte invàlida '%s'a gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nou"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Oberts"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Pla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Inicia"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Atura"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Aquest mes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Aquesta setmana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Aquest any"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Avui"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "No definit %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tipus de vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "hores"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuts"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "mesos"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "fins"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,361 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Czech (https://app.transifex.com/odoo/teams/41243/cs/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: cs\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Akce okna zobrazení"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Použít"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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 "Jádro"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Sbalit řádky"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Vytvořit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Upravit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Rozbalte řádky"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Od"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantův diagram"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Ganttův potomek může být pouze pole nebo šablona, dostal %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt musí mít atribut 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt musí mít atribut 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt musí mít atribut 'dependency_inverted_field', jakmile je specifikováno"
|
||||||
|
" 'dependency_field'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Zobrazení Gantt může obsahovat pouze jeden štítek šablony"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Nedostatečná pole pro zobrazení Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Neplatný default_scale '%s' v gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Název"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nové"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Volný"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plán"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Začít"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Zastavit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Tento měsíc"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Tento týden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Tento rok"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Dnes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Celkem"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Nedefinováno %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Zobrazení"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Typ zobrazení"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "hodin"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minut"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "měsíce"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "k"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,264 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Sanne Kristensen <sanne@vkdata.dk>, 2022
|
||||||
|
# Mads Søndergaard, 2022
|
||||||
|
# Mads Søndergaard, 2022
|
||||||
|
# Martin Trigaux, 2023
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2023\n"
|
||||||
|
"Language-Team: Danish (https://app.transifex.com/odoo/teams/41243/da/)\n"
|
||||||
|
"Language: da\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Er du sikker på du vil slette dette datasæt?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Basis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Sammenfald rækker"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Opret"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Dag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Udvid rækker"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt visning"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Gantt arving kan kun være et felt eller en skabelon, fik %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt skal have en 'date_start' egenskab"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt skal have en 'date_stop' egenskab"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Gantt visning kan kun indeholde én skabelons tag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr "Gruppering per dato er ikke understøttet"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Utilstrækkelig felter til Gantt visning!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Ugyldig default_scale '%s' i gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Måned"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Ny"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Næste"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Åben"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planlæg"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr "Plan eksisterer"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Forrige"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "I dag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Udefineret %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Uge"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "År"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Larissa Manderfeld, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Larissa Manderfeld, 2024\n"
|
||||||
|
"Language-Team: German (https://app.transifex.com/odoo/teams/41243/de/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: de\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sSt.%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s kann nicht in der Vergangenheit liegen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sSt."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Ansicht des Aktionsfensters"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Dense-Modus aktivieren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Sparse-Modus aktivieren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Anwenden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Sind Sie sicher, dass Sie diesen Datensatz löschen möchten?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Basis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Zeilen einklappen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Erstellen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Bearbeiten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Zeilen erweitern"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Heute fokussieren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Von"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt-Ansicht"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Untergeordnetes Gantt kann nur Feld oder Vorlage sein, %s erhalten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt muss ein „date_start“-Attribut haben"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt muss ein „date_stop“-Attribut haben"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt muss ein „dependency_inverted_field“-Attribut haben, sobald das "
|
||||||
|
"„dependency_field“ bestimmt wurde"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Gantt-Startdatum"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Gantt-Enddatum"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Gantt-Ansicht kann nur ein Vorlagen-Stichwort beinhalten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Kann nicht in der Vergangenheit liegen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Unzureichende Felder für die Gantt-Ansicht!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Ungültige Attribute (%(invalid_attributes)s) in der Gantt-Ansicht. Attribute"
|
||||||
|
" müssen in (%(valid_attributes)s) stehen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "Ungültige default_range „%s“ in Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Ungültige default_scale „%s“ in Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "Ungültiger display_mode „%s“ in Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Namen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Neu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Öffnen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Verschiebung erfolgreich abgeschlossen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Loslegen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stopp"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Die Abhängigkeiten sind nicht gültig, es gibt einen Kreis."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Es sind keine gültigen Kandidaten neu zu planen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Diesen Monat"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Dieses Quartal"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Diese Woche"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Dieses Jahr"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Heute"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Symbolleistenmenü"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Gesamt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s Undefiniert"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Ansicht"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Ansichtstyp"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Sie können %(record)s nicht nach %(related_record)s verschieben."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "Sie können %(main_record)s nicht nach %(other_record)s verschieben."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "Stunden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "Minuten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "Monate"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "bis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
# 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: 2023-05-16 16:03+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"
|
||||||
|
"Language: el\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Δημιουργία"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Ημέρα"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Προβολή Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Μήνας"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Επόμενο"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Ανοιχτό"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Σχεδίασε"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Προηγούμενο"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Σήμερα"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Εβδομάδα"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "Έτος"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Spanish (https://app.transifex.com/odoo/teams/41243/es/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: es\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s h %(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s no se puede programar en el pasado"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s h"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Vista de la ventana de acción"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Activar modo denso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Activar modo disperso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Aplicar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "¿Está 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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Ocultar filas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Crear"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Editar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Expandir filas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Enfoque de hoy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Desde"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vista Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt debe tener un atributo \"date_start\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt debe tener un atributo \"date_stop\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Fecha de inicio de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Fecha de finalización de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "La vista de Gantt solo puede contener una etiqueta de plantilla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "No es posible programar en el pasado."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "¡Campos insuficientes para la vista de Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Atributos no válidos (%(invalid_attributes)s) en la vista gantt. Los "
|
||||||
|
"atributos deben estar en (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' no válido en Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Default_scale '%s' no válida en vista de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode \"%s\" no válido en gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nuevo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Abrir"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planificar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Iniciar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Detener"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Las dependencias no son válidas, hay un ciclo."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "No hay candidatos válidos para replanificar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Este mes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Este trimestre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Esta semana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Este año"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hoy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menú de barra de herramientas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s sin definir"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tipo de vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "No puede mover %(record)s a %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "No puede reprogramar %(main_record)s a %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "horas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minutos"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "meses"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "a"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Patricia Gutiérrez Capetillo <pagc@odoo.com>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Patricia Gutiérrez Capetillo <pagc@odoo.com>, 2024\n"
|
||||||
|
"Language-Team: Spanish (Latin America) (https://app.transifex.com/odoo/teams/41243/es_419/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: es_419\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s no se puede programar en el pasado"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Vista de acción de ventana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Activar modo denso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Activar modo disperso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Aplicar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "¿Está 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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Contraer filas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Crear"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Editar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Expandir filas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Importantes de hoy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Desde"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vista de gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Gantt secundario solo puede ser un campo o plantilla, obtuvo %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt debe tener un atributo \"date_start\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt debe tener un atributo \"date_stopt\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Fecha de inicio de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Fecha de finalización de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "La vista de Gantt solo puede contener una etiqueta de plantilla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "No es posible programar en el pasado."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Campos insuficientes para la vista de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Atributos inválidos (%(invalid_attributes)s) en la vista de Gantt. Los "
|
||||||
|
"atributos deben estar en (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' no válido en Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Default_scale '%s' no válida en vista gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode \"%s\" inválido en la vista de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nuevo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Abierto"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Reprogramación realizada con éxito."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Iniciar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Detener"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Las dependencias no son válidas, hay un ciclo."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "No hay candidatos válidos para replanificar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Este mes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Este trimestre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Esta semana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Este año"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hoy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menú de barra de herramientas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s sin definir"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Ver tipo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "No puede mover %(record)s a %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "No puede mover %(main_record)s a %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "horas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minutos"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "meses"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "para"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Siim Raasuke, 2024
|
||||||
|
# Stevin Lilla, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
# Eneli Õigus <enelioigus@gmail.com>, 2024
|
||||||
|
# Anna, 2024
|
||||||
|
# Triine Aavik <triine@avalah.ee>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Triine Aavik <triine@avalah.ee>, 2024\n"
|
||||||
|
"Language-Team: Estonian (https://app.transifex.com/odoo/teams/41243/et/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: et\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)stundi%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%stund"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Toimingu akna vaade"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Kinnita"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Kas oled kindel, et soovid antud kirjet kustutada?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Baas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "peida read"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Loo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Muuda"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Laienda ridu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Kellelt?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantti vaade"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Vigane default_scale '%s' ganti vaates"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nimi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Uus"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Avatud"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plaan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Alusta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Peata"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "See kuu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "See nädal"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "See aasta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Täna"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Kokku"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Määramata %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vaade"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Vaate tüüp"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "tundi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minutit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "kuud"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "kuni"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,367 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Tiffany Chang, 2024
|
||||||
|
# Miku Laitinen <miku.laitinen@gmail.com>, 2024
|
||||||
|
# Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2024
|
||||||
|
# Mikko Salmela <salmemik@gmail.com>, 2024
|
||||||
|
# Ossi Mantylahti <ossi.mantylahti@obs-solutions.fi>, 2024
|
||||||
|
# Tuomo Aura <tuomo.aura@web-veistamo.fi>, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2024\n"
|
||||||
|
"Language-Team: Finnish (https://app.transifex.com/odoo/teams/41243/fi/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: fi\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Toimintoikkunan näkymä"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Käytä"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Oletko varma, että haluat poistaa tämän tietueen?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Pohja"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Supista rivit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Luo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Muokkaa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Laajenna rivit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Alkaa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt-näkymä"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Gantt-kaavion alataso voi olla vain kenttä tai malli, saatiin %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Ganttissa on oltava attribuutti 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Ganttissa on oltava attribuutti 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Ganttissa on oltava attribuutti 'dependency_inverted_field', kun "
|
||||||
|
"'dependency_field' on määritetty"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Gantt-näkymä voi sisältää vain yhden mallitunnisteen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Kenttiä ei ole tarpeeksi Gantt-näkymään!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Ganttissa on virheellinen default_scale '%s'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nimi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Uusi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Avoin"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Suunnittele"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Aloitus"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Lopeta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Tässä kuussa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Tällä viikolla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Tämä vuosi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Tänään"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Yhteensä"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Määrittelemätön %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Näytä"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Näkymän tyyppi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "tunti(a)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuutit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "kuukaudet"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "->"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,366 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: French (https://app.transifex.com/odoo/teams/41243/fr/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s ne peut pas être planifié dans le passé"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Vue de la fenêtre d'action"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Activer le mode dense"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Activer le mode clairsemé"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Appliquer"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Plier les lignes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Créer"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Modifier"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Déplier les lignes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Cibler la date d'aujourd'hui"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "À partir de"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vue de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt doit avoir un attribut 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt doit avoir un attribut 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gant doit avoir un attribut 'dependency_inverted_field' dès que le "
|
||||||
|
"'dependency_field' est défini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Date de début Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Date de fin Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "La vue Gantt peut uniquement contenir une étiquette de modèles"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Impossible de planifier dans le passé."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Champs insuffisants pour la vue Gantt !"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Des attributs invalides se trouvent (%(invalid_attributes)s) dans la vue "
|
||||||
|
"Gantt. Les attributs doivent être en (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' invalide dans gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "default_scale '%s' invalide dans Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "Display_mode '%s' invalide dans Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nouveau"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Ouvert"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planifier"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Lancer"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Arrêter"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Les dépendances ne sont pas valides, il y a un cycle."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Il n'y a pas de candidats valides à replanifier."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Ce mois"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Ce trimestre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Cette semaine"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Cette année"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Aujourd'hui"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menu barre d'outils"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s indéfini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vue"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Type de vue"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Vous ne pouvez pas déplacer %(record)s vers %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
"Vous ne pouvez pas reprogrammer %(main_record)s vers %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "heures"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minutes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "mois"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "au"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# שהאב חוסיין <shhab89@gmail.com>, 2024
|
||||||
|
# MichaelHadar, 2024
|
||||||
|
# דודי מלכה <Dudimalka6@gmail.com>, 2024
|
||||||
|
# Yihya Hugirat <hugirat@gmail.com>, 2024
|
||||||
|
# Lilach Gilliam <lilach.gilliam@gmail.com>, 2024
|
||||||
|
# ZVI BLONDER <ZVIBLONDER@gmail.com>, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2024\n"
|
||||||
|
"Language-Team: Hebrew (https://app.transifex.com/odoo/teams/41243/he/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: he\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "תצוגת חלון פעולה"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "החל"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "צמצם שורות"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "יצירה"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "ערוך"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "הרחב שורות"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "מ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "גאנט"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "תצוגת גאנט"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "גאנט מחייב הגדרת \"תאריך התחלה\":"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "גאנט מחייב הגדרת \"תאריך סיום\":"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "אין מספיק שדות לתצוגת גאנט!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "שם"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "חדש"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "פתח"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "תוכנית"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "התחל"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "עצור"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "חודש נוכחי"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "שבוע נוכחי"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "שנה נוכחית"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "היום"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "סה\"כ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s לא מוגדר"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "תצוגה"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "סוג תצוגה"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "שעות"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "דקות"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "חודשים"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "ל"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,359 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2024\n"
|
||||||
|
"Language-Team: Hindi (https://app.transifex.com/odoo/teams/41243/hi/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: hi\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "बनाएँ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "संपादित"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "नया"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Igor Krizanovic <krizanovic.igor@gmail.com>, 2024
|
||||||
|
# Vladimir Olujić <olujic.vladimir@storm.hr>, 2024
|
||||||
|
# Karolina Tonković <karolina.tonkovic@storm.hr>, 2024
|
||||||
|
# Bole <bole@dajmi5.com>, 2024
|
||||||
|
# Kristina Palaš, 2024
|
||||||
|
# Tina Milas, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2024\n"
|
||||||
|
"Language-Team: Croatian (https://app.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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Radni prozor"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Primjeni"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Kreiraj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Uredi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Od"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantogram"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantogram"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Naziv"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Novi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Otvori"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Start"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Kraj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Ovaj mjesec"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Ovaj tjedan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Ove godine"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Danas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Ukupno"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Pogledaj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tip pogleda"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "sati"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "mjeseci"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "do"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# gezza <geza.nagy@oregional.hu>, 2022
|
||||||
|
# Tamás Németh <ntomasz81@gmail.com>, 2022
|
||||||
|
# Istvan <leki69@gmail.com>, 2022
|
||||||
|
# Csaba Tóth <i3rendszerhaz@gmail.com>, 2022
|
||||||
|
# Martin Trigaux, 2022
|
||||||
|
# krnkris, 2023
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
|
||||||
|
"Last-Translator: krnkris, 2023\n"
|
||||||
|
"Language-Team: Hungarian (https://app.transifex.com/odoo/teams/41243/hu/)\n"
|
||||||
|
"Language: hu\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Sorok becsukása"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Létrehozás"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Nap"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Sorok kinyitása"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt nézet"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Hónap"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Új"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Következő"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Megnyitás"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Terv"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Előző"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Ma"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Megtekintés"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Hét"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "Év"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Abe Manyo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Abe Manyo, 2024\n"
|
||||||
|
"Language-Team: Indonesian (https://app.transifex.com/odoo/teams/41243/id/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: id\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sj%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s tidak dapat dijadwalkan di masa lalu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Jendela Tindakan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Aktifkan mode dense"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Aktifkan mode sparse"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Terapkan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Apakah Anda yakin ingin menghapus record ini?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Base"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Tutup baris"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Buat"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Edit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Perluas baris"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Fokus Hari Ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Dari"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Tampilan Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Anak Gantt hanya dapat menjadi field atau templat, memiliki %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt harus memiliki attribute 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt harus memiliki attribute 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt harus memiliki attribute 'dependency_inverted_field' setelah "
|
||||||
|
"'dependency_field' ditentukan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Tanggal mulai Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Tanggal berhenti Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Tampilan Gantt hanya dapat memiliki satu tag templat"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Tidak dapat menjadwalkan di masa lalu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Field tidak mencukupi untuk Tampilan Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Atribut tidak valid (%(invalid_attributes)s) di tampilan gantt. Atribut "
|
||||||
|
"harus dalam (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' tidak valid di gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "default_scale '%s' invalid di Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode '%s' tidak valid d gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nama"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Baru"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Terbuka"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Rencana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Dijadwalkan ulang dengan sukses."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Mulai"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stop"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Ketergantungan tidak valid, terdapat cycle."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Tidak ada kandidat yang valid untuk direncanakan ulang"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Bulan ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Triwulan ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Minggu ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Tahun ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hari Ini"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menu toolbar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Undefined %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Tampilan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tipe Tampilan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Anda tidak dapat menggerakkan %(record)s ke %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
"Anda tidak dapat menjadwalkan ulang %(main_record)s ke %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "jam"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "menit"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "bulan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "kepada"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Marianna Ciofani, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Marianna Ciofani, 2024\n"
|
||||||
|
"Language-Team: Italian (https://app.transifex.com/odoo/teams/41243/it/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: it\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s:%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s non può essere programmato nel passato"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Azione visualizzazione finestra"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Attiva modalità dense"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Attiva modalità sparse"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Applica"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Contrai righe"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Crea"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Modifica"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Espandi righe"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Focus oggi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Da"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vista Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
"Una riga figlia Gantt può essere solo un campo o un modello, tu hai %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt deve possedere un attributo \"date_start\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt deve possedere un attributo \"date_stop\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"La vista Gantt deve avere un attributo 'dependency_inverted_field' una volta"
|
||||||
|
" che il 'dependency_field' viene specificato"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Data di inizio gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Data di fine gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "La vista Gantt può contenere un solo tag templates"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Impossibile programmare in passato."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Campi non sufficienti per la vista Gantt."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Attributi non validi (%(invalid_attributes)s) nella vista gantt, devono "
|
||||||
|
"essere tra (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range non valido '%s' in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "default_scale \"%s\" non valido in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode \"%s\" non valida in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nome"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nuovo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Apri"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Pianificazione"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Riprogrammazione avvenuta con successo."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Avvia"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Ferma"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Le dipendenze non sono valide, c'è un ciclo."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Non sono presenti candidati validi per la ripianificazione"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Questo mese"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Questo trimestre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Questa settimana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Questo anno"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Oggi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menu barra degli strumenti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Totale"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "%s non definiti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tipo vista"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Impossibile spostare %(record)s in %(related_record)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "Impossibile riprogrammare %(main_record)s in %(other_record)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "ore"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "mesi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "a"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,362 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Junko Augias, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Junko Augias, 2024\n"
|
||||||
|
"Language-Team: Japanese (https://app.transifex.com/odoo/teams/41243/ja/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: ja\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%sは過去に予定することはできません"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "アクションウィンドウビュー"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "デンスモードを有効化する"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "スパースモードを有効化する"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "適用"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "行を折りたたむ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "作成"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "編集"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "行を展開"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "今日のフォーカス"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "from"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "ガント"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "ガントビュー"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "ガントのchildはフィールドまたはテンプレートのみにできますが、%sを取得しました"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "ガントには'date_start'属性が必要です"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "ガントには'date_stop'属性が必要です"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"'dependency_field' が指定されたら、ガントは 'dependency_inverted_field' を持つ必要があります。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "ガント開始日"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "ガント停止日"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "ガントビューには、テンプレートタグを1つだけ含めることができます"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "過去に予定することはできません。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "ガントビューのフィールドが不十分です!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"ガントビューの属性 (%(invalid_attributes)s)が無効です。属性は(%(valid_attributes)s)である必要があります。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "ガントでの無効な default_range '%s' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "ganttのdefault_scale '%s'が無効です"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "ガントでの無効な display_mode '%s' "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "名称"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "新規"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "開く"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "計画"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "正常に再スケジュールされました。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "開始"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "停止"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "依存関係が有効でなく、サイクルがあります。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "再計画に有効な候補者はいません"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "今月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "今四半期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "今週"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "今年"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "今日"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "ツールバーメニュー"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "合計"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "未定義の%s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "ビュー"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "ビュータイプ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr " %(record)sを %(related_record)sへ移動することはできません。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr " %(record)sを %(related_record)sへリスケジュールすることはできません。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "時間"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "分"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "か月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "から"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Daye Jeong, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Daye Jeong, 2024\n"
|
||||||
|
"Language-Team: Korean (https://app.transifex.com/odoo/teams/41243/ko/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: ko\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s시간 %(minute)s분"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s는 과거로 예약할 수 없습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "작업 윈도우 보기"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "dense mode 활성화"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "sparse mode 활성화"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "적용"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "행 축소"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "작성"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "편집"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "행 확장"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "오늘의 포커스"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "시작 시간"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "간트 차트"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "간트 화면"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "간트 하위 메뉴는 필드나 템플릿만 선택 가능하며, 다음 내용입니다 %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "간트에는 'date_start' 속성을 지정해야 합니다"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "간트에는 'date_stop' 속성을 지정해야 합니다"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"'dependency_field'가 지정되는 경우, 간트에서 'dependency_inverted_field' 속성을 지정해야 합니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "간트 시작일"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "간트 종료일"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "간트 뷰에는 서식 태그가 하나만 포함될 수 있습니다"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "지난 시점으로는 예약할 수 없습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "간트 차트 화면에 대한 필드가 충분하지 않습니다!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"간트 보기에 잘못된 속성 (%(invalid_attributes)s)이 있습니다. 속성은 (%(valid_attributes)s)에 "
|
||||||
|
"위치해야 합니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "간트에 잘못된 default_range '%s'가 있습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "간트에서 default_scale '%s' 가 유효하지 않습니다"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "간트에 잘못된 display_mode '%s'가 있습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "이름"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "신규"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "열기"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "계획"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "일정 변경이 성공적으로 완료되었습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "시작"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "중지"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "종속성이 유효하지 않으며 주기가 있습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "다시 계획할 수 있는 적격 후보자가 없습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "이번 달"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "이번 분기"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "이번 주"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "올해"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "오늘"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "도구 모음 메뉴"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "총계"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "정의되지 않은 %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "화면"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "화면 유형"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "%(record)s를 %(related_record)s로 이동할 수 없습니다."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "%(main_record)s을 %(other_record)s으로 일정을 변경할 수 없습니다. "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "시간"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "분"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "월"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "종료"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,257 @@
|
||||||
|
# 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: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2019-08-26 09:38+0000\n"
|
||||||
|
"Language-Team: Luxembourgish (https://www.transifex.com/odoo/teams/41243/lb/)\n"
|
||||||
|
"Language: lb\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Audrius Palenskis <audrius.palenskis@gmail.com>, 2022
|
||||||
|
# Rolandas <info@paninfo.lt>, 2022
|
||||||
|
# Edgaras Kriukonis <edgaras@focusate.eu>, 2022
|
||||||
|
# Ramunė ViaLaurea <ramune.vialaurea@gmail.com>, 2022
|
||||||
|
# Naglis Jonaitis, 2022
|
||||||
|
# Martin Trigaux, 2022
|
||||||
|
# Linas Versada <linaskrisiukenas@gmail.com>, 2023
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
|
||||||
|
"Last-Translator: Linas Versada <linaskrisiukenas@gmail.com>, 2023\n"
|
||||||
|
"Language-Team: Lithuanian (https://app.transifex.com/odoo/teams/41243/lt/)\n"
|
||||||
|
"Language: lt\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Ar tikrai norite ištrinti šį įrašą?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Bazė"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Sutraukti eilutes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Sukurti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Diena"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Išskleisti eilutes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Ganto vaizdas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Ganto diagrama privalo turėti pradžios ir pabaigos požymius"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr "Grupavimas pagal datas nepalaikomas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Mėnuo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Naujas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Kitas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Atidaryti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Suplanuoti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Ankstesnis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Šiandien"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Nežinoma %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Peržiūrėti"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Savaitė"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "Metai"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Bayarkhuu Bataa, 2024
|
||||||
|
# Batmunkh Ganbat <batmunkh2522@gmail.com>, 2024
|
||||||
|
# Uuganbayar Batbaatar <uuganaaub33@gmail.com>, 2024
|
||||||
|
# Baskhuu Lodoikhuu <baskhuujacara@gmail.com>, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
# hish, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: hish, 2024\n"
|
||||||
|
"Language-Team: Mongolian (https://app.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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Үйлдлийн цонх харагдац"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Хэрэгжүүлэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Мөрүүдийг хумих"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Үүсгэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Засах"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Мөрүүдийг дэлгэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Эхлэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Хүснэгтлэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Хүснэгтлэн харах"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Нэр"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Шинэ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Нээх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Төлөвлөх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Эхлэх"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Зогс"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Энэ сар"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Энэ долоо хоног"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Өнөөдөр"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Нийт дүн"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Харах"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Дэлгэцийн төрөл"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "цаг"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "минут"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "сарууд"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "дуусах"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,262 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Marius Stedjan <marius@stedjan.com>, 2022
|
||||||
|
# Martin Trigaux, 2023
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2023\n"
|
||||||
|
"Language-Team: Norwegian Bokmål (https://app.transifex.com/odoo/teams/41243/nb/)\n"
|
||||||
|
"Language: nb\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Opprett"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Dag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt-visning"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Måned"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Ny"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Neste"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Åpen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planlegg"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Tilbake"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "I dag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Vis"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Uke"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "År"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Erwin van der Ploeg <erwin@odooexperts.nl>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Erwin van der Ploeg <erwin@odooexperts.nl>, 2024\n"
|
||||||
|
"Language-Team: Dutch (https://app.transifex.com/odoo/teams/41243/nl/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: nl\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)su%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s kan niet in het verlden plaatsvinden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%su"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Actie venster weergave"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Dense mode activeren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Sparse mode activeren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Toepassen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Rijen inklappen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Aanmaken"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Bewerken"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Rijen uitvouwen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Focus Vandaag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Van"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt weergave"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Onderliggende Gantt kan alleen een veld of sjabloon zijn, krijg %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt moet een 'date_start' kenmerk hebben"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt moet een 'date_stop' kenmerk hebben"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gant moet een 'dependency_inverted_field' kenmerk hebben zodra het "
|
||||||
|
"'dependency_field' is gespecifieerd"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Gantt-startdatum"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Gantt-einddatum"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "De Gantt-weergave kan slechts één sjabloon-label bevatten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Je kan niet in het verleden plannen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Niet genoeg velden voor Gantt weergave!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Ongeldige kenmerken (%(invalid_attributes)s) in Gantt-weergave. Kenmerken "
|
||||||
|
"moeten in (%(valid_attributes)s) zijn"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "Ongeldige default_range '%s' in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Ongeldige default_scale '%s' in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "Ongeldige display_mode '%s' in gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Naam"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nieuw"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Openen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Met succes één opnieuw gepland."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Start"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stop"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "De afhankelijkheden zijn niet geldig, er is een cyclus."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Er zijn geen geldige kandidaten om te herplannen"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Deze maand"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Dit kwartaal"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Deze week"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Dit jaar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Vandaag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Werkbalkmenu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Totaal"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Niet gedefinieerd %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Bekijk"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Soort weergave"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Je kunt %(record)s niet naar %(related_record)s verplaatsen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "Je kunt %(main_record)s niet op %(other_record)s herplannen."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "uren"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuten"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "maanden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "aan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,361 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Polish (https://app.transifex.com/odoo/teams/41243/pl/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: pl\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Widok okna akcji"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Zastosuj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Czy na pewno chcesz usunąć ten rekord?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Baza"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Zwiń wiersze"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Utwórz"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Edytuj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Rozwiń wiersze"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Od"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Wykres Gantta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Widok Gantta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Dziecko Gantt może być tylko polem lub szablonem, mam %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt musi mieć atrybut \"date_start\"."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt musi mieć atrybut \"date_stop\"."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt musi mieć atrybut \"dependency_inverted_field\" po określeniu "
|
||||||
|
"\"dependency_field\"."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Widok Gantta może zawierać tylko jeden tag szablonu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Niewystarczająca liczba pól dla widoku Gantta!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Nieprawidłowy default_scale '%s' w gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nazwa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nowe"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Otwarta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Uruchom"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Zatrzymaj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Ten miesiąc"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Ten tydzień"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Ten rok"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Na dzisiaj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Suma"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Niezdefiniowany %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Widok"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Typ widoku"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "godziny"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minut"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "miesiące"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "do"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Martin Trigaux, 2022
|
||||||
|
# Nuno Silva <nuno.silva@arxi.pt>, 2022
|
||||||
|
# Manuela Silva <mmsrs@sky.com>, 2023
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-05-16 16:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2022-09-22 05:49+0000\n"
|
||||||
|
"Last-Translator: Manuela Silva <mmsrs@sky.com>, 2023\n"
|
||||||
|
"Language-Team: Portuguese (https://app.transifex.com/odoo/teams/41243/pt/)\n"
|
||||||
|
"Language: pt\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Colapsar linhas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Criar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "Dia"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Expandir linhas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vista de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Grouping by date is not supported"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Mês"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Novo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Seguinte"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Aberto"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plano"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_cell_buttons.xml:0
|
||||||
|
msgid "Plan existing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Anterior"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hoje"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Ver"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Semana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "Ano"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Maitê Dietze, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Maitê Dietze, 2024\n"
|
||||||
|
"Language-Team: Portuguese (Brazil) (https://app.transifex.com/odoo/teams/41243/pt_BR/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: pt_BR\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s não pode ser agendado no passado"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Exibição da janela de ação"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Ativar o modo denso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Ativar o modo esparso"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Aplicar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Você tem certeza de que deseja excluir este registro?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Base"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Recolher linhas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Criar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Editar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Expandir linhas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Foco em Hoje"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "De"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Visualização de Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Gantts secundários só podem ser campos ou modelos, há %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt deve ter um atributo \"date_start\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt deve ter um atributo \"date_stop\""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt deve ter um atributo \"'dependency_inverted_field\" uma vez que "
|
||||||
|
"\"dependency_field\" está especificado"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Data de início do Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Data de término do Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "A visualização de Gantt deve conter somente um marcador do modelo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "É impossível fazer agendamentos no passado."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Campos insuficientes para a visualização de Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Atributos inválidos (%(invalid_attributes)s) na visualização de Gantt. Os "
|
||||||
|
"atributos devem estar em (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "default_range '%s' inválido no Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Default_scale \"%s\" inválida em Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "Display_mode '%s' inválido em gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nome"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Novo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Aberto"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plano"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Reagendamento feito com sucesso."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Iniciar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Parar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "As dependências não são válidas; há um ciclo."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "Não há candidatos válidos para replanejar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Este mês"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Este trimestre"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Esta semana"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Este ano"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hoje"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menu da barra de ferramentas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Indefinido %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Visualização"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tipo de visualização"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Você não pode se mover %(record)s para %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "Não é possível reagendar %(main_record)s para %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "horas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minutos"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "meses"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "até"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,361 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Lyall Kindmurr, 2024
|
||||||
|
# Foldi Robert <foldirobert@nexterp.ro>, 2024
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Romanian (https://app.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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Acțiune Vizualizare Fereastră"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Aplică"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Reduceți rândurile"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Creează"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Editare"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Extindere Rânduri"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "De la"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Vizualizare Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nume"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Nou"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Afișare"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Start"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stop"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Luna aceasta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Săpt. curentă"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Anul Acesta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Astăzi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Total"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Nedefinit %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Afișare"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Tip vizualizare"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "ore"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minute"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "luni"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "la"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,258 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 17.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-01-08 07:03+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-01-30 15:14+0400\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: Russian (https://app.transifex.com/odoo/teams/41243/ru/)\n"
|
||||||
|
"Language: ru\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Свернуть ряды"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Создать"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Day"
|
||||||
|
msgstr "День"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Редактировать"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Расширить ряды"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_view.js:0
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Гантт"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Вид Гантт"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Дочерний элемент Ганта может быть только полем или шаблоном, получено %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Гант должен иметь атрибут 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Гант должен иметь атрибут 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'dependency_inverted_field' attribute once the 'dependency_field' is specified"
|
||||||
|
msgstr "Gantt должен иметь атрибут 'dependency_inverted_field' после указания 'dependency_field'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Представление Ганта может содержать только один тег шаблона"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Недостаточно полей для представления Ганта!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid attributes (%s) in gantt view. Attributes must be in (%s)"
|
||||||
|
msgstr "Недопустимые атрибуты (%s) в представлении Ганта. Атрибуты должны быть в (%s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Недопустимая шкала по умолчанию '%s' в гигантской схеме"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Month"
|
||||||
|
msgstr "Месяц"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Имя"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Новый"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Следующий"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Открыть"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "План"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Previous"
|
||||||
|
msgstr "Предыдущий"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Records that are in the past cannot be automatically rescheduled. They should be manually rescheduled instead."
|
||||||
|
msgstr "Записи, которые находятся в прошлом, не могут быть автоматически перенесены. Их следует переносить вручную."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Начало"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Стоп"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.xml:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Сегодня"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Всего"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Неопределено %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Просмотр"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Week"
|
||||||
|
msgstr "Неделя"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Year"
|
||||||
|
msgstr "Год"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %s towards %s."
|
||||||
|
msgstr "Вы не можете перенести %s на %s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule tasks that do not follow a direct dependency path. Only the first task has been automatically rescheduled."
|
||||||
|
msgstr "Вы не можете перенести в график задачи, которые не следуют прямому пути зависимости. Автоматически переносится только первая задача."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "часов"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "минут"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "месяцев"
|
||||||
|
|
@ -0,0 +1,359 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Slovenian (https://app.transifex.com/odoo/teams/41243/sl/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: sl\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Pogled okna za ukrep"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Uporabi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr "Ste prepričani, da želite izbrisati ta zapis?"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Osnova"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Strni vrstice"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Ustvari"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Uredi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Razširi vrstice"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Od"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt diagram"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Naziv"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Novo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Odprto"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Prični"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Ustavi"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Ta mesec"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Ta teden"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Danes"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Skupaj"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Prikaz"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Vrsta prikaza"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "ure"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minute"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "meseci"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "do"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,367 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Mikael Åkerberg <mikael.akerberg@mariaakerberg.com>, 2024
|
||||||
|
# 03992e16f8df6e39b9d1cc0ff635887e, 2024
|
||||||
|
# Martin Wilderoth <martin.wilderoth@linserv.se>, 2024
|
||||||
|
# Simon S, 2024
|
||||||
|
# Anders Wallenquist <anders.wallenquist@vertel.se>, 2024
|
||||||
|
# Chrille Hedberg <hedberg.chrille@gmail.com>, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
# Kristoffer Grundström <lovaren@gmail.com>, 2024
|
||||||
|
# Jakob Krabbe <jakob.krabbe@vertel.se>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Jakob Krabbe <jakob.krabbe@vertel.se>, 2024\n"
|
||||||
|
"Language-Team: Swedish (https://app.transifex.com/odoo/teams/41243/sv/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: sv\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Vy för åtgärdsfönster"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Verkställ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Are you sure to delete this record?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_base
|
||||||
|
msgid "Base"
|
||||||
|
msgstr "Bas"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Skapa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Redigera"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Från"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Ganttvy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Namn"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Ny"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Öppna"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Start"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stoppa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Denna månad"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Denna vecka"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Detta år"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Idag"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Totalt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Visa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Typ av vy"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "timmar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "minuter"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "månader"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "till"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Wil Odoo, 2024\n"
|
||||||
|
"Language-Team: Thai (https://app.transifex.com/odoo/teams/41243/th/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: th\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s ชั่วโมง %(minute)s นาที"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s ไม่สามารถกำหนดเวลาในอดีตได้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s ชั่วโมง"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "มุมมองหน้าต่างการดำเนินการ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "นำไปใช้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "ย่อแถว"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "สร้าง"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "แก้ไข"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "ขยายแถว"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "จาก"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "แกนต์"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "มุมมองแบบแกนต์"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "แกนต์ย่อยได้เฉพาะฟิลด์หรือเทมเพลตเท่านั้น มี %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "แกนต์ต้องมี 'date_start' แอตทริบิวต์ "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "แกนต์ต้องมี \"date_stop\" แอตทริบิวต์ "
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt ต้องมีแอตทริบิวต์ 'dependency_inverted_field' เมื่อระบุ "
|
||||||
|
"'dependency_field' แล้ว"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "มุมมองแกนต์สามารถมีแท็กเทมเพลตได้เพียงแท็กเดียว"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "ไม่สามารถกำหนดเวลาในอดีตได้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "ฟิลด์ไม่เพียงพอสำหรับมุมมองแกนต์!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"แอตทริบิวต์ไม่ถูกต้อง (%(invalid_attributes)s) ในมุมมองแกนต์ "
|
||||||
|
"แอตทริบิวต์ต้องอยู่ใน (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Invalid default_scale '%s' ในแกนต์"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode '%s' ไม่ถูกต้องในแกนต์"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "ชื่อ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "ใหม่"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "เปิด"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "แผน"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "เริ่ม"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "หยุด"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "การขึ้นต่อกันไม่ถูกต้อง มีวงจรอยู่"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "ไม่มีผู้สมัครที่ถูกต้องที่จะวางแผนใหม่"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "เดือนนี้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "สัปดาห์นี้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "ปีนี้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "วันนี้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "รวม"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "ไม่กำหนด %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "ดู"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "ประเภทมุมมอง"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "คุณไม่สามารถย้าย %(record)s ไปยัง %( related_record)s ได้"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "คุณไม่สามารถจัดกำหนดการใหม่ %(main_record)s ไปยัง %(other_record)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "ชั่วโมง"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "นาที"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "เดือน"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "ถึง"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,372 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Ahmet Altinisik <aaltinisik@altinkaya.com.tr>, 2024
|
||||||
|
# Ozlem Cikrikci <ozlemc@eskayazilim.com.tr>, 2024
|
||||||
|
# Tugay Hatıl <tugayh@projetgrup.com>, 2024
|
||||||
|
# Gökhan Erdoğdu <gokhan.erdogdu@mechsoft.com.tr>, 2024
|
||||||
|
# Levent Karakaş <levent@mektup.at>, 2024
|
||||||
|
# abc Def <hdogan1974@gmail.com>, 2024
|
||||||
|
# Murat Kaplan <muratk@projetgrup.com>, 2024
|
||||||
|
# Ediz Duman <neps1192@gmail.com>, 2024
|
||||||
|
# Ertuğrul Güreş <ertugrulg@projetgrup.com>, 2024
|
||||||
|
# Halil, 2024
|
||||||
|
# Murat Durmuş <muratd@projetgrup.com>, 2024
|
||||||
|
# Martin Trigaux, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Martin Trigaux, 2024\n"
|
||||||
|
"Language-Team: Turkish (https://app.transifex.com/odoo/teams/41243/tr/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: tr\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Pencere Aksiyon Görünümü"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Uygula"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Satırları daralt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Oluştur"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Düzenle"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Satırları genişlet"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Başlama"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Gantt Görünümü"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Gantt alt öğesi yalnızca alan veya şablon olabilir, %svar"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt'ın bir 'date_start' özelliği olmalıdır"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt'ın bir 'date_stop' özelliği olmalıdır"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"\"dependency_field\" belirtildikten sonra Gantt'ın "
|
||||||
|
"\"dependency_inverted_field\" özniteliğine sahip olması gerekir"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
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
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Gantt görünümü için yetersiz alanlar!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Gantt'ta geçersiz default_scale '%s'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Adı"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Yeni"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Açık"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Planla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Başla"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Durdur"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Bu Ay"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Bu Hafta"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Bu Yıl"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Bugün"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Toplam"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Tanımsız %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Görüntüle"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Görünüm Türü"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "saat"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "dakika"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "ay"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "den"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Alina Lisnenko <alina.lisnenko@erp.co.ua>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Alina Lisnenko <alina.lisnenko@erp.co.ua>, 2024\n"
|
||||||
|
"Language-Team: Ukrainian (https://app.transifex.com/odoo/teams/41243/uk/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: uk\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sгод%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sгод"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Перегляд вікна дії"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Застосувати"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Згорнути рядки"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Створити"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Редагувати"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Розгорнути рядки"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Від"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Діаграма Ґанта"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Перегляд діаграми Ґанта"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
"Дочірня діаграма Ганта може бути лише полем або шаблоном, отримайте %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Діаграма Ганта повинна мати атрибут 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Діаграма Ганта повинна мати атрибут 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Гант повинен мати атрибут 'dependency_inverted_field', коли вказано "
|
||||||
|
"'dependency_field'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Діаграма Ганта може містити лише один тег шаблону"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Недостатньо полів для перегляду діаграми Ганта!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Недійсне default_scale '%s' у діаграмі Ганта"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Назва"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Новий"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Відкрито"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "План"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Початок"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Зупинити"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Цього місяця"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Цього тижня"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Цього року"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Сьогодні"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Разом"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Невизначений %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Перегляд"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Тип перегляду"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "годин"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "хвилин"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "місяців"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "до"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Thi Huong Nguyen, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Thi Huong Nguyen, 2024\n"
|
||||||
|
"Language-Team: Vietnamese (https://app.transifex.com/odoo/teams/41243/vi/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: vi\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)sh%(minute)s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s không thể được lên lịch trong quá khứ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%sh"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "Chế độ xem cửa sổ tác vụ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "Kích hoạt dense mode"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "Kích hoạt sparse mode"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Áp dụng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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ơ sở"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "Thu gọn hàng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Tạo"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Chỉnh sửa"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "Mở rộng hàng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "Tiêu điểm hôm nay"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Từ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "Biểu đồ Gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "Phần phụ của Gantt chỉ có thể là trường hoặc mẫu, nhưng đây là %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "Gantt cần có một thuột tính 'date_start'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "Gantt cần có một thuột tính 'date_stop'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
"Gantt phải có thuộc tính 'dependency_inverted_field' sau khi xác định "
|
||||||
|
"'dependency_field'"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "Ngày bắt đầu gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "Ngày ngừng gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "Chế độ xem Gantt chỉ có thể chứa một thẻ mẫu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "Không thể lên lịch trong quá khứ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "Không đủ trường cho Chế độ xem Gantt!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
"Thuộc tính không hợp lệ (%(invalid_attributes)s) trong chế độ xem gantt. Các"
|
||||||
|
" thuộc tính phải có dạng (%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "Default_range '%s' không hợp lệ trong gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "Default_scale không hợp hệ '%s' trong gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "display_mode không hợp hệ '%s' trong gantt"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Tên"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "Mới"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "Mở"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "Kế hoạch"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "Đã lên lịch lại thành công."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "Bắt đầu"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Ngừng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "Phần phụ thuộc không hợp lệ, có một chu kỳ."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "There are no valid candidates to re-plan"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "Tháng này"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "Quý này"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "Tuần này"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "Năm nay"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hôm nay"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "Menu thanh công cụ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Tổng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "Không xác định %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Chế độ xem"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "Dạng hiển thị"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "Bạn không thể chuyển %(record)s đến %(related_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "Bạn không thể lên lịch lại %(main_record)s sang %(other_record)s."
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "giờ"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "phút"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "tháng"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "đến"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,355 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Odoo哥 <vnsoft.he@gmail.com>, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Odoo哥 <vnsoft.he@gmail.com>, 2024\n"
|
||||||
|
"Language-Team: Chinese (China) (https://app.transifex.com/odoo/teams/41243/zh_CN/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: zh_CN\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s小时%(minute)s分钟"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s 无法排期至过往日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s小时"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "动作窗口视图"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "激活密集模式"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "激活稀疏模式"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "应用"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "折叠行"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "创建"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "编辑"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "展开行"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "聚焦到今天"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "来自"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "甘特图"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "甘特视图"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "甘特儿只能是字段或模板,转到%s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "甘特图必须有一个'date_start'属性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "甘特图必须有一个'date_stop'属性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr "一旦指定了 \"依赖关系_字段\",甘特图就必须具有 \"依赖关系_反转字段 \"属性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "甘特图开始日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "甘特图结束日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "甘特图视图只能包含一个模板标签"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "无法排期到已往的日期。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "甘特图视图的字段不足!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr "甘特图视图中的属性(%(invalid_attributes)s)无效,属性必须在(%(valid_attributes)s)之中。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "甘特图中的default_range'%s'无效"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "甘特图中的default_scale'%s无效"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "甘特图中的display_mode'%s'无效"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "名称"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "新建"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "打开"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "安排"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "重新安排成功完成。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "开始"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "停止"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "依赖项目无效:存在一个循环。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "没有有效的候选人来重新规划"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "本月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "本季度"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "本周"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "今年"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "今天"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "工具栏菜单"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "总计"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "未定义的 %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "视图"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "视图类型"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "您不可移动%(record)s至%(related_record)s。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "您不可重新排期%(main_record)s至%(other_record)s。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "小时"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "分钟"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "到"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * web_gantt
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Wil Odoo, 2024
|
||||||
|
# Tony Ng, 2024
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 18.0+e\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-09-25 09:29+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-09-25 09:44+0000\n"
|
||||||
|
"Last-Translator: Tony Ng, 2024\n"
|
||||||
|
"Language-Team: Chinese (Taiwan) (https://app.transifex.com/odoo/teams/41243/zh_TW/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Language: zh_TW\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%(hour)sh%(minute)s"
|
||||||
|
msgstr "%(hour)s 小時 %(minute)s 分鐘"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "%s cannot be scheduled in the past"
|
||||||
|
msgstr "%s 不可排期至過往日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "%sh"
|
||||||
|
msgstr "%s 小時"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_actions_act_window_view
|
||||||
|
msgid "Action Window View"
|
||||||
|
msgstr "動作窗檢視"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate dense mode"
|
||||||
|
msgstr "啟動緊密模式"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Activate sparse mode"
|
||||||
|
msgstr "啟動稀疏模式"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "套用"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
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
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Collapse rows"
|
||||||
|
msgstr "摺疊列"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "建立"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "編輯"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Expand rows"
|
||||||
|
msgstr "展開列"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Focus Today"
|
||||||
|
msgstr "聚焦至今天"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "From"
|
||||||
|
msgstr "由"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_actions_act_window_view__view_mode__gantt
|
||||||
|
#: model:ir.model.fields.selection,name:web_gantt.selection__ir_ui_view__type__gantt
|
||||||
|
msgid "Gantt"
|
||||||
|
msgstr "甘特圖"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Gantt View"
|
||||||
|
msgstr "甘特圖檢視"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt child can only be field or template, got %s"
|
||||||
|
msgstr "甘特圖子項只可以是欄位或範本,但收到 %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_start' attribute"
|
||||||
|
msgstr "甘特圖必須有一個 date_start 屬性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt must have a 'date_stop' attribute"
|
||||||
|
msgstr "甘特圖必須有一個 date_stop 屬性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Gantt must have a 'dependency_inverted_field' attribute once the "
|
||||||
|
"'dependency_field' is specified"
|
||||||
|
msgstr "甘特圖若有指定 dependency_field,就必須有 dependency_inverted_field 屬性"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt start date"
|
||||||
|
msgstr "甘特圖開始日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.js:0
|
||||||
|
msgid "Gantt stop date"
|
||||||
|
msgstr "甘特圖結束日期"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Gantt view can contain only one templates tag"
|
||||||
|
msgstr "甘特圖只可包含一個範本標籤"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Impossible to schedule in the past."
|
||||||
|
msgstr "無法排期至過往日期。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Insufficient fields for Gantt View!"
|
||||||
|
msgstr "欄位數目不足以供甘特圖使用!"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid ""
|
||||||
|
"Invalid attributes (%(invalid_attributes)s) in gantt view. Attributes must "
|
||||||
|
"be in (%(valid_attributes)s)"
|
||||||
|
msgstr "甘特圖檢視畫面中的屬性(%(invalid_attributes)s)無效。屬性必須在(%(valid_attributes)s)"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_range '%s' in gantt"
|
||||||
|
msgstr "甘特圖的 default_range '%s' 無效"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid default_scale '%s' in gantt"
|
||||||
|
msgstr "甘特圖的 default_scale '%s' 無效"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/ir_ui_view.py:0
|
||||||
|
msgid "Invalid display_mode '%s' in gantt"
|
||||||
|
msgstr "甘特圖檢視模式中的顯示模式 display_mode 無效:%s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "名稱"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.xml:0
|
||||||
|
msgid "New"
|
||||||
|
msgstr "新增"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_controller.js:0
|
||||||
|
msgid "Open"
|
||||||
|
msgstr "開啟"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Plan"
|
||||||
|
msgstr "計劃"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "Reschedule done successfully."
|
||||||
|
msgstr "已成功改期。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "開始"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_popover.xml:0
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "停止"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "The dependencies are not valid, there is a cycle."
|
||||||
|
msgstr "依賴項目無效:存在一個循環。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "There are no valid candidates to re-plan"
|
||||||
|
msgstr "沒有有效的候選人可以重新規劃"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This month"
|
||||||
|
msgstr "本月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This quarter"
|
||||||
|
msgstr "本季度"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This week"
|
||||||
|
msgstr "本周"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "This year"
|
||||||
|
msgstr "本年度"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "今天"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "Toolbar menu"
|
||||||
|
msgstr "工具列選單"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "總計"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_model.js:0
|
||||||
|
msgid "Undefined %s"
|
||||||
|
msgstr "未定義 %s"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer.js:0
|
||||||
|
#: model:ir.model,name:web_gantt.model_ir_ui_view
|
||||||
|
msgid "View"
|
||||||
|
msgstr "檢視"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_actions_act_window_view__view_mode
|
||||||
|
#: model:ir.model.fields,field_description:web_gantt.field_ir_ui_view__type
|
||||||
|
msgid "View Type"
|
||||||
|
msgstr "檢視類型"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot move %(record)s towards %(related_record)s."
|
||||||
|
msgstr "你不可移動 %(record)s 至 %(related_record)s。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/web_gantt/models/models.py:0
|
||||||
|
msgid "You cannot reschedule %(main_record)s towards %(other_record)s."
|
||||||
|
msgstr "你不可重新排期 %(main_record)s 至 %(other_record)s。"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "hours"
|
||||||
|
msgstr "小時"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "minutes"
|
||||||
|
msgstr "分鐘"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_arch_parser.js:0
|
||||||
|
msgid "months"
|
||||||
|
msgstr "月"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_renderer_controls.xml:0
|
||||||
|
msgid "to"
|
||||||
|
msgstr "到"
|
||||||
|
|
||||||
|
#. module: web_gantt
|
||||||
|
#. odoo-javascript
|
||||||
|
#: code:addons/web_gantt/static/src/gantt_row_progress_bar.xml:0
|
||||||
|
msgid "{{ props.progressBar.warning }}"
|
||||||
|
msgstr "{{ props.progressBar.warning }}"
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from . import ir_ui_view
|
||||||
|
from . import ir_actions
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class ActWindowView(models.Model):
|
||||||
|
_inherit = 'ir.actions.act_window.view'
|
||||||
|
|
||||||
|
view_mode = fields.Selection(selection_add=[('gantt', 'Gantt')], ondelete={'gantt': 'cascade'})
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from odoo import fields, models, _
|
||||||
|
from odoo.tools import format_list
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
GANTT_VALID_ATTRIBUTES = set([
|
||||||
|
'__validate__', # ir.ui.view implementation detail
|
||||||
|
'date_start',
|
||||||
|
'date_stop',
|
||||||
|
'default_scale',
|
||||||
|
'default_range',
|
||||||
|
'class',
|
||||||
|
'js_class',
|
||||||
|
'form_view_id',
|
||||||
|
'progress',
|
||||||
|
'consolidation',
|
||||||
|
'consolidation_max',
|
||||||
|
'consolidation_exclude',
|
||||||
|
'string',
|
||||||
|
'create',
|
||||||
|
'on_create',
|
||||||
|
'cell_create',
|
||||||
|
'edit',
|
||||||
|
'delete',
|
||||||
|
'plan',
|
||||||
|
'default_group_by',
|
||||||
|
'dynamic_range',
|
||||||
|
'display_mode',
|
||||||
|
'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',
|
||||||
|
'groups_limit'
|
||||||
|
])
|
||||||
|
|
||||||
|
class View(models.Model):
|
||||||
|
_inherit = 'ir.ui.view'
|
||||||
|
|
||||||
|
type = fields.Selection(selection_add=[('gantt', 'Gantt')])
|
||||||
|
|
||||||
|
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', 'week_2', 'month', 'month_3', 'year'):
|
||||||
|
self._raise_view_error(_("Invalid default_scale '%s' in gantt", default_scale), node)
|
||||||
|
default_range = node.get('default_range')
|
||||||
|
if default_range:
|
||||||
|
if default_range not in ('day', 'week', 'month', 'quarter', 'year'):
|
||||||
|
self._raise_view_error(_("Invalid default_range '%s' in gantt", default_range), node)
|
||||||
|
display_mode = node.get('display_mode')
|
||||||
|
if display_mode:
|
||||||
|
if display_mode not in ('dense', 'sparse'):
|
||||||
|
self._raise_view_error(_("Invalid display_mode '%s' in gantt", display_mode), 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 (%(invalid_attributes)s) in gantt view. Attributes must be in (%(valid_attributes)s)",
|
||||||
|
invalid_attributes=format_list(self.env, remaining),
|
||||||
|
valid_attributes=format_list(self.env, GANTT_VALID_ATTRIBUTES),
|
||||||
|
)
|
||||||
|
self._raise_view_error(msg, node)
|
||||||
|
|
||||||
|
def _get_view_fields(self, view_type, models):
|
||||||
|
if view_type == 'gantt':
|
||||||
|
models[self._name] = list(self._fields.keys())
|
||||||
|
return models
|
||||||
|
return super()._get_view_fields(view_type, models)
|
||||||
|
|
||||||
|
def _get_view_info(self):
|
||||||
|
return {'gantt': {'icon': 'fa fa-tasks'}} | super()._get_view_info()
|
||||||
|
|
||||||
|
def _is_qweb_based_view(self, view_type):
|
||||||
|
return view_type == 'gantt' or super()._is_qweb_based_view(view_type)
|
||||||
|
|
@ -0,0 +1,780 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from datetime import datetime, timezone, timedelta
|
||||||
|
from lxml.builder import E
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tools import _, unique, OrderedSet
|
||||||
|
|
||||||
|
|
||||||
|
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'
|
||||||
|
_WEB_GANTT_NO_POSSIBLE_ACTION_ERROR = 'no_possible_action_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 get_gantt_data(self, domain, groupby, read_specification, limit=None, offset=0, unavailability_fields=None, progress_bar_fields=None, start_date=None, stop_date=None, scale=None):
|
||||||
|
"""
|
||||||
|
Returns the result of a read_group (and optionally search for and read records inside each
|
||||||
|
group), and the total number of groups matching the search domain.
|
||||||
|
|
||||||
|
:param domain: search domain
|
||||||
|
:param groupby: list of field to group on (see ``groupby``` param of ``read_group``)
|
||||||
|
:param read_specification: web_read specification to read records within the groups
|
||||||
|
:param limit: see ``limit`` param of ``read_group``
|
||||||
|
:param offset: see ``offset`` param of ``read_group``
|
||||||
|
:param boolean unavailability_fields
|
||||||
|
:param string start_date: start datetime in utc, e.g. "2024-06-22 23:00:00"
|
||||||
|
:param string stop_date: stop datetime in utc
|
||||||
|
:param string scale: among "day", "week", "month" and "year"
|
||||||
|
:return: {
|
||||||
|
'groups': [
|
||||||
|
{
|
||||||
|
'<groupby_1>': <value_groupby_1>,
|
||||||
|
...,
|
||||||
|
'__record_ids': [<ids>]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'records': [<record data>]
|
||||||
|
'length': total number of groups
|
||||||
|
'unavailabilities': {
|
||||||
|
'<unavailability_fields_1>': <value_unavailability_fields_1>,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
'progress_bars': {
|
||||||
|
'<progress_bar_fields_1>': <value_progress_bar_fields_1>,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
# TODO: group_expand doesn't currently respect the limit/offset
|
||||||
|
lazy = not limit and not offset and len(groupby) == 1
|
||||||
|
# Because there is no limit by group, we can fetch record_ids as aggregate
|
||||||
|
final_result = self.web_read_group(
|
||||||
|
domain, ['__record_ids:array_agg(id)'], groupby,
|
||||||
|
limit=limit, offset=offset, lazy=lazy,
|
||||||
|
)
|
||||||
|
|
||||||
|
all_record_ids = tuple(unique(
|
||||||
|
record_id
|
||||||
|
for one_group in final_result['groups']
|
||||||
|
for record_id in one_group['__record_ids']
|
||||||
|
))
|
||||||
|
|
||||||
|
# Do search_fetch to order records (model order can be no-trivial)
|
||||||
|
all_records = self.with_context(active_test=False).search_fetch([('id', 'in', all_record_ids)], read_specification.keys())
|
||||||
|
final_result['records'] = all_records.with_env(self.env).web_read(read_specification)
|
||||||
|
|
||||||
|
if unavailability_fields is None:
|
||||||
|
unavailability_fields = []
|
||||||
|
if progress_bar_fields is None:
|
||||||
|
progress_bar_fields = []
|
||||||
|
|
||||||
|
ordered_set_ids = OrderedSet(all_records._ids)
|
||||||
|
res_ids_for_unavailabilities = defaultdict(set)
|
||||||
|
res_ids_for_progress_bars = defaultdict(set)
|
||||||
|
for group in final_result['groups']:
|
||||||
|
for field in unavailability_fields:
|
||||||
|
res_id = group[field][0] if group[field] else False
|
||||||
|
if res_id:
|
||||||
|
res_ids_for_unavailabilities[field].add(res_id)
|
||||||
|
for field in progress_bar_fields:
|
||||||
|
res_id = group[field][0] if group[field] else False
|
||||||
|
if res_id:
|
||||||
|
res_ids_for_progress_bars[field].add(res_id)
|
||||||
|
# Reorder __record_ids
|
||||||
|
group['__record_ids'] = list(ordered_set_ids & OrderedSet(group['__record_ids']))
|
||||||
|
# We don't need these in the gantt view
|
||||||
|
del group['__domain']
|
||||||
|
del group[f'{groupby[0]}_count' if lazy else '__count']
|
||||||
|
group.pop('__fold', None)
|
||||||
|
|
||||||
|
if unavailability_fields or progress_bar_fields:
|
||||||
|
start, stop = fields.Datetime.from_string(start_date), fields.Datetime.from_string(stop_date)
|
||||||
|
|
||||||
|
unavailabilities = {}
|
||||||
|
for field in unavailability_fields:
|
||||||
|
unavailabilities[field] = self._gantt_unavailability(field, list(res_ids_for_unavailabilities[field]), start, stop, scale)
|
||||||
|
final_result['unavailabilities'] = unavailabilities
|
||||||
|
|
||||||
|
progress_bars = {}
|
||||||
|
for field in progress_bar_fields:
|
||||||
|
progress_bars[field] = self._gantt_progress_bar(field, list(res_ids_for_progress_bars[field]), start, stop)
|
||||||
|
final_result['progress_bars'] = progress_bars
|
||||||
|
|
||||||
|
return final_result
|
||||||
|
|
||||||
|
@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: dict = {
|
||||||
|
type: notification type,
|
||||||
|
message: notification message,
|
||||||
|
old_vals_per_pill_id: dict = {
|
||||||
|
pill_id: {
|
||||||
|
start_date_field_name: planned_date_begin before rescheduling
|
||||||
|
stop_date_field_name: date_deadline before rescheduling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
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_count(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_gantt_reschedule_is_relation_candidate(
|
||||||
|
master_record, slave_record, start_date_field_name, stop_date_field_name):
|
||||||
|
return {
|
||||||
|
'type': 'warning',
|
||||||
|
'message': _('You cannot reschedule %(main_record)s towards %(other_record)s.',
|
||||||
|
main_record=master_record.name, other_record=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
|
||||||
|
|
||||||
|
if not trigger_record._web_gantt_reschedule_is_record_candidate(start_date_field_name, stop_date_field_name):
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'display_notification',
|
||||||
|
'params': {
|
||||||
|
'type': 'warning',
|
||||||
|
'message': _(
|
||||||
|
"You cannot move %(record)s towards %(related_record)s.",
|
||||||
|
record=trigger_record.name,
|
||||||
|
related_record=related_record.name,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = self.env.cr.savepoint()
|
||||||
|
log_messages, old_vals_per_pill_id = trigger_record._web_gantt_action_reschedule_candidates(dependency_field_name, dependency_inverted_field_name, start_date_field_name, stop_date_field_name, direction, related_record)
|
||||||
|
has_errors = bool(log_messages.get("errors"))
|
||||||
|
sp.close(rollback=has_errors)
|
||||||
|
notification_type = "success"
|
||||||
|
message = _("Reschedule done successfully.")
|
||||||
|
if has_errors or log_messages.get("warnings"):
|
||||||
|
message = self._web_gantt_get_reschedule_message(log_messages)
|
||||||
|
notification_type = "warning" if has_errors else "info"
|
||||||
|
return {
|
||||||
|
"type": notification_type,
|
||||||
|
"message": message,
|
||||||
|
"old_vals_per_pill_id": old_vals_per_pill_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
def action_rollback_scheduling(self, old_vals_per_pill_id):
|
||||||
|
for record in self:
|
||||||
|
vals = old_vals_per_pill_id.get(str(record.id), old_vals_per_pill_id.get(record.id))
|
||||||
|
if vals:
|
||||||
|
record.write(vals)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _gantt_progress_bar(self, field, res_ids, start, stop):
|
||||||
|
""" 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:
|
||||||
|
field = 'foo',
|
||||||
|
res_ids = [1, 2]
|
||||||
|
start_date = 01/01/2000, end_date = 01/07/2000,
|
||||||
|
self = base()
|
||||||
|
|
||||||
|
Result:
|
||||||
|
{
|
||||||
|
1: {'value': 50, 'max_value': 100},
|
||||||
|
2: {'value': 25, 'max_value': 200},
|
||||||
|
}
|
||||||
|
|
||||||
|
:param string field: field on which there are progressbars
|
||||||
|
:param list res_ids: res_ids of related records for which we need to compute progress bar
|
||||||
|
:param string start_datetime: start date in utc
|
||||||
|
:param string end_datetime: end date in utc
|
||||||
|
:returns: dict of value and max_value per record
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _gantt_unavailability(self, field, res_ids, start, stop, scale):
|
||||||
|
""" Get unavailabilities data for a given set of resources.
|
||||||
|
|
||||||
|
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 = 01/01/2000 in datetime utc, stop = 01/07/2000 in datetime utc, scale = 'week',
|
||||||
|
field = "empployee_id", res_ids = [3, 9]
|
||||||
|
|
||||||
|
* The expected return value of this function is a dict of the form
|
||||||
|
{
|
||||||
|
value: [{
|
||||||
|
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>
|
||||||
|
}, ...]
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
For example Marcel (3) is unavailable January 2 afternoon and
|
||||||
|
January 4 the whole day, the dict should look like this
|
||||||
|
{
|
||||||
|
3: [{
|
||||||
|
'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'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
Note that John (9) has no unavailabilies and thus 9 is not in
|
||||||
|
returned dict
|
||||||
|
|
||||||
|
:param string field: name of a many2X field
|
||||||
|
:param list res_ids: list of values for field for which we want unavailabilities (a value is either False or an id)
|
||||||
|
:param datetime start: start datetime
|
||||||
|
:param datetime stop: stop datetime
|
||||||
|
:param string scale: among "day", "week", "month" and "year"
|
||||||
|
:returns: dict of unavailabilities
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def _web_gantt_get_candidates(self,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
related_record, move_forward_without_conflicts,
|
||||||
|
):
|
||||||
|
result = {
|
||||||
|
'warnings': [],
|
||||||
|
'errors': [],
|
||||||
|
}
|
||||||
|
# first get the children of self
|
||||||
|
self_children_ids = []
|
||||||
|
pills_to_plan_before = []
|
||||||
|
pills_to_plan_after = []
|
||||||
|
|
||||||
|
if move_forward_without_conflicts:
|
||||||
|
candidates_to_exclude = {related_record.id}
|
||||||
|
else:
|
||||||
|
candidates_to_exclude = {self.id} | set(related_record[dependency_inverted_field_name].ids)
|
||||||
|
|
||||||
|
if self._web_gantt_check_cycle_existance_and_get_rescheduling_candidates(
|
||||||
|
self_children_ids, dependency_inverted_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
candidates_to_exclude,
|
||||||
|
):
|
||||||
|
result['errors'].append(self._WEB_GANTT_LOOP_ERROR)
|
||||||
|
return (result, pills_to_plan_before, pills_to_plan_after, [])
|
||||||
|
|
||||||
|
# second, get the ancestors of related_record
|
||||||
|
related_record_ancestors_ids = []
|
||||||
|
|
||||||
|
if move_forward_without_conflicts:
|
||||||
|
candidates_to_exclude = {related_record.id} | set(self[dependency_field_name].ids)
|
||||||
|
else:
|
||||||
|
candidates_to_exclude = {self.id}
|
||||||
|
|
||||||
|
if related_record._web_gantt_check_cycle_existance_and_get_rescheduling_candidates(
|
||||||
|
related_record_ancestors_ids, dependency_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
candidates_to_exclude,
|
||||||
|
):
|
||||||
|
result['errors'].append(self._WEB_GANTT_LOOP_ERROR)
|
||||||
|
return (result, pills_to_plan_before, pills_to_plan_after, [])
|
||||||
|
|
||||||
|
# third, get the intersection between self children and related_record ancestors
|
||||||
|
if move_forward_without_conflicts:
|
||||||
|
all_pills_ids, pills_to_check_from_ids = self_children_ids, set(related_record_ancestors_ids)
|
||||||
|
else:
|
||||||
|
related_record_ancestors_ids.reverse()
|
||||||
|
all_pills_ids, pills_to_check_from_ids = related_record_ancestors_ids, self_children_ids
|
||||||
|
|
||||||
|
for pill_id in all_pills_ids:
|
||||||
|
if pill_id in pills_to_check_from_ids:
|
||||||
|
(pills_to_plan_before if move_forward_without_conflicts else pills_to_plan_after).append(pill_id)
|
||||||
|
else:
|
||||||
|
(pills_to_plan_after if move_forward_without_conflicts else pills_to_plan_before).append(pill_id)
|
||||||
|
|
||||||
|
return (result, pills_to_plan_before, pills_to_plan_after, all_pills_ids)
|
||||||
|
|
||||||
|
def _web_gantt_get_reschedule_message_per_key(self, key, params=None):
|
||||||
|
if key == self._WEB_GANTT_LOOP_ERROR:
|
||||||
|
return _("The dependencies are not valid, there is a cycle.")
|
||||||
|
elif key == self._WEB_GANTT_NO_POSSIBLE_ACTION_ERROR:
|
||||||
|
return _("There are no valid candidates to re-plan")
|
||||||
|
elif key == "past_error":
|
||||||
|
if params: # params is the record that is in the past
|
||||||
|
return _("%s cannot be scheduled in the past", params.display_name)
|
||||||
|
else:
|
||||||
|
return _("Impossible to schedule in the past.")
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def _web_gantt_get_reschedule_message(self, log_messages):
|
||||||
|
def get_messages(logs):
|
||||||
|
messages = []
|
||||||
|
for key in logs:
|
||||||
|
message = self._web_gantt_get_reschedule_message_per_key(key, log_messages.get(key))
|
||||||
|
if message:
|
||||||
|
messages.append(message)
|
||||||
|
return messages
|
||||||
|
|
||||||
|
messages = []
|
||||||
|
errors = log_messages.get("errors")
|
||||||
|
if errors:
|
||||||
|
messages = get_messages(log_messages.get("errors"))
|
||||||
|
else:
|
||||||
|
messages = get_messages(log_messages.get("warnings", []))
|
||||||
|
return "\n".join(messages)
|
||||||
|
|
||||||
|
def _web_gantt_action_reschedule_candidates(
|
||||||
|
self,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
direction, related_record,
|
||||||
|
):
|
||||||
|
""" Prepare the candidates according to the provided parameters and move them.
|
||||||
|
|
||||||
|
: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 related_record: The record that self will be moving to
|
||||||
|
:return: tuple(valid, message) (valid = True if Successful, message = None or contains the notification text if
|
||||||
|
text if valid = True or the error text if valid = False.
|
||||||
|
"""
|
||||||
|
search_forward = direction == self._WEB_GANTT_RESCHEDULE_FORWARD
|
||||||
|
# moving forward without conflicts
|
||||||
|
if search_forward and self[stop_date_field_name] <= related_record[start_date_field_name] and related_record in self[dependency_inverted_field_name]:
|
||||||
|
log_messages, pills_to_plan_before_related_record, pills_to_plan_after_related_record, all_candidates_ids = self._web_gantt_get_candidates(
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
related_record, True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if log_messages.get("errors") or not pills_to_plan_before_related_record:
|
||||||
|
return log_messages, {}
|
||||||
|
|
||||||
|
# plan self_children backward from related_record
|
||||||
|
pills_to_plan_before_related_record.reverse()
|
||||||
|
log_messages, old_vals_per_pill_id = self._web_gantt_move_candidates(
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
False, pills_to_plan_before_related_record,
|
||||||
|
related_record[start_date_field_name],
|
||||||
|
all_candidates_ids, True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if log_messages.get("errors") or not pills_to_plan_after_related_record:
|
||||||
|
return log_messages, {} if log_messages.get("errors") else old_vals_per_pill_id
|
||||||
|
|
||||||
|
# plan related_record_ancestors forward from related_record
|
||||||
|
new_log_messages, second_old_vals_per_pill_id = self._web_gantt_move_candidates(
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
True, pills_to_plan_after_related_record,
|
||||||
|
self[stop_date_field_name]
|
||||||
|
)
|
||||||
|
|
||||||
|
log_messages.setdefault("errors", []).extend(new_log_messages.get("errors", []))
|
||||||
|
log_messages.setdefault("warnings", []).extend(new_log_messages.get("warnings", []))
|
||||||
|
|
||||||
|
return log_messages, old_vals_per_pill_id | second_old_vals_per_pill_id
|
||||||
|
# moving backward without conflicts
|
||||||
|
elif related_record[stop_date_field_name] <= self[start_date_field_name] and related_record in self[dependency_field_name]:
|
||||||
|
log_messages, pills_to_plan_before_related_record, pills_to_plan_after_related_record, all_candidates_ids = related_record._web_gantt_get_candidates(
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
self, False,
|
||||||
|
)
|
||||||
|
|
||||||
|
if log_messages.get("errors") or not pills_to_plan_after_related_record:
|
||||||
|
return log_messages, {}
|
||||||
|
|
||||||
|
# plan related_record_children_ids forward from related_record
|
||||||
|
log_messages, old_vals_per_pill_id = self._web_gantt_move_candidates(
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
True, pills_to_plan_after_related_record,
|
||||||
|
related_record[stop_date_field_name],
|
||||||
|
all_candidates_ids, True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if log_messages.get("errors") or not pills_to_plan_before_related_record:
|
||||||
|
return log_messages, {} if log_messages.get("errors") else old_vals_per_pill_id
|
||||||
|
|
||||||
|
# plan self_ancestors_ids backward from related_record
|
||||||
|
pills_to_plan_before_related_record.reverse()
|
||||||
|
new_log_messages, second_old_vals_per_pill_id = self._web_gantt_move_candidates(
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
False, pills_to_plan_before_related_record,
|
||||||
|
self[start_date_field_name]
|
||||||
|
)
|
||||||
|
|
||||||
|
log_messages.setdefault("errors", []).extend(new_log_messages.get("errors", []))
|
||||||
|
log_messages.setdefault("warnings", []).extend(new_log_messages.get("warnings", []))
|
||||||
|
|
||||||
|
return log_messages, old_vals_per_pill_id | second_old_vals_per_pill_id
|
||||||
|
# moving forward or backward with conflicts
|
||||||
|
else:
|
||||||
|
candidates_ids = []
|
||||||
|
dependency = dependency_inverted_field_name if search_forward else dependency_field_name
|
||||||
|
if self._web_gantt_check_cycle_existance_and_get_rescheduling_candidates(
|
||||||
|
candidates_ids, dependency,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
):
|
||||||
|
log_messages['errors'].append(self._WEB_GANTT_LOOP_ERROR)
|
||||||
|
return {
|
||||||
|
"errors": [self._WEB_GANTT_LOOP_ERROR],
|
||||||
|
}, {}
|
||||||
|
|
||||||
|
if not candidates_ids:
|
||||||
|
return {
|
||||||
|
"errors": [self._WEB_GANTT_NO_POSSIBLE_ACTION_ERROR],
|
||||||
|
}, {}
|
||||||
|
|
||||||
|
return self._web_gantt_move_candidates(
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
dependency_field_name, dependency_inverted_field_name,
|
||||||
|
search_forward, candidates_ids,
|
||||||
|
related_record[stop_date_field_name if search_forward else start_date_field_name]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _web_gantt_is_candidate_in_conflict(self, start_date_field_name, stop_date_field_name, dependency_field_name, dependency_inverted_field_name):
|
||||||
|
return (
|
||||||
|
any(r[start_date_field_name] and r[stop_date_field_name] and self[start_date_field_name] < r[stop_date_field_name] for r in self[dependency_field_name])
|
||||||
|
or any(r[start_date_field_name] and r[stop_date_field_name] and self[stop_date_field_name] > r[start_date_field_name] for r in self[dependency_inverted_field_name])
|
||||||
|
)
|
||||||
|
|
||||||
|
def _web_gantt_move_candidates(self, start_date_field_name, stop_date_field_name, dependency_field_name, dependency_inverted_field_name, search_forward, candidates_ids, date_candidate=None, all_candidates_ids=None, move_not_in_conflicts_candidates=False):
|
||||||
|
""" Move candidates according to the provided parameters.
|
||||||
|
|
||||||
|
: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 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.
|
||||||
|
search_forward, candidates_ids, date_candidate
|
||||||
|
:param search_forward: True if the direction = 'forward'
|
||||||
|
:param candidates_ids: The candidates to reschdule
|
||||||
|
:param date_candidate: The first possible date for the rescheduling
|
||||||
|
:param all_candidates_ids: moving without conflicts is done in 2 steps, candidates_ids contains the candidates
|
||||||
|
to schedule during the step, and all_candidates_ids contains the candidates to schedule in the 2 steps
|
||||||
|
:return: dict of list containing 2 keys, errors and warnings
|
||||||
|
"""
|
||||||
|
result = {
|
||||||
|
"errors": [],
|
||||||
|
"warnings": [],
|
||||||
|
}
|
||||||
|
old_vals_per_pill_id = {}
|
||||||
|
candidates = self.browse(candidates_ids)
|
||||||
|
|
||||||
|
for i, candidate in enumerate(candidates):
|
||||||
|
if not move_not_in_conflicts_candidates and not candidate._web_gantt_is_candidate_in_conflict(start_date_field_name, stop_date_field_name, dependency_field_name, dependency_inverted_field_name):
|
||||||
|
continue
|
||||||
|
|
||||||
|
start_date, end_date = candidate._web_gantt_reschedule_compute_dates(
|
||||||
|
date_candidate,
|
||||||
|
search_forward,
|
||||||
|
start_date_field_name, stop_date_field_name
|
||||||
|
)
|
||||||
|
start_date, end_date = start_date.astimezone(timezone.utc), end_date.astimezone(timezone.utc)
|
||||||
|
old_start_date, old_end_date = candidate[start_date_field_name], candidate[stop_date_field_name]
|
||||||
|
if not candidate._web_gantt_reschedule_write_new_dates(
|
||||||
|
start_date, end_date,
|
||||||
|
start_date_field_name, stop_date_field_name
|
||||||
|
):
|
||||||
|
result["errors"].append("past_error")
|
||||||
|
result["past_error"] = candidate
|
||||||
|
return result, {}
|
||||||
|
else:
|
||||||
|
old_vals_per_pill_id[candidate.id] = {
|
||||||
|
start_date_field_name: old_start_date,
|
||||||
|
stop_date_field_name: old_end_date,
|
||||||
|
}
|
||||||
|
|
||||||
|
if i + 1 < len(candidates):
|
||||||
|
next_candidate = candidates[i + 1]
|
||||||
|
if search_forward:
|
||||||
|
ancestors = next_candidate[dependency_field_name]
|
||||||
|
if ancestors:
|
||||||
|
date_candidate = max(ancestors.mapped(stop_date_field_name))
|
||||||
|
else:
|
||||||
|
date_candidate = end_date
|
||||||
|
else:
|
||||||
|
children = next_candidate[dependency_inverted_field_name]
|
||||||
|
if children:
|
||||||
|
date_candidate = min(children.mapped(start_date_field_name))
|
||||||
|
else:
|
||||||
|
date_candidate = start_date
|
||||||
|
|
||||||
|
return result, old_vals_per_pill_id
|
||||||
|
|
||||||
|
def _web_gantt_check_cycle_existance_and_get_rescheduling_candidates(self,
|
||||||
|
candidates_ids, dependency_field_name,
|
||||||
|
start_date_field_name, stop_date_field_name,
|
||||||
|
candidates_to_exclude=None, visited=None, ancestors=None,
|
||||||
|
):
|
||||||
|
""" Get the current records' related records rescheduling candidates (explained in details
|
||||||
|
in case 1 and case 2 in the below example)
|
||||||
|
|
||||||
|
This method Executes a dfs (depth first search algorithm) on the dependencies tree to:
|
||||||
|
1- detect cycles (detect if it's not a valid tree)
|
||||||
|
2- return the topological sorting of the candidates to reschedule
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
[4]->[6]
|
||||||
|
|
|
||||||
|
v
|
||||||
|
--->[0]->[1]->[2] [5]->[7]->[8]-----------------
|
||||||
|
| | | |
|
||||||
|
| v v |
|
||||||
|
| [3] [9]->[10] |
|
||||||
|
| |
|
||||||
|
---------------------<x>----------------------------
|
||||||
|
|
||||||
|
[0]->[1]: pill 0 should be done before 1
|
||||||
|
<: left arrow to move pill 8 backward pill 0
|
||||||
|
>: right arrow to move pill 0 forward pill 8
|
||||||
|
x: delete the dependence
|
||||||
|
|
||||||
|
Case 1:
|
||||||
|
If the right arrow is clicked, pill 0 should move forward. And as 1, 2, 3 are children of 0, they should be done after it,
|
||||||
|
they should also be moved forward.
|
||||||
|
This method will return False (no cycles) and a valid order of candidates = [0, 1, 2, 3] that should be scheduled
|
||||||
|
|
||||||
|
Case 2:
|
||||||
|
If the left arrow is clicked, pill 8 should move backward task 0, as 4, 6, 5, 7 are ancestors for 8, they should be done
|
||||||
|
before it, they should be moved backward also. 9 and 10 should not be impacted as they are not ancestors of 8.
|
||||||
|
This method will return False (no cycles) and a valid order of candidates = [5, 4, 6, 7, 8] that should be scheduled
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
modify the previous tree by adding an edge from pill 2 to pill 0 (no more a tree after this added edge)
|
||||||
|
-----------
|
||||||
|
| |
|
||||||
|
v |
|
||||||
|
[0]->[1]->[2]
|
||||||
|
|
||||||
|
This method will return True because there is the cycle illustrated above
|
||||||
|
|
||||||
|
:param candidates_ids: empty list that will contain the candidates at the end
|
||||||
|
: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 candidates_to_exclude: candidates to exclude
|
||||||
|
:param visited: set containing all the visited pills
|
||||||
|
:param ancestors: set containing the visited ancestors for the current pill
|
||||||
|
:return: bool, True if there is a cycle, else False.
|
||||||
|
candidates_id will also contain the pills to plan in a valid topological order
|
||||||
|
"""
|
||||||
|
if candidates_to_exclude is None:
|
||||||
|
candidates_to_exclude = []
|
||||||
|
if visited is None:
|
||||||
|
visited = set()
|
||||||
|
if ancestors is None:
|
||||||
|
ancestors = []
|
||||||
|
visited.add(self.id)
|
||||||
|
ancestors.append(self.id)
|
||||||
|
for child in self[dependency_field_name]:
|
||||||
|
if child.id in ancestors:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if child.id not in visited and child.id not in candidates_to_exclude and child._web_gantt_check_cycle_existance_and_get_rescheduling_candidates(candidates_ids, dependency_field_name, start_date_field_name, stop_date_field_name, candidates_to_exclude, visited, ancestors):
|
||||||
|
return True
|
||||||
|
|
||||||
|
ancestors.pop()
|
||||||
|
if self._web_gantt_reschedule_is_record_candidate(start_date_field_name, stop_date_field_name) and self.id not in candidates_to_exclude:
|
||||||
|
candidates_ids.insert(0, self.id)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _web_gantt_reschedule_compute_dates(
|
||||||
|
self, date_candidate, search_forward, start_date_field_name, stop_date_field_name
|
||||||
|
):
|
||||||
|
""" 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.
|
||||||
|
: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_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)
|
||||||
|
|
||||||
|
def _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_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
|
||||||
|
|
||||||
|
epsilon = 30 seconds was added because the first valid interval can be now and because of some seconds, it will become < now() at the comparaison moment
|
||||||
|
it's a matter of some seconds
|
||||||
|
"""
|
||||||
|
new_start_date = new_start_date.astimezone(timezone.utc).replace(tzinfo=None)
|
||||||
|
if new_start_date < datetime.now() + timedelta(seconds=-30):
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.write({
|
||||||
|
start_date_field_name: new_start_date,
|
||||||
|
stop_date_field_name: new_stop_date.astimezone(timezone.utc).replace(tzinfo=None)
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
|
@ -0,0 +1,332 @@
|
||||||
|
import { getLocalYearAndWeek } from "@web/core/l10n/dates";
|
||||||
|
import { _t } from "@web/core/l10n/translation";
|
||||||
|
import { evaluateExpr } from "@web/core/py_js/py";
|
||||||
|
import { exprToBoolean } from "@web/core/utils/strings";
|
||||||
|
import { visitXML } from "@web/core/utils/xml";
|
||||||
|
import { getActiveActions } from "@web/views/utils";
|
||||||
|
|
||||||
|
const DECORATIONS = [
|
||||||
|
"decoration-danger",
|
||||||
|
"decoration-info",
|
||||||
|
"decoration-secondary",
|
||||||
|
"decoration-success",
|
||||||
|
"decoration-warning",
|
||||||
|
];
|
||||||
|
const PARTS = { full: 1, half: 2, quarter: 4 };
|
||||||
|
const SCALES = {
|
||||||
|
day: {
|
||||||
|
// determines subcolumns
|
||||||
|
cellPrecisions: { full: 60, half: 30, quarter: 15 },
|
||||||
|
defaultPrecision: "full",
|
||||||
|
time: "minute",
|
||||||
|
unitDescription: _t("minutes"),
|
||||||
|
|
||||||
|
// determines columns
|
||||||
|
interval: "hour",
|
||||||
|
minimalColumnWidth: 40,
|
||||||
|
|
||||||
|
// determines column groups
|
||||||
|
unit: "day",
|
||||||
|
groupHeaderFormatter: (date) => date.toFormat("dd MMMM yyyy"),
|
||||||
|
|
||||||
|
defaultRange: { unit: "day", count: 3 },
|
||||||
|
},
|
||||||
|
week: {
|
||||||
|
cellPrecisions: { full: 24, half: 12 },
|
||||||
|
defaultPrecision: "half",
|
||||||
|
time: "hour",
|
||||||
|
unitDescription: _t("hours"),
|
||||||
|
|
||||||
|
interval: "day",
|
||||||
|
minimalColumnWidth: 192,
|
||||||
|
colHeaderFormatter: (date) => date.toFormat("dd"),
|
||||||
|
|
||||||
|
unit: "week",
|
||||||
|
groupHeaderFormatter: formatLocalWeekYear,
|
||||||
|
|
||||||
|
defaultRange: { unit: "week", count: 3 },
|
||||||
|
},
|
||||||
|
week_2: {
|
||||||
|
cellPrecisions: { full: 24, half: 12 },
|
||||||
|
defaultPrecision: "half",
|
||||||
|
time: "hour",
|
||||||
|
unitDescription: _t("hours"),
|
||||||
|
|
||||||
|
interval: "day",
|
||||||
|
minimalColumnWidth: 96,
|
||||||
|
colHeaderFormatter: (date) => date.toFormat("dd"),
|
||||||
|
|
||||||
|
unit: "week",
|
||||||
|
groupHeaderFormatter: formatLocalWeekYear,
|
||||||
|
|
||||||
|
defaultRange: { unit: "week", count: 6 },
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
cellPrecisions: { full: 24, half: 12 },
|
||||||
|
defaultPrecision: "half",
|
||||||
|
time: "hour",
|
||||||
|
unitDescription: _t("hours"),
|
||||||
|
|
||||||
|
interval: "day",
|
||||||
|
minimalColumnWidth: 50,
|
||||||
|
colHeaderFormatter: (date) => date.toFormat("dd"),
|
||||||
|
|
||||||
|
unit: "month",
|
||||||
|
groupHeaderFormatter: (date, env) => date.toFormat(env.isSmall ? "MMM yyyy" : "MMMM yyyy"),
|
||||||
|
|
||||||
|
defaultRange: { unit: "month", count: 3 },
|
||||||
|
},
|
||||||
|
month_3: {
|
||||||
|
cellPrecisions: { full: 24, half: 12 },
|
||||||
|
defaultPrecision: "half",
|
||||||
|
time: "hour",
|
||||||
|
unitDescription: _t("hours"),
|
||||||
|
|
||||||
|
interval: "day",
|
||||||
|
minimalColumnWidth: 18,
|
||||||
|
colHeaderFormatter: (date) => date.toFormat("dd"),
|
||||||
|
|
||||||
|
unit: "month",
|
||||||
|
groupHeaderFormatter: (date, env) => date.toFormat(env.isSmall ? "MMM yyyy" : "MMMM yyyy"),
|
||||||
|
|
||||||
|
defaultRange: { unit: "month", count: 6 },
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
cellPrecisions: { full: 1 },
|
||||||
|
defaultPrecision: "full",
|
||||||
|
time: "month",
|
||||||
|
unitDescription: _t("months"),
|
||||||
|
|
||||||
|
interval: "month",
|
||||||
|
minimalColumnWidth: 60,
|
||||||
|
colHeaderFormatter: (date, env) => date.toFormat(env.isSmall ? "MMM" : "MMMM"),
|
||||||
|
|
||||||
|
unit: "year",
|
||||||
|
groupHeaderFormatter: (date) => date.toFormat("yyyy"),
|
||||||
|
|
||||||
|
defaultRange: { unit: "year", count: 1 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date to a `'W'W kkkk` datetime string, in the user's locale settings.
|
||||||
|
*
|
||||||
|
* @param {Date|luxon.DateTime} date
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function formatLocalWeekYear(date) {
|
||||||
|
const { year, week } = getLocalYearAndWeek(date);
|
||||||
|
return `W${week} ${year}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPreferedScaleId(scaleId, scales) {
|
||||||
|
// we assume that scales is not empty
|
||||||
|
if (scaleId in scales) {
|
||||||
|
return scaleId;
|
||||||
|
}
|
||||||
|
const scaleIds = Object.keys(SCALES);
|
||||||
|
const index = scaleIds.findIndex((id) => id === scaleId);
|
||||||
|
for (let j = index - 1; j >= 0; j--) {
|
||||||
|
const id = scaleIds[j];
|
||||||
|
if (id in scales) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = index + 1; j < scaleIds.length; j++) {
|
||||||
|
const id = scaleIds[j];
|
||||||
|
if (id in scales) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RANGES = {
|
||||||
|
day: { scaleId: "day", description: _t("Today") },
|
||||||
|
week: { scaleId: "week", description: _t("This week") },
|
||||||
|
month: { scaleId: "month", description: _t("This month") },
|
||||||
|
quarter: { scaleId: "month_3", description: _t("This quarter") },
|
||||||
|
year: { scaleId: "year", description: _t("This year") },
|
||||||
|
};
|
||||||
|
|
||||||
|
export class GanttArchParser {
|
||||||
|
parse(arch) {
|
||||||
|
let infoFromRootNode;
|
||||||
|
const decorationFields = [];
|
||||||
|
const popoverArchParams = {
|
||||||
|
displayGenericButtons: true,
|
||||||
|
bodyTemplate: null,
|
||||||
|
footerTemplate: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
visitXML(arch, (node) => {
|
||||||
|
switch (node.tagName) {
|
||||||
|
case "gantt": {
|
||||||
|
infoFromRootNode = getInfoFromRootNode(node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "field": {
|
||||||
|
const fieldName = node.getAttribute("name");
|
||||||
|
decorationFields.push(fieldName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "templates": {
|
||||||
|
const body = node.querySelector("[t-name=gantt-popover]") || null;
|
||||||
|
if (body) {
|
||||||
|
popoverArchParams.bodyTemplate = body.cloneNode(true);
|
||||||
|
popoverArchParams.bodyTemplate.removeAttribute("t-name");
|
||||||
|
const footer = popoverArchParams.bodyTemplate.querySelector("footer");
|
||||||
|
if (footer) {
|
||||||
|
popoverArchParams.displayGenericButtons = false;
|
||||||
|
footer.remove();
|
||||||
|
const footerTemplate = new Document().createElement("t");
|
||||||
|
footerTemplate.append(...footer.children);
|
||||||
|
popoverArchParams.footerTemplate = footerTemplate;
|
||||||
|
const replace = footer.getAttribute("replace");
|
||||||
|
if (replace && !exprToBoolean(replace)) {
|
||||||
|
popoverArchParams.displayGenericButtons = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...infoFromRootNode,
|
||||||
|
decorationFields,
|
||||||
|
popoverArchParams,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInfoFromRootNode(rootNode) {
|
||||||
|
const attrs = {};
|
||||||
|
for (const { name, value } of rootNode.attributes) {
|
||||||
|
attrs[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { create: canCreate, delete: canDelete, edit: canEdit } = getActiveActions(rootNode);
|
||||||
|
const canCellCreate = exprToBoolean(attrs.cell_create, true) && canCreate;
|
||||||
|
const canPlan = exprToBoolean(attrs.plan, true) && canEdit;
|
||||||
|
|
||||||
|
let consolidationMaxField;
|
||||||
|
let consolidationMaxValue;
|
||||||
|
const consolidationMax = attrs.consolidation_max ? evaluateExpr(attrs.consolidation_max) : {};
|
||||||
|
if (Object.keys(consolidationMax).length > 0) {
|
||||||
|
consolidationMaxField = Object.keys(consolidationMax)[0];
|
||||||
|
consolidationMaxValue = consolidationMax[consolidationMaxField];
|
||||||
|
}
|
||||||
|
|
||||||
|
const consolidationParams = {
|
||||||
|
excludeField: attrs.consolidation_exclude,
|
||||||
|
field: attrs.consolidation,
|
||||||
|
maxField: consolidationMaxField,
|
||||||
|
maxValue: consolidationMaxValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dependencyField = attrs.dependency_field || null;
|
||||||
|
const dependencyEnabled = !!dependencyField;
|
||||||
|
const dependencyInvertedField = attrs.dependency_inverted_field || null;
|
||||||
|
|
||||||
|
const allowedScales = [];
|
||||||
|
if (attrs.scales) {
|
||||||
|
for (const key of attrs.scales.split(",")) {
|
||||||
|
if (SCALES[key]) {
|
||||||
|
allowedScales.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowedScales.length === 0) {
|
||||||
|
allowedScales.push(...Object.keys(SCALES));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cell precision
|
||||||
|
const cellPrecisions = {};
|
||||||
|
|
||||||
|
// precision = {'day': 'hour:half', 'week': 'day:half', 'month': 'day', 'year': 'month:quarter'}
|
||||||
|
const precisionAttrs = attrs.precision ? evaluateExpr(attrs.precision) : {};
|
||||||
|
for (const scaleId in SCALES) {
|
||||||
|
if (precisionAttrs[scaleId]) {
|
||||||
|
const precision = precisionAttrs[scaleId].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] &&
|
||||||
|
Object.keys(SCALES[scaleId].cellPrecisions).includes(precision[1])
|
||||||
|
) {
|
||||||
|
cellPrecisions[scaleId] = precision[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cellPrecisions[scaleId] ||= SCALES[scaleId].defaultPrecision;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scales = {};
|
||||||
|
for (const scaleId of allowedScales) {
|
||||||
|
const precision = cellPrecisions[scaleId];
|
||||||
|
const referenceScale = SCALES[scaleId];
|
||||||
|
scales[scaleId] = {
|
||||||
|
...referenceScale,
|
||||||
|
cellPart: PARTS[precision],
|
||||||
|
cellTime: referenceScale.cellPrecisions[precision],
|
||||||
|
id: scaleId,
|
||||||
|
unitDescription: referenceScale.unitDescription.toString(),
|
||||||
|
};
|
||||||
|
// protect SCALES content
|
||||||
|
delete scales[scaleId].cellPrecisions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ranges = {};
|
||||||
|
for (const rangeId in RANGES) {
|
||||||
|
const referenceRange = RANGES[rangeId];
|
||||||
|
ranges[rangeId] = {
|
||||||
|
...referenceRange,
|
||||||
|
id: rangeId,
|
||||||
|
scaleId: getPreferedScaleId(referenceRange.scaleId, scales),
|
||||||
|
description: referenceRange.description.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let pillDecorations = null;
|
||||||
|
for (const decoration of DECORATIONS) {
|
||||||
|
if (decoration in attrs) {
|
||||||
|
if (!pillDecorations) {
|
||||||
|
pillDecorations = {};
|
||||||
|
}
|
||||||
|
pillDecorations[decoration] = attrs[decoration];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
canCellCreate,
|
||||||
|
canCreate,
|
||||||
|
canDelete,
|
||||||
|
canEdit,
|
||||||
|
canPlan,
|
||||||
|
colorField: attrs.color,
|
||||||
|
computePillDisplayName: !!attrs.pill_label,
|
||||||
|
consolidationParams,
|
||||||
|
createAction: attrs.on_create || null,
|
||||||
|
dateStartField: attrs.date_start,
|
||||||
|
dateStopField: attrs.date_stop,
|
||||||
|
defaultGroupBy: attrs.default_group_by ? attrs.default_group_by.split(",") : [],
|
||||||
|
defaultRange: attrs.default_range,
|
||||||
|
defaultScale: attrs.default_scale || "month",
|
||||||
|
dependencyEnabled,
|
||||||
|
dependencyField,
|
||||||
|
dependencyInvertedField,
|
||||||
|
disableDrag: exprToBoolean(attrs.disable_drag_drop),
|
||||||
|
displayMode: attrs.display_mode || "dense",
|
||||||
|
displayTotalRow: exprToBoolean(attrs.total_row),
|
||||||
|
displayUnavailability: exprToBoolean(attrs.display_unavailability),
|
||||||
|
formViewId: attrs.form_view_id ? parseInt(attrs.form_view_id, 10) : false,
|
||||||
|
offset: attrs.offset,
|
||||||
|
pagerLimit: attrs.groups_limit ? parseInt(attrs.groups_limit, 10) : null,
|
||||||
|
pillDecorations,
|
||||||
|
progressBarFields: attrs.progress_bar ? attrs.progress_bar.split(",") : null,
|
||||||
|
progressField: attrs.progress || null,
|
||||||
|
ranges,
|
||||||
|
scales,
|
||||||
|
string: attrs.string || _t("Gantt View").toString(),
|
||||||
|
thumbnails: attrs.thumbnails ? evaluateExpr(attrs.thumbnails) : {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { ViewCompiler } from "@web/views/view_compiler";
|
||||||
|
|
||||||
|
export class GanttCompiler extends ViewCompiler {}
|
||||||
|
GanttCompiler.OWL_DIRECTIVE_WHITELIST = [
|
||||||
|
...ViewCompiler.OWL_DIRECTIVE_WHITELIST,
|
||||||
|
"t-name",
|
||||||
|
"t-esc",
|
||||||
|
"t-out",
|
||||||
|
"t-set",
|
||||||
|
"t-value",
|
||||||
|
"t-if",
|
||||||
|
"t-else",
|
||||||
|
"t-elif",
|
||||||
|
"t-foreach",
|
||||||
|
"t-as",
|
||||||
|
"t-key",
|
||||||
|
"t-att.*",
|
||||||
|
"t-call",
|
||||||
|
"t-translation",
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,294 @@
|
||||||
|
import { Component, onWillRender, useEffect, useRef } from "@odoo/owl";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {"error" | "warning"} ConnectorAlert
|
||||||
|
* @typedef {`__connector__${number | "new"}`} ConnectorId
|
||||||
|
* @typedef {import("./gantt_renderer").Point} Point
|
||||||
|
*
|
||||||
|
* @typedef ConnectorProps
|
||||||
|
* @property {ConnectorId} id
|
||||||
|
* @property {ConnectorAlert | null} alert
|
||||||
|
* @property {boolean} highlighted
|
||||||
|
* @property {boolean} displayButtons
|
||||||
|
* @property {Point | () => Point | null} sourcePoint
|
||||||
|
* @property {Point | () => Point | null} targetPoint
|
||||||
|
*
|
||||||
|
* @typedef {Object} PathInfo
|
||||||
|
* @property {Point} sourceControlPoint
|
||||||
|
* @property {Point} targetControlPoint
|
||||||
|
* @property {Point} removeButtonPosition
|
||||||
|
*
|
||||||
|
* @typedef Point
|
||||||
|
* @property {number} [x]
|
||||||
|
* @property {number} [y]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stroke's rgba css string corresponding to the provided parameters for both the stroke and its
|
||||||
|
* hovered state.
|
||||||
|
*
|
||||||
|
* @param {number} r [0, 255]
|
||||||
|
* @param {number} g [0, 255]
|
||||||
|
* @param {number} b [0, 255]
|
||||||
|
* @return {{ stroke: string, hoveredStroke: string }} the css colors.
|
||||||
|
*/
|
||||||
|
export function getStrokeAndHoveredStrokeColor(r, g, b) {
|
||||||
|
return {
|
||||||
|
color: `rgba(${r},${g},${b},0.5)`,
|
||||||
|
highlightedColor: `rgba(${r},${g},${b},1)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const COLORS = {
|
||||||
|
default: getStrokeAndHoveredStrokeColor(143, 143, 143),
|
||||||
|
error: getStrokeAndHoveredStrokeColor(211, 65, 59),
|
||||||
|
warning: getStrokeAndHoveredStrokeColor(236, 151, 31),
|
||||||
|
outline: getStrokeAndHoveredStrokeColor(255, 255, 255),
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @extends {Component<{ reactive: ConnectorProps }, any>} */
|
||||||
|
export class GanttConnector extends Component {
|
||||||
|
static props = {
|
||||||
|
reactive: {
|
||||||
|
type: Object,
|
||||||
|
shape: {
|
||||||
|
id: String,
|
||||||
|
alert: {
|
||||||
|
type: [{ value: "error" }, { value: "warning" }, { value: null }],
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
highlighted: { type: Boolean, optional: true },
|
||||||
|
displayButtons: { type: Boolean, optional: true },
|
||||||
|
sourcePoint: [
|
||||||
|
{ value: null },
|
||||||
|
Function,
|
||||||
|
{ type: Object, shape: { left: Number, top: Number } },
|
||||||
|
],
|
||||||
|
targetPoint: [
|
||||||
|
{ value: null },
|
||||||
|
Function,
|
||||||
|
{ type: Object, shape: { left: Number, top: Number } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onLeftButtonClick: { type: Function, optional: true },
|
||||||
|
onRemoveButtonClick: { type: Function, optional: true },
|
||||||
|
onRightButtonClick: { type: Function, optional: true },
|
||||||
|
};
|
||||||
|
static defaultProps = {
|
||||||
|
highlighted: false,
|
||||||
|
displayButtons: false,
|
||||||
|
};
|
||||||
|
static template = "web_gantt.GanttConnector";
|
||||||
|
|
||||||
|
rootRef = useRef("root");
|
||||||
|
style = {
|
||||||
|
hoverEaseWidth: 10,
|
||||||
|
slackness: 0.9,
|
||||||
|
stroke: { width: 2 },
|
||||||
|
outlineStroke: { width: 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
get alert() {
|
||||||
|
return this.props.reactive.alert;
|
||||||
|
}
|
||||||
|
|
||||||
|
get displayButtons() {
|
||||||
|
return this.props.reactive.displayButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
get highlighted() {
|
||||||
|
return this.props.reactive.highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id() {
|
||||||
|
return this.props.reactive.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isNew() {
|
||||||
|
return this.id.endsWith("new");
|
||||||
|
}
|
||||||
|
|
||||||
|
get sourcePoint() {
|
||||||
|
return this.props.reactive.sourcePoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
get targetPoint() {
|
||||||
|
return this.props.reactive.targetPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
onWillRender(this.onWillRender);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
(el, sourceLeft, sourceTop, targetLeft, targetTop) => {
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { sourceControlPoint, targetControlPoint, removeButtonPosition } =
|
||||||
|
this.getPathInfo(
|
||||||
|
{ left: sourceLeft, top: sourceTop },
|
||||||
|
{ left: targetLeft, top: targetTop },
|
||||||
|
this.style.slackness
|
||||||
|
);
|
||||||
|
|
||||||
|
const drawingCommands = [
|
||||||
|
`M`,
|
||||||
|
`${sourceLeft},${sourceTop}`,
|
||||||
|
`C`,
|
||||||
|
`${sourceControlPoint.left},${sourceControlPoint.top}`,
|
||||||
|
`${targetControlPoint.left},${targetControlPoint.top}`,
|
||||||
|
`${targetLeft},${targetTop}`,
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
const paths = el.querySelectorAll(
|
||||||
|
".o_connector_stroke, .o_connector_stroke_hover_ease"
|
||||||
|
);
|
||||||
|
for (const path of paths) {
|
||||||
|
path.setAttribute("d", drawingCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
const svgButtons = el.querySelector(".o_connector_stroke_buttons");
|
||||||
|
if (svgButtons) {
|
||||||
|
svgButtons.setAttribute("x", removeButtonPosition.left - 24);
|
||||||
|
svgButtons.setAttribute("y", removeButtonPosition.top - 8);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => this.getEffectDependencies()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the connector properties from the props.
|
||||||
|
*
|
||||||
|
* @param {ConnectorProps} props
|
||||||
|
*/
|
||||||
|
computeStyle({ alert, highlighted }) {
|
||||||
|
const key = highlighted ? "highlightedColor" : "color";
|
||||||
|
const strokeType = alert || "default";
|
||||||
|
this.style = {
|
||||||
|
hoverEaseWidth: 10,
|
||||||
|
slackness: 0.9,
|
||||||
|
stroke: {
|
||||||
|
color: COLORS[strokeType][key],
|
||||||
|
width: 2,
|
||||||
|
},
|
||||||
|
outlineStroke: {
|
||||||
|
color: COLORS.outline[key],
|
||||||
|
width: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getEffectDependencies() {
|
||||||
|
let sourcePoint = this.sourcePoint || { left: 0, top: 0 };
|
||||||
|
if (typeof sourcePoint === "function") {
|
||||||
|
sourcePoint = sourcePoint();
|
||||||
|
}
|
||||||
|
let targetPoint = this.targetPoint || { left: 0, top: 0 };
|
||||||
|
if (typeof targetPoint === "function") {
|
||||||
|
targetPoint = targetPoint();
|
||||||
|
}
|
||||||
|
const { x, y } = this.rootRef.el?.getBoundingClientRect() || { x: 0, y: 0 };
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.rootRef.el,
|
||||||
|
sourcePoint.left - x,
|
||||||
|
sourcePoint.top - y,
|
||||||
|
targetPoint.left - x,
|
||||||
|
targetPoint.top - y,
|
||||||
|
this.displayButtons,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the linear interpolation for a point to be found somewhere on the line startingPoint, endingPoint.
|
||||||
|
*
|
||||||
|
* @param {Point} startingPoint
|
||||||
|
* @param {Point} endingPoint
|
||||||
|
* @param {number} lambda
|
||||||
|
* @returns {Point}
|
||||||
|
*/
|
||||||
|
getLinearInterpolation(startingPoint, endingPoint, lambda = 0.5) {
|
||||||
|
return {
|
||||||
|
left: lambda * startingPoint.left + (1 - lambda) * endingPoint.left,
|
||||||
|
top: lambda * startingPoint.top + (1 - lambda) * endingPoint.top,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {Point} sourcePoint
|
||||||
|
* @param {Point} targetPoint
|
||||||
|
* @param {number} slackness [0, 1]
|
||||||
|
* @returns {PathInfo}
|
||||||
|
*/
|
||||||
|
getPathInfo(sourcePoint, targetPoint, slackness) {
|
||||||
|
// If the source is on the left of the target, we need to invert the control points.
|
||||||
|
const xDelta = targetPoint.left - sourcePoint.left;
|
||||||
|
const yDelta = targetPoint.top - sourcePoint.top;
|
||||||
|
const directionFactor = Math.sign(xDelta);
|
||||||
|
|
||||||
|
// 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 xInc = 100 + (Math.abs(xDelta) * slackness) / 10;
|
||||||
|
const yInc =
|
||||||
|
Math.abs(yDelta) < 16 && directionFactor === -1 ? 15 - 0.001 * xDelta * slackness : 0;
|
||||||
|
|
||||||
|
const b = {
|
||||||
|
left: sourcePoint.left + xInc,
|
||||||
|
top: sourcePoint.top + yInc,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prevent having the air pin effect when in creation and having target on the left of the source
|
||||||
|
const c = {
|
||||||
|
left: targetPoint.left + (this.isNew && directionFactor === -1 ? xInc : -xInc),
|
||||||
|
top: targetPoint.top + yInc,
|
||||||
|
};
|
||||||
|
|
||||||
|
const e = this.getLinearInterpolation(sourcePoint, b);
|
||||||
|
const f = this.getLinearInterpolation(b, c);
|
||||||
|
const g = this.getLinearInterpolation(c, targetPoint);
|
||||||
|
const h = this.getLinearInterpolation(e, f);
|
||||||
|
const i = this.getLinearInterpolation(f, g);
|
||||||
|
const j = this.getLinearInterpolation(h, i);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceControlPoint: b,
|
||||||
|
targetControlPoint: c,
|
||||||
|
removeButtonPosition: j,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Handlers
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
onLeftButtonClick() {
|
||||||
|
if (this.props.onLeftButtonClick) {
|
||||||
|
this.props.onLeftButtonClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveButtonClick() {
|
||||||
|
if (this.props.onRemoveButtonClick) {
|
||||||
|
this.props.onRemoveButtonClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightButtonClick() {
|
||||||
|
if (this.props.onRightButtonClick) {
|
||||||
|
this.props.onRightButtonClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onWillRender() {
|
||||||
|
const key = this.highlighted ? "highlightedColor" : "color";
|
||||||
|
this.style.stroke.color = COLORS[this.alert || "default"][key];
|
||||||
|
this.style.outlineStroke.color = COLORS.outline[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttConnector">
|
||||||
|
<t t-set="xmlAttributes" t-value="{ version: '1.1', xmlns: 'http://www.w3.org/2000/svg' }" />
|
||||||
|
<svg t-if="sourcePoint and targetPoint"
|
||||||
|
t-ref="root"
|
||||||
|
t-att-data-connector-id="id"
|
||||||
|
class="o_gantt_connector position-absolute start-0 top-0 w-100 h-100"
|
||||||
|
t-att-class="{ o_connector_highlighted: highlighted }"
|
||||||
|
pointer-events="none"
|
||||||
|
t-att="xmlAttributes"
|
||||||
|
>
|
||||||
|
<t t-set="strokeColor" t-value="style.stroke.color" />
|
||||||
|
<t t-set="outlineStrokeColor" t-value="style.outlineStroke.color" />
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<marker t-att-id="id"
|
||||||
|
markerHeight="6"
|
||||||
|
markerWidth="6"
|
||||||
|
markerUnits="strokeWidth"
|
||||||
|
orient="auto"
|
||||||
|
refX="9"
|
||||||
|
refY="6"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
>
|
||||||
|
<t t-call="web_gantt.ConnectorStrokeHead">
|
||||||
|
<t t-set="color" t-value="strokeColor" />
|
||||||
|
<t t-set="width" t-value="style.stroke.width" />
|
||||||
|
</t>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<t t-call="web_gantt.ConnectorStroke">
|
||||||
|
<t t-set="class" t-value="'o_connector_stroke_hover_ease'" />
|
||||||
|
<t t-set="color" t-value="transparent" />
|
||||||
|
<t t-set="width" t-value="style.stroke.width + style.hoverEaseWidth + style.outlineStroke.width" />
|
||||||
|
</t>
|
||||||
|
<t t-if="style.outlineStroke.width gt 0">
|
||||||
|
<t t-call="web_gantt.ConnectorStroke">
|
||||||
|
<t t-set="class" t-value="'o_connector_stroke_outline'" />
|
||||||
|
<t t-set="color" t-value="outlineStrokeColor" />
|
||||||
|
<t t-set="width" t-value="style.stroke.width + style.outlineStroke.width" />
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<t t-call="web_gantt.ConnectorStroke">
|
||||||
|
<t t-set="class" t-value="'o_connector_stroke'" />
|
||||||
|
<t t-set="color" t-value="strokeColor" />
|
||||||
|
<t t-set="markerEnd" t-value="id" />
|
||||||
|
<t t-set="width" t-value="style.stroke.width" />
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-if="displayButtons">
|
||||||
|
<svg class="o_connector_stroke_buttons"
|
||||||
|
width="48"
|
||||||
|
height="16"
|
||||||
|
pointer-events="all"
|
||||||
|
viewBox="0 0 1536 512"
|
||||||
|
t-att="xmlAttributes"
|
||||||
|
>
|
||||||
|
<rect fill="transparent" x="0" y="0" width="1536" height="512" />
|
||||||
|
<g class="o_connector_stroke_button o_connector_stroke_reschedule_button"
|
||||||
|
t-on-click.stop="onLeftButtonClick"
|
||||||
|
>
|
||||||
|
<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 class="o_connector_stroke_button o_connector_stroke_remove_button"
|
||||||
|
t-on-click.stop="onRemoveButtonClick"
|
||||||
|
>
|
||||||
|
<rect fill="white" x="532" y="20" width="472" height="472" 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 class="o_connector_stroke_button o_connector_stroke_reschedule_button"
|
||||||
|
t-on-click.stop="onRightButtonClick"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</t>
|
||||||
|
</svg>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.ConnectorStroke">
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
t-att-stroke="color"
|
||||||
|
t-att-stroke-width="width"
|
||||||
|
t-att-class="class"
|
||||||
|
t-att-marker-end="markerEnd ? `url(#${markerEnd})` : false"
|
||||||
|
t-att-pointer-events="isNew ? 'none' : 'stroke'"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.ConnectorStrokeHead">
|
||||||
|
<path
|
||||||
|
d="M2,2 L10,6 L2,10 L6,6 L2,2"
|
||||||
|
class="o_connector_stroke_head"
|
||||||
|
t-att-fill="color"
|
||||||
|
t-att-stroke="color"
|
||||||
|
t-att="xmlAttributes"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
import { _t } from "@web/core/l10n/translation";
|
||||||
|
import { Component, onWillUnmount, useEffect, useRef, useSubEnv } from "@odoo/owl";
|
||||||
|
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
|
||||||
|
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
|
||||||
|
import { Layout } from "@web/search/layout";
|
||||||
|
import { standardViewProps } from "@web/views/standard_view_props";
|
||||||
|
import { useModelWithSampleData } from "@web/model/model";
|
||||||
|
import { usePager } from "@web/search/pager_hook";
|
||||||
|
import { useService } from "@web/core/utils/hooks";
|
||||||
|
import { SearchBar } from "@web/search/search_bar/search_bar";
|
||||||
|
import { useSearchBarToggler } from "@web/search/search_bar/search_bar_toggler";
|
||||||
|
import { CogMenu } from "@web/search/cog_menu/cog_menu";
|
||||||
|
import { CallbackRecorder, useSetupAction } from "@web/search/action_hook";
|
||||||
|
|
||||||
|
export class GanttController extends Component {
|
||||||
|
static components = {
|
||||||
|
CogMenu,
|
||||||
|
Layout,
|
||||||
|
SearchBar,
|
||||||
|
};
|
||||||
|
static props = {
|
||||||
|
...standardViewProps,
|
||||||
|
Model: Function,
|
||||||
|
Renderer: Function,
|
||||||
|
buttonTemplate: String,
|
||||||
|
modelParams: Object,
|
||||||
|
scrollPosition: { type: Object, optional: true },
|
||||||
|
};
|
||||||
|
static template = "web_gantt.GanttController";
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.actionService = useService("action");
|
||||||
|
this.dialogService = useService("dialog");
|
||||||
|
this.orm = useService("orm");
|
||||||
|
|
||||||
|
useSubEnv({
|
||||||
|
getCurrentFocusDateCallBackRecorder: new CallbackRecorder(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const rootRef = useRef("root");
|
||||||
|
|
||||||
|
this.model = useModelWithSampleData(this.props.Model, this.props.modelParams);
|
||||||
|
useSetupAction({
|
||||||
|
rootRef,
|
||||||
|
getLocalState: () => {
|
||||||
|
return { metaData: this.model.metaData, displayParams: this.model.displayParams };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
onWillUnmount(() => this.closeDialog?.());
|
||||||
|
|
||||||
|
usePager(() => {
|
||||||
|
const { groupedBy, pagerLimit, pagerOffset } = this.model.metaData;
|
||||||
|
const { count } = this.model.data;
|
||||||
|
if (pagerLimit !== null && groupedBy.length) {
|
||||||
|
return {
|
||||||
|
offset: pagerOffset,
|
||||||
|
limit: pagerLimit,
|
||||||
|
total: count,
|
||||||
|
onUpdate: async ({ offset, limit }) => {
|
||||||
|
await this.model.updatePagerParams({ offset, limit });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
(showNoContentHelp) => {
|
||||||
|
if (showNoContentHelp) {
|
||||||
|
const realRows = [
|
||||||
|
...rootRef.el.querySelectorAll(
|
||||||
|
".o_gantt_row_header:not(.o_sample_data_disabled)"
|
||||||
|
),
|
||||||
|
];
|
||||||
|
// interactive rows created in extensions (fromServer undefined)
|
||||||
|
const headerContainerWidth =
|
||||||
|
rootRef.el.querySelector(".o_gantt_header_groups").clientHeight +
|
||||||
|
rootRef.el.querySelector(".o_gantt_header_columns").clientHeight;
|
||||||
|
|
||||||
|
const offset = realRows.reduce(
|
||||||
|
(current, el) => current + el.clientHeight,
|
||||||
|
headerContainerWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
const noContentHelperEl = rootRef.el.querySelector(".o_view_nocontent");
|
||||||
|
noContentHelperEl.style.top = `${offset}px`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => [this.showNoContentHelp]
|
||||||
|
);
|
||||||
|
this.searchBarToggler = useSearchBarToggler();
|
||||||
|
}
|
||||||
|
|
||||||
|
get className() {
|
||||||
|
if (this.env.isSmall) {
|
||||||
|
const classList = (this.props.className || "").split(" ");
|
||||||
|
classList.push("o_action_delegate_scroll");
|
||||||
|
return classList.join(" ");
|
||||||
|
}
|
||||||
|
return this.props.className;
|
||||||
|
}
|
||||||
|
|
||||||
|
get showNoContentHelp() {
|
||||||
|
return this.model.useSampleModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Record<string, any>} [context]
|
||||||
|
*/
|
||||||
|
create(context) {
|
||||||
|
const { createAction } = this.model.metaData;
|
||||||
|
if (createAction) {
|
||||||
|
this.actionService.doAction(createAction, {
|
||||||
|
additionalContext: context,
|
||||||
|
onClose: () => {
|
||||||
|
this.model.fetchData();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.openDialog({ context });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens dialog to add/edit/view a record
|
||||||
|
*
|
||||||
|
* @param {Record<string, any>} props FormViewDialog props
|
||||||
|
* @param {Record<string, any>} [options={}]
|
||||||
|
*/
|
||||||
|
openDialog(props, options = {}) {
|
||||||
|
const { canDelete, canEdit, resModel, formViewId: viewId } = this.model.metaData;
|
||||||
|
|
||||||
|
const title = props.title || (props.resId ? _t("Open") : _t("Create"));
|
||||||
|
|
||||||
|
let removeRecord;
|
||||||
|
if (canDelete && props.resId) {
|
||||||
|
removeRecord = () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.dialogService.add(ConfirmationDialog, {
|
||||||
|
body: _t("Are you sure to delete this record?"),
|
||||||
|
confirm: async () => {
|
||||||
|
await this.orm.unlink(resModel, [props.resId]);
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closeDialog = this.dialogService.add(
|
||||||
|
FormViewDialog,
|
||||||
|
{
|
||||||
|
title,
|
||||||
|
resModel,
|
||||||
|
viewId,
|
||||||
|
resId: props.resId,
|
||||||
|
size: props.size,
|
||||||
|
mode: canEdit ? "edit" : "readonly",
|
||||||
|
context: props.context,
|
||||||
|
removeRecord,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
onClose: () => {
|
||||||
|
this.closeDialog = null;
|
||||||
|
this.model.fetchData();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Handlers
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
onAddClicked() {
|
||||||
|
const { scale } = this.model.metaData;
|
||||||
|
const focusDate = this.getCurrentFocusDate();
|
||||||
|
const start = focusDate.startOf(scale.unit);
|
||||||
|
const stop = focusDate.endOf(scale.unit).plus({ millisecond: 1 });
|
||||||
|
const context = this.model.getDialogContext({ start, stop, withDefault: true });
|
||||||
|
this.create(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentFocusDate() {
|
||||||
|
const { callbacks } = this.env.getCurrentFocusDateCallBackRecorder;
|
||||||
|
if (callbacks.length) {
|
||||||
|
return callbacks[0]();
|
||||||
|
}
|
||||||
|
return this.model.metaData.focusDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttController">
|
||||||
|
<div t-att-class="className" t-ref="root">
|
||||||
|
<Layout className="model.useSampleModel ? 'o_view_sample_data' : ''" display="props.display">
|
||||||
|
<t t-set-slot="control-panel-create-button">
|
||||||
|
<button t-if="model.metaData.canCreate" class="o_gantt_button_add btn btn-primary" data-hotkey="r" t-on-click="onAddClicked">
|
||||||
|
New
|
||||||
|
</button>
|
||||||
|
</t>
|
||||||
|
<t t-set-slot="control-panel-additional-actions">
|
||||||
|
<CogMenu/>
|
||||||
|
</t>
|
||||||
|
<t t-set-slot="layout-buttons">
|
||||||
|
<t t-call="{{ props.buttonTemplate }}"/>
|
||||||
|
</t>
|
||||||
|
<t t-set-slot="layout-actions">
|
||||||
|
<SearchBar t-if="searchBarToggler.state.showSearchBar"/>
|
||||||
|
</t>
|
||||||
|
<t t-set-slot="control-panel-navigation-additional">
|
||||||
|
<t t-component="searchBarToggler.component" t-props="searchBarToggler.props"/>
|
||||||
|
</t>
|
||||||
|
<t t-set-slot="default" t-slot-scope="layout">
|
||||||
|
<t t-if="showNoContentHelp">
|
||||||
|
<t t-if="props.info.noContentHelp" t-call="web.ActionHelper">
|
||||||
|
<t t-set="noContentHelp" t-value="props.info.noContentHelp"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="" t-call="web.NoContentHelper"/>
|
||||||
|
</t>
|
||||||
|
<t t-component="props.Renderer"
|
||||||
|
class="model.useSampleModel ? 'o_sample_data_disabled' : ''"
|
||||||
|
model="model"
|
||||||
|
arch="props.arch"
|
||||||
|
create.bind="create"
|
||||||
|
openDialog.bind="openDialog"
|
||||||
|
scrollPosition="props.scrollPosition"
|
||||||
|
contentRef="layout.contentRef"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttView.Buttons">
|
||||||
|
<div class="d-flex flex-wrap o_gantt_buttons_container">
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,745 @@
|
||||||
|
import { onWillUnmount, status, useComponent, useEffect, useEnv } from "@odoo/owl";
|
||||||
|
import { getEndOfLocalWeek, getStartOfLocalWeek } from "@web/core/l10n/dates";
|
||||||
|
import { makePopover, usePopover } from "@web/core/popover/popover_hook";
|
||||||
|
import { makeDraggableHook } from "@web/core/utils/draggable_hook_builder_owl";
|
||||||
|
import { useService } from "@web/core/utils/hooks";
|
||||||
|
import { clamp } from "@web/core/utils/numbers";
|
||||||
|
import { pick } from "@web/core/utils/objects";
|
||||||
|
import { GanttPopoverInDialog } from "./gantt_popover_in_dialog";
|
||||||
|
|
||||||
|
/** @typedef {luxon.DateTime} DateTime */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} target
|
||||||
|
* @param {number[]} values
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function closest(target, values) {
|
||||||
|
return values.reduce(
|
||||||
|
(prev, val) => (Math.abs(val - target) < Math.abs(prev - target) ? val : prev),
|
||||||
|
Infinity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a time diff to a date keeping the same value even if the offset changed
|
||||||
|
* during the manipulation. This is typically needed with timezones using DayLight
|
||||||
|
* Saving offset changes.
|
||||||
|
*
|
||||||
|
* @example dateAddFixedOffset(luxon.DateTime.local(), { hour: 1 });
|
||||||
|
* @param {DateTime} date
|
||||||
|
* @param {Record<string, number>} plusParams
|
||||||
|
*/
|
||||||
|
export function dateAddFixedOffset(date, plusParams) {
|
||||||
|
const shouldApplyOffset = Object.keys(plusParams).some((key) =>
|
||||||
|
/^(hour|minute|second)s?$/i.test(key)
|
||||||
|
);
|
||||||
|
const result = date.plus(plusParams);
|
||||||
|
if (shouldApplyOffset) {
|
||||||
|
const initialOffset = date.offset;
|
||||||
|
const diff = initialOffset - result.offset;
|
||||||
|
if (diff) {
|
||||||
|
const adjusted = result.plus({ minute: diff });
|
||||||
|
return adjusted.offset === initialOffset ? result : adjusted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function diffColumn(col1, col2, unit) {
|
||||||
|
return col2.diff(col1, unit).values[`${unit}s`];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRangeFromDate(rangeId, date) {
|
||||||
|
const startDate = localStartOf(date, rangeId);
|
||||||
|
const stopDate = startDate.plus({ [rangeId]: 1 }).minus({ day: 1 });
|
||||||
|
return { focusDate: date, startDate, stopDate, rangeId };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function localStartOf(date, unit) {
|
||||||
|
return unit === "week" ? getStartOfLocalWeek(date) : date.startOf(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function localEndOf(date, unit) {
|
||||||
|
return unit === "week" ? getEndOfLocalWeek(date) : date.endOf(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} cellPart
|
||||||
|
* @param {(0 | 1)[]} subSlotUnavailabilities
|
||||||
|
* @param {boolean} isToday
|
||||||
|
* @returns {string | null}
|
||||||
|
*/
|
||||||
|
export function getCellColor(cellPart, subSlotUnavailabilities, isToday) {
|
||||||
|
const sum = subSlotUnavailabilities.reduce((acc, d) => acc + d);
|
||||||
|
if (!sum) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (cellPart) {
|
||||||
|
case sum: {
|
||||||
|
return `background-color:${getCellPartColor(sum, isToday)}`;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
const [c0, c1] = subSlotUnavailabilities.map((d) => getCellPartColor(d, isToday));
|
||||||
|
return `background:linear-gradient(90deg,${c0}49%,${c1}50%)`;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
const [c0, c1, c2, c3] = subSlotUnavailabilities.map((d) =>
|
||||||
|
getCellPartColor(d, isToday)
|
||||||
|
);
|
||||||
|
return `background:linear-gradient(90deg,${c0}24%,${c1}25%,${c1}49%,${c2}50%,${c2}74%,${c3}75%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {0 | 1} availability
|
||||||
|
* @param {boolean} isToday
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getCellPartColor(availability, isToday) {
|
||||||
|
if (availability) {
|
||||||
|
return "var(--Gantt__DayOff-background-color)";
|
||||||
|
} else if (isToday) {
|
||||||
|
return "var(--Gantt__DayOffToday-background-color)";
|
||||||
|
} else {
|
||||||
|
return "var(--Gantt__Day-background-color)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number | [number, string]} value
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function getColorIndex(value) {
|
||||||
|
if (typeof value === "number") {
|
||||||
|
return Math.round(value) % NB_GANTT_RECORD_COLORS;
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
return value[0] % NB_GANTT_RECORD_COLORS;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intervals are supposed to intersect (intersection duration >= 1 milliseconds)
|
||||||
|
*
|
||||||
|
* @param {[DateTime, DateTime]} interval
|
||||||
|
* @param {[DateTime, DateTime]} otherInterval
|
||||||
|
* @returns {[DateTime, DateTime]}
|
||||||
|
*/
|
||||||
|
export function getIntersection(interval, otherInterval) {
|
||||||
|
const [start, end] = interval;
|
||||||
|
const [otherStart, otherEnd] = otherInterval;
|
||||||
|
return [start >= otherStart ? start : otherStart, end <= otherEnd ? end : otherEnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes intersection of a closed interval with a union of closed intervals ordered and disjoint
|
||||||
|
* = a union of intersections
|
||||||
|
*
|
||||||
|
* @param {[DateTime, DateTime]} interval
|
||||||
|
* @param {[DateTime, DateTime]} intervals
|
||||||
|
* @returns {[DateTime, DateTime][]}
|
||||||
|
*/
|
||||||
|
export function getUnionOfIntersections(interval, intervals) {
|
||||||
|
const [start, end] = interval;
|
||||||
|
const intersecting = intervals.filter((otherInterval) => {
|
||||||
|
const [otheStart, otherEnd] = otherInterval;
|
||||||
|
return otherEnd > start && end > otheStart;
|
||||||
|
});
|
||||||
|
const len = intersecting.length;
|
||||||
|
if (len === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const union = [];
|
||||||
|
const first = getIntersection(interval, intersecting[0]);
|
||||||
|
union.push(first);
|
||||||
|
if (len >= 2) {
|
||||||
|
const last = getIntersection(interval, intersecting[len - 1]);
|
||||||
|
union.push(...intersecting.slice(1, len - 1), last);
|
||||||
|
}
|
||||||
|
return union;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {Ref<HTMLElement>} params.ref
|
||||||
|
* @param {string} params.selector
|
||||||
|
* @param {string} params.related
|
||||||
|
* @param {string} params.className
|
||||||
|
*/
|
||||||
|
export function useMultiHover({ ref, selector, related, className }) {
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} el
|
||||||
|
*/
|
||||||
|
const findSiblings = (el) =>
|
||||||
|
ref.el.querySelectorAll(
|
||||||
|
related
|
||||||
|
.map((attr) => `[${attr}='${el.getAttribute(attr).replace(/'/g, "\\'")}']`)
|
||||||
|
.join("")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PointerEvent} ev
|
||||||
|
*/
|
||||||
|
const onPointerEnter = (ev) => {
|
||||||
|
for (const sibling of findSiblings(ev.target)) {
|
||||||
|
sibling.classList.add(...classList);
|
||||||
|
classedEls.add(sibling);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PointerEvent} ev
|
||||||
|
*/
|
||||||
|
const onPointerLeave = (ev) => {
|
||||||
|
for (const sibling of findSiblings(ev.target)) {
|
||||||
|
sibling.classList.remove(...classList);
|
||||||
|
classedEls.delete(sibling);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const classList = className.split(/\s+/g);
|
||||||
|
const classedEls = new Set();
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
(...targets) => {
|
||||||
|
if (targets.length) {
|
||||||
|
for (const target of targets) {
|
||||||
|
target.addEventListener("pointerenter", onPointerEnter);
|
||||||
|
target.addEventListener("pointerleave", onPointerLeave);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
for (const el of classedEls) {
|
||||||
|
el.classList.remove(...classList);
|
||||||
|
}
|
||||||
|
classedEls.clear();
|
||||||
|
for (const target of targets) {
|
||||||
|
target.removeEventListener("pointerenter", onPointerEnter);
|
||||||
|
target.removeEventListener("pointerleave", onPointerLeave);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => [...ref.el.querySelectorAll(selector)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NB_GANTT_RECORD_COLORS = 12;
|
||||||
|
|
||||||
|
function getElementCenter(el) {
|
||||||
|
const { x, y, width, height } = el.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: x + width / 2,
|
||||||
|
y: y + height / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resizable hook handles
|
||||||
|
|
||||||
|
const HANDLE_CLASS_START = "o_handle_start";
|
||||||
|
const HANDLE_CLASS_END = "o_handle_end";
|
||||||
|
const handles = {
|
||||||
|
start: document.createElement("div"),
|
||||||
|
end: document.createElement("div"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draggable hooks
|
||||||
|
|
||||||
|
export const useGanttConnectorDraggable = makeDraggableHook({
|
||||||
|
name: "useGanttConnectorDraggable",
|
||||||
|
acceptedParams: {
|
||||||
|
parentWrapper: [String],
|
||||||
|
},
|
||||||
|
onComputeParams({ ctx, params }) {
|
||||||
|
ctx.parentWrapper = params.parentWrapper;
|
||||||
|
ctx.followCursor = false;
|
||||||
|
},
|
||||||
|
onDragStart: ({ ctx, addStyle }) => {
|
||||||
|
const { current } = ctx;
|
||||||
|
const parent = current.element.closest(ctx.parentWrapper);
|
||||||
|
if (!parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const otherParent of ctx.ref.el.querySelectorAll(ctx.parentWrapper)) {
|
||||||
|
if (otherParent !== parent) {
|
||||||
|
addStyle(otherParent, { pointerEvents: "auto" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { sourcePill: parent, ...current.connectorCenter };
|
||||||
|
},
|
||||||
|
onDrag: ({ ctx }) => {
|
||||||
|
ctx.current.connectorCenter = getElementCenter(ctx.current.element);
|
||||||
|
return pick(ctx.current, "connectorCenter");
|
||||||
|
},
|
||||||
|
onDragEnd: ({ ctx }) => pick(ctx.current, "element"),
|
||||||
|
onDrop: ({ ctx, target }) => {
|
||||||
|
const { current } = ctx;
|
||||||
|
const parent = current.element.closest(ctx.parentWrapper);
|
||||||
|
const targetParent = target.closest(ctx.parentWrapper);
|
||||||
|
if (!targetParent || targetParent === parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return { target: targetParent };
|
||||||
|
},
|
||||||
|
onWillStartDrag: ({ ctx }) => {
|
||||||
|
ctx.current.connectorCenter = getElementCenter(ctx.current.element);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function getCoordinate(style, name) {
|
||||||
|
return +style.getPropertyValue(name).slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumnStart(style) {
|
||||||
|
return getCoordinate(style, "grid-column-start");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumnEnd(style) {
|
||||||
|
return getCoordinate(style, "grid-column-end");
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGanttDraggable = makeDraggableHook({
|
||||||
|
name: "useGanttDraggable",
|
||||||
|
acceptedParams: {
|
||||||
|
cells: [String, Function],
|
||||||
|
cellDragClassName: [String, Function],
|
||||||
|
ghostClassName: [String, Function],
|
||||||
|
hoveredCell: [Object],
|
||||||
|
addStickyCoordinates: [Function],
|
||||||
|
},
|
||||||
|
onComputeParams({ ctx, params }) {
|
||||||
|
ctx.cellSelector = params.cells;
|
||||||
|
ctx.ghostClassName = params.ghostClassName;
|
||||||
|
ctx.cellDragClassName = params.cellDragClassName;
|
||||||
|
ctx.hoveredCell = params.hoveredCell;
|
||||||
|
ctx.addStickyCoordinates = params.addStickyCoordinates;
|
||||||
|
},
|
||||||
|
onDragStart({ ctx }) {
|
||||||
|
const { current, ghostClassName } = ctx;
|
||||||
|
current.element.before(current.placeHolder);
|
||||||
|
if (ghostClassName) {
|
||||||
|
current.placeHolder.classList.add(ghostClassName);
|
||||||
|
}
|
||||||
|
return { pill: current.element };
|
||||||
|
},
|
||||||
|
onDrag({ ctx, addStyle }) {
|
||||||
|
const { cellSelector, current, hoveredCell } = ctx;
|
||||||
|
let { el: cell, part } = hoveredCell;
|
||||||
|
|
||||||
|
const isDifferentCell = cell !== current.cell.el;
|
||||||
|
const isDifferentPart = part !== current.cell.part;
|
||||||
|
|
||||||
|
if (cell && !cell.matches(cellSelector)) {
|
||||||
|
cell = null; // Not a cell
|
||||||
|
}
|
||||||
|
|
||||||
|
current.cell.el = cell;
|
||||||
|
current.cell.part = part;
|
||||||
|
|
||||||
|
if (cell) {
|
||||||
|
// Recompute cell style if in a different cell
|
||||||
|
if (isDifferentCell) {
|
||||||
|
const style = getComputedStyle(cell);
|
||||||
|
current.cell.gridRow = style.getPropertyValue("grid-row");
|
||||||
|
current.cell.gridColumnStart = getColumnStart(style) + current.gridColumnOffset;
|
||||||
|
}
|
||||||
|
// Assign new grid coordinates if in different cell or different cell part
|
||||||
|
if (isDifferentCell || isDifferentPart) {
|
||||||
|
const { pillSpan } = current;
|
||||||
|
const { gridRow, gridColumnStart: start } = current.cell;
|
||||||
|
const gridColumnStart = clamp(start + part, 1, current.maxGridColumnStart);
|
||||||
|
const gridColumnEnd = gridColumnStart + pillSpan;
|
||||||
|
|
||||||
|
addStyle(current.cellGhost, {
|
||||||
|
gridRow,
|
||||||
|
gridColumn: `c${gridColumnStart} / c${gridColumnEnd}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [gridRowStart, gridRowEnd] = /r(\d+) \/ r(\d+)/g.exec(gridRow).slice(1);
|
||||||
|
ctx.addStickyCoordinates(
|
||||||
|
[gridRowStart, gridRowEnd],
|
||||||
|
[gridColumnStart, gridColumnEnd]
|
||||||
|
);
|
||||||
|
current.cell.col = gridColumnStart;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current.cell.col = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach or remove cell ghost
|
||||||
|
if (isDifferentCell) {
|
||||||
|
if (cell) {
|
||||||
|
cell.after(current.cellGhost);
|
||||||
|
} else {
|
||||||
|
current.cellGhost.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { pill: current.element };
|
||||||
|
},
|
||||||
|
onDragEnd({ ctx }) {
|
||||||
|
return { pill: ctx.current.element };
|
||||||
|
},
|
||||||
|
onDrop({ ctx }) {
|
||||||
|
const { cell, element, initialCol } = ctx.current;
|
||||||
|
if (cell.col !== null) {
|
||||||
|
return {
|
||||||
|
pill: element,
|
||||||
|
cell: cell.el,
|
||||||
|
diff: cell.col - initialCol,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onWillStartDrag({ ctx, addCleanup, addClass }) {
|
||||||
|
const { current } = ctx;
|
||||||
|
const { el: cell, part } = ctx.hoveredCell;
|
||||||
|
|
||||||
|
current.placeHolder = current.element.cloneNode(true);
|
||||||
|
current.cellGhost = document.createElement("div");
|
||||||
|
current.cellGhost.className = ctx.cellDragClassName;
|
||||||
|
current.cell = { el: null, index: null, part: 0 };
|
||||||
|
|
||||||
|
const gridStyle = getComputedStyle(cell.parentElement);
|
||||||
|
const pillStyle = getComputedStyle(current.element);
|
||||||
|
const cellStyle = getComputedStyle(cell);
|
||||||
|
|
||||||
|
const gridTemplateColumns = gridStyle.getPropertyValue("grid-template-columns");
|
||||||
|
const pGridColumnStart = getColumnStart(pillStyle);
|
||||||
|
const pGridColumnEnd = getColumnEnd(pillStyle);
|
||||||
|
const cGridColumnStart = getColumnStart(cellStyle) + part;
|
||||||
|
|
||||||
|
let highestGridCol;
|
||||||
|
for (const e of gridTemplateColumns.split(/\s+/).reverse()) {
|
||||||
|
const res = /\[c(\d+)\]/g.exec(e);
|
||||||
|
if (res) {
|
||||||
|
highestGridCol = +res[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pillSpan = pGridColumnEnd - pGridColumnStart;
|
||||||
|
|
||||||
|
current.initialCol = pGridColumnStart;
|
||||||
|
current.maxGridColumnStart = highestGridCol - pillSpan;
|
||||||
|
current.gridColumnOffset = pGridColumnStart - cGridColumnStart;
|
||||||
|
current.pillSpan = pillSpan;
|
||||||
|
|
||||||
|
addClass(ctx.ref.el, "pe-auto");
|
||||||
|
addCleanup(() => {
|
||||||
|
current.placeHolder.remove();
|
||||||
|
current.cellGhost.remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useGanttUndraggable = makeDraggableHook({
|
||||||
|
name: "useGanttUndraggable",
|
||||||
|
onDragStart({ ctx }) {
|
||||||
|
return { pill: ctx.current.element };
|
||||||
|
},
|
||||||
|
onDragEnd({ ctx }) {
|
||||||
|
return { pill: ctx.current.element };
|
||||||
|
},
|
||||||
|
onWillStartDrag({ ctx, addCleanup, addClass, addStyle, getRect }) {
|
||||||
|
const { x, y, width, height } = getRect(ctx.current.element);
|
||||||
|
ctx.current.container = document.createElement("div");
|
||||||
|
|
||||||
|
addClass(ctx.ref.el, "pe-auto");
|
||||||
|
addStyle(ctx.current.container, {
|
||||||
|
position: "fixed",
|
||||||
|
left: `${x}px`,
|
||||||
|
top: `${y}px`,
|
||||||
|
width: `${width}px`,
|
||||||
|
height: `${height}px`,
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.current.element.after(ctx.current.container);
|
||||||
|
addCleanup(() => ctx.current.container.remove());
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useGanttResizable = makeDraggableHook({
|
||||||
|
name: "useGanttResizable",
|
||||||
|
requiredParams: ["handles"],
|
||||||
|
acceptedParams: {
|
||||||
|
innerPills: [String, Function],
|
||||||
|
handles: [String, Function],
|
||||||
|
hoveredCell: [Object],
|
||||||
|
rtl: [Boolean, Function],
|
||||||
|
cells: [String, Function],
|
||||||
|
precision: [Number, Function],
|
||||||
|
showHandles: [Function],
|
||||||
|
},
|
||||||
|
onComputeParams({ ctx, params, addCleanup, addEffectCleanup, getRect }) {
|
||||||
|
const onElementPointerEnter = (ev) => {
|
||||||
|
if (ctx.dragging || ctx.willDrag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pill = ev.target;
|
||||||
|
const innerPill = pill.querySelector(params.innerPills);
|
||||||
|
|
||||||
|
const pillRect = getRect(innerPill);
|
||||||
|
|
||||||
|
for (const el of Object.values(handles)) {
|
||||||
|
el.style.height = `${pillRect.height}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const showHandles = params.showHandles ? params.showHandles(pill) : {};
|
||||||
|
if ("start" in showHandles && !showHandles.start) {
|
||||||
|
handles.start.remove();
|
||||||
|
} else {
|
||||||
|
innerPill.appendChild(handles.start);
|
||||||
|
}
|
||||||
|
if ("end" in showHandles && !showHandles.end) {
|
||||||
|
handles.end.remove();
|
||||||
|
} else {
|
||||||
|
innerPill.appendChild(handles.end);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onElementPointerLeave = () => {
|
||||||
|
const remove = () => Object.values(handles).forEach((h) => h.remove());
|
||||||
|
if (ctx.dragging || ctx.current.element) {
|
||||||
|
addCleanup(remove);
|
||||||
|
} else {
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.cellSelector = params.cells;
|
||||||
|
ctx.hoveredCell = params.hoveredCell;
|
||||||
|
ctx.precision = params.precision;
|
||||||
|
ctx.rtl = params.rtl;
|
||||||
|
|
||||||
|
for (const el of ctx.ref.el.querySelectorAll(params.elements)) {
|
||||||
|
el.addEventListener("pointerenter", onElementPointerEnter);
|
||||||
|
el.addEventListener("pointerleave", onElementPointerLeave);
|
||||||
|
addEffectCleanup(() => {
|
||||||
|
el.removeEventListener("pointerenter", onElementPointerEnter);
|
||||||
|
el.removeEventListener("pointerleave", onElementPointerLeave);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handles.start.className = `${params.handles} ${HANDLE_CLASS_START}`;
|
||||||
|
handles.start.style.cursor = `${params.rtl ? "e" : "w"}-resize`;
|
||||||
|
|
||||||
|
handles.end.className = `${params.handles} ${HANDLE_CLASS_END}`;
|
||||||
|
handles.end.style.cursor = `${params.rtl ? "w" : "e"}-resize`;
|
||||||
|
|
||||||
|
// Override "full" and "element" selectors: we want the draggable feature
|
||||||
|
// to apply to the handles
|
||||||
|
ctx.pillSelector = ctx.elementSelector;
|
||||||
|
ctx.fullSelector = ctx.elementSelector = `.${params.handles}`;
|
||||||
|
|
||||||
|
// Force the handles to stay in place
|
||||||
|
ctx.followCursor = false;
|
||||||
|
},
|
||||||
|
onDragStart({ ctx, addStyle }) {
|
||||||
|
addStyle(ctx.current.pill, { zIndex: 15 });
|
||||||
|
return { pill: ctx.current.pill };
|
||||||
|
},
|
||||||
|
onDrag({ ctx, addStyle, getRect }) {
|
||||||
|
const { cellSelector, current, hoveredCell, pointer, precision, rtl, ref } = ctx;
|
||||||
|
let { el: cell, part } = hoveredCell;
|
||||||
|
|
||||||
|
const point = [pointer.x, current.initialPosition.y];
|
||||||
|
if (!cell) {
|
||||||
|
let rect;
|
||||||
|
cell = document.elementsFromPoint(...point).find((el) => el.matches(cellSelector));
|
||||||
|
if (!cell) {
|
||||||
|
const cells = Array.from(ref.el.querySelectorAll(".o_gantt_cells .o_gantt_cell"));
|
||||||
|
if (pointer.x < current.initialPosition.x) {
|
||||||
|
cell = rtl ? cells.at(-1) : cells[0];
|
||||||
|
} else {
|
||||||
|
cell = rtl ? cells[0] : cells.at(-1);
|
||||||
|
}
|
||||||
|
rect = getRect(cell);
|
||||||
|
point[0] = rtl ? rect.right - 1 : rect.left + 1;
|
||||||
|
} else {
|
||||||
|
rect = getRect(cell);
|
||||||
|
}
|
||||||
|
const x = Math.floor(rect.x);
|
||||||
|
const width = Math.floor(rect.width);
|
||||||
|
part = Math.floor((point[0] - x) / (width / precision));
|
||||||
|
}
|
||||||
|
|
||||||
|
const cellStyle = getComputedStyle(cell);
|
||||||
|
const cGridColStart = getColumnStart(cellStyle);
|
||||||
|
|
||||||
|
const { x, width } = getRect(cell);
|
||||||
|
const coef = ((rtl ? -1 : 1) * width) / precision;
|
||||||
|
const startBorder = (rtl ? x + width : x) + part * coef;
|
||||||
|
const endBorder = startBorder + coef;
|
||||||
|
|
||||||
|
const theClosest = closest(point[0], [startBorder, endBorder]);
|
||||||
|
|
||||||
|
let diff =
|
||||||
|
cGridColStart +
|
||||||
|
part +
|
||||||
|
(theClosest === startBorder ? 0 : 1) -
|
||||||
|
(current.isStart ? current.firstCol : current.lastCol);
|
||||||
|
|
||||||
|
if (diff === current.lastDiff) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.isStart) {
|
||||||
|
diff = Math.min(diff, current.initialDiff - 1);
|
||||||
|
addStyle(current.pill, { "grid-column-start": `c${current.firstCol + diff}` });
|
||||||
|
} else {
|
||||||
|
diff = Math.max(diff, 1 - current.initialDiff);
|
||||||
|
addStyle(current.pill, { "grid-column-end": `c${current.lastCol + diff}` });
|
||||||
|
}
|
||||||
|
current.lastDiff = diff;
|
||||||
|
|
||||||
|
const isLeftHandle = rtl ? !current.isStart : current.isStart;
|
||||||
|
const grabbedHandle = isLeftHandle ? "left" : "right";
|
||||||
|
diff = current.isStart ? -diff : diff;
|
||||||
|
return { pill: current.pill, grabbedHandle, diff };
|
||||||
|
},
|
||||||
|
onDragEnd({ ctx }) {
|
||||||
|
const { current, pillSelector } = ctx;
|
||||||
|
const pill = current.element.closest(pillSelector);
|
||||||
|
return { pill };
|
||||||
|
},
|
||||||
|
onDrop({ ctx }) {
|
||||||
|
const { current } = ctx;
|
||||||
|
|
||||||
|
if (!current.lastDiff) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const direction = current.isStart ? "start" : "end";
|
||||||
|
return { pill: current.pill, diff: current.lastDiff, direction };
|
||||||
|
},
|
||||||
|
onWillStartDrag({ ctx, addClass }) {
|
||||||
|
const { current, pillSelector } = ctx;
|
||||||
|
|
||||||
|
const pill = ctx.current.element.closest(pillSelector);
|
||||||
|
current.pill = pill;
|
||||||
|
|
||||||
|
const pillStyle = getComputedStyle(pill);
|
||||||
|
current.firstCol = getColumnStart(pillStyle);
|
||||||
|
current.lastCol = getColumnEnd(pillStyle);
|
||||||
|
current.initialDiff = current.lastCol - current.firstCol;
|
||||||
|
|
||||||
|
ctx.cursor = getComputedStyle(current.element).cursor;
|
||||||
|
|
||||||
|
current.isStart = current.element.classList.contains(HANDLE_CLASS_START);
|
||||||
|
|
||||||
|
addClass(ctx.ref.el, "pe-auto");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function getCellsOnRow(refEl, rowId) {
|
||||||
|
return refEl.querySelectorAll(
|
||||||
|
`.o_gantt_cell:not(.o_gantt_group)[data-row-id='${CSS.escape(rowId)}']`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMinMax(a, b) {
|
||||||
|
return a <= b ? [a, b] : [b, a];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGanttSelectable = makeDraggableHook({
|
||||||
|
name: "useGanttSelectable",
|
||||||
|
acceptedParams: {
|
||||||
|
hoveredCell: [Object],
|
||||||
|
rtl: [Boolean, Function],
|
||||||
|
},
|
||||||
|
onComputeParams({ ctx, params }) {
|
||||||
|
ctx.followCursor = false;
|
||||||
|
ctx.hoveredCell = params.hoveredCell;
|
||||||
|
ctx.rtl = params.rtl;
|
||||||
|
},
|
||||||
|
onDrag({ ctx, addClass, getRect, removeClass }) {
|
||||||
|
const { current, hoveredCell, pointer, ref, rtl } = ctx;
|
||||||
|
let { el: cell } = hoveredCell;
|
||||||
|
if (!cell) {
|
||||||
|
const point = [pointer.x, current.initialPosition.y];
|
||||||
|
cell = document.elementsFromPoint(...point).find((el) => el.matches(".o_gantt_cell"));
|
||||||
|
if (!cell) {
|
||||||
|
const cells = Array.from(ref.el.querySelectorAll(".o_gantt_cells .o_gantt_cell"));
|
||||||
|
if (pointer.x < current.initialPosition.x) {
|
||||||
|
cell = rtl ? cells.at(-1) : cells[0];
|
||||||
|
} else {
|
||||||
|
cell = rtl ? cells[0] : cells.at(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const col = +cell.dataset.col;
|
||||||
|
const lastSelectedCol = current.lastSelectedCol;
|
||||||
|
current.lastSelectedCol = col;
|
||||||
|
if (lastSelectedCol === col) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [startCol, stopCol] = getMinMax(current.initialCol, col);
|
||||||
|
for (const cell of getCellsOnRow(ref.el, current.rowId)) {
|
||||||
|
const cellCol = +cell.dataset.col;
|
||||||
|
if (cellCol < startCol || cellCol > stopCol) {
|
||||||
|
removeClass(cell, "o_drag_hover");
|
||||||
|
} else {
|
||||||
|
addClass(cell, "o_drag_hover");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDrop({ ctx }) {
|
||||||
|
const { current } = ctx;
|
||||||
|
const { rowId, initialCol, lastSelectedCol } = current;
|
||||||
|
const [startCol, stopCol] = getMinMax(initialCol, lastSelectedCol);
|
||||||
|
return { rowId, startCol, stopCol };
|
||||||
|
},
|
||||||
|
onWillStartDrag({ ctx, addClass }) {
|
||||||
|
const { current, hoveredCell, ref } = ctx;
|
||||||
|
const { el: cell } = hoveredCell;
|
||||||
|
current.rowId = cell.dataset.rowId;
|
||||||
|
current.initialCol = +cell.dataset.col;
|
||||||
|
addClass(ref.el, "pe-auto");
|
||||||
|
addClass(cell, "pe-auto");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as usePopover, but replaces the popover by a dialog when display size is small.
|
||||||
|
*
|
||||||
|
* @param {typeof import("@odoo/owl").Component} component
|
||||||
|
* @param {import("@web/core/popover/popover_service").PopoverServiceAddOptions} [options]
|
||||||
|
* @returns {import("@web/core/popover/popover_hook").PopoverHookReturnType}
|
||||||
|
*/
|
||||||
|
export function useGanttResponsivePopover(dialogTitle, component, options = {}) {
|
||||||
|
const dialogService = useService("dialog");
|
||||||
|
const env = useEnv();
|
||||||
|
const owner = useComponent();
|
||||||
|
const popover = usePopover(component, options);
|
||||||
|
const onClose = () => {
|
||||||
|
if (status(owner) !== "destroyed") {
|
||||||
|
options.onClose?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const dialogAddFn = (_, comp, props, options) => dialogService.add(comp, props, options);
|
||||||
|
const popoverInDialog = makePopover(dialogAddFn, GanttPopoverInDialog, { onClose });
|
||||||
|
const ganttReponsivePopover = {
|
||||||
|
open: (target, props) => {
|
||||||
|
if (env.isSmall) {
|
||||||
|
popoverInDialog.open(target, {
|
||||||
|
component: component,
|
||||||
|
componentProps: props,
|
||||||
|
dialogTitle,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
popover.open(target, props);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: () => {
|
||||||
|
popover.close();
|
||||||
|
popoverInDialog.close();
|
||||||
|
},
|
||||||
|
get isOpen() {
|
||||||
|
return popover.isOpen || popoverInDialog.isOpen;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
onWillUnmount(ganttReponsivePopover.close);
|
||||||
|
return ganttReponsivePopover;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
|
||||||
|
function _mockGetGanttData(_, { model, kwargs }) {
|
||||||
|
const lazy = !kwargs.limit && !kwargs.offset && kwargs.groupby.length === 1;
|
||||||
|
const { groups, length } = this.mockWebReadGroup(model, {
|
||||||
|
...kwargs,
|
||||||
|
lazy,
|
||||||
|
fields: ["__record_ids:array_agg(id)"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const recordIds = [];
|
||||||
|
for (const group of groups) {
|
||||||
|
recordIds.push(...(group.__record_ids || []));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { records } = this.mockWebSearchReadUnity(model, [], {
|
||||||
|
domain: [["id", "in", recordIds]],
|
||||||
|
context: kwargs.context,
|
||||||
|
specification: kwargs.read_specification,
|
||||||
|
});
|
||||||
|
|
||||||
|
const unavailabilities = {};
|
||||||
|
for (const fieldName of kwargs.unavailability_fields || []) {
|
||||||
|
unavailabilities[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress_bars = {};
|
||||||
|
for (const fieldName of kwargs.progress_bar_fields || []) {
|
||||||
|
progress_bars[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { groups, length, records, unavailabilities, progress_bars };
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.category("mock_server").add("get_gantt_data", _mockGetGanttData);
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { Component, useRef } from "@odoo/owl";
|
||||||
|
import { ViewButton } from "@web/views/view_button/view_button";
|
||||||
|
import { useViewButtons } from "@web/views/view_button/view_button_hook";
|
||||||
|
import { useViewCompiler } from "@web/views/view_compiler";
|
||||||
|
import { GanttCompiler } from "./gantt_compiler";
|
||||||
|
|
||||||
|
export class GanttPopover extends Component {
|
||||||
|
static template = "web_gantt.GanttPopover";
|
||||||
|
static components = { ViewButton };
|
||||||
|
static props = [
|
||||||
|
"title",
|
||||||
|
"displayGenericButtons",
|
||||||
|
"bodyTemplate?",
|
||||||
|
"footerTemplate?",
|
||||||
|
"resModel",
|
||||||
|
"resId",
|
||||||
|
"context",
|
||||||
|
"close",
|
||||||
|
"reload",
|
||||||
|
"buttons",
|
||||||
|
];
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.rootRef = useRef("root");
|
||||||
|
|
||||||
|
this.templates = { body: "web_gantt.GanttPopover.default" };
|
||||||
|
const toCompile = {};
|
||||||
|
const { bodyTemplate, footerTemplate } = this.props;
|
||||||
|
if (bodyTemplate) {
|
||||||
|
toCompile.body = bodyTemplate;
|
||||||
|
if (footerTemplate) {
|
||||||
|
toCompile.footer = footerTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.assign(
|
||||||
|
this.templates,
|
||||||
|
useViewCompiler(GanttCompiler, toCompile, { recordExpr: "__record__" })
|
||||||
|
);
|
||||||
|
|
||||||
|
useViewButtons(this.rootRef, {
|
||||||
|
reload: async () => {
|
||||||
|
await this.props.reload();
|
||||||
|
this.props.close();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get renderingContext() {
|
||||||
|
return Object.assign({}, this.props.context, {
|
||||||
|
__comp__: this,
|
||||||
|
__record__: { resModel: this.props.resModel, resId: this.props.resId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onClick(button) {
|
||||||
|
await button.onClick();
|
||||||
|
this.props.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttPopover">
|
||||||
|
<div t-ref="root" style="max-width: 320px;"> <!-- the chosen value is rather arbitrary: the idea was to have enough space (but not too much) for some particular known cases-->
|
||||||
|
<div class="popover-header d-flex justify-content-between py-2 pe-2">
|
||||||
|
<h4 class="p-0 pt-1">
|
||||||
|
<t t-esc="props.title" />
|
||||||
|
</h4>
|
||||||
|
<span class="ms-4 mt-1 me-2 cursor-pointer" t-on-click.stop="props.close">
|
||||||
|
<i class="fa fa-close" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="popover-body">
|
||||||
|
<t t-call="{{ templates.body }}" t-call-context="renderingContext" />
|
||||||
|
</div>
|
||||||
|
<div t-if="(props.displayGenericButtons and props.buttons) or templates.footer" class="popover-footer border-top p-3 d-flex flex-wrap gap-1">
|
||||||
|
<t t-if="props.displayGenericButtons and props.buttons">
|
||||||
|
<t t-foreach="props.buttons" t-as="button" t-key="button_index">
|
||||||
|
<button t-att-class="button.class" t-on-click="() => this.onClick(button)" t-esc="button.text" />
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<t t-if="templates.footer">
|
||||||
|
<t t-call="{{ templates.footer }}" t-call-context="renderingContext" />
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttPopover.default">
|
||||||
|
<ul class="p-0 mb-0 list-unstyled">
|
||||||
|
<li class="pe-2">
|
||||||
|
<strong>Name</strong>: <span t-esc="name" />
|
||||||
|
</li>
|
||||||
|
<li class="pe-2">
|
||||||
|
<strong>Start</strong>: <span t-esc="start" />
|
||||||
|
</li>
|
||||||
|
<li class="pe-2">
|
||||||
|
<strong>Stop</strong>: <span t-esc="stop" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from "@odoo/owl";
|
||||||
|
import { Dialog } from "@web/core/dialog/dialog";
|
||||||
|
|
||||||
|
export class GanttPopoverInDialog extends Component {
|
||||||
|
static components = { Dialog };
|
||||||
|
static props = ["close", "component", "componentProps", "dialogTitle"];
|
||||||
|
static template = "web_gantt.GanttPopoverInDialog";
|
||||||
|
get componentProps() {
|
||||||
|
return { ...this.props.componentProps, close: this.props.close };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
<t t-name="web_gantt.GanttPopoverInDialog">
|
||||||
|
<Dialog title="props.dialogTitle" footer="false">
|
||||||
|
<t t-component="props.component" t-props="componentProps"/>
|
||||||
|
</Dialog>
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,255 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer">
|
||||||
|
<GanttRendererControls t-props="controlsProps" />
|
||||||
|
<div t-ref="grid"
|
||||||
|
class="o_gantt_renderer o_renderer bg-view"
|
||||||
|
t-att-class="{ o_has_row_headers: hasRowHeaders, 'pe-auto': isDragging }"
|
||||||
|
t-att-style="getGridStyle()"
|
||||||
|
t-on-pointermove="throttledComputeHoverParams"
|
||||||
|
t-on-pointerleave="onPointerLeave"
|
||||||
|
>
|
||||||
|
<t t-call="{{ constructor.headerTemplate }}"/>
|
||||||
|
<t t-if="hasRowHeaders">
|
||||||
|
<div class="o_gantt_row_headers o_gantt_row_sidebar o_gantt_grid_rows border-end position-sticky start-0 bg-view">
|
||||||
|
<t t-foreach="rowsToRender" t-as="row" t-key="row.id">
|
||||||
|
<t t-call="{{ constructor.rowHeaderTemplate }}" />
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
<div t-ref="cellContainer" class="o_gantt_cells o_gantt_grid_rows o_gantt_grid_columns position-relative">
|
||||||
|
<t t-foreach="rowsToRender" t-as="row" t-key="row.id">
|
||||||
|
<t t-call="{{ constructor.rowContentTemplate }}" />
|
||||||
|
</t>
|
||||||
|
<t t-foreach="pillsToRender" t-as="pill" t-key="pill.id">
|
||||||
|
<t t-set="row" t-value="getRowFromPill(pill)"/>
|
||||||
|
<t t-if="row.isGroup">
|
||||||
|
<t t-call="{{ constructor.groupPillTemplate }}" />
|
||||||
|
</t>
|
||||||
|
<t t-else="" >
|
||||||
|
<t t-call="{{ constructor.pillTemplate }}" />
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<t t-if="shouldRenderConnectors()">
|
||||||
|
<t t-foreach="connectorsToRender" t-as="connector" t-key="connector.id">
|
||||||
|
<GanttConnector
|
||||||
|
reactive="connector"
|
||||||
|
onRemoveButtonClick="() => this.onRemoveButtonClick(connector.id)"
|
||||||
|
onLeftButtonClick="() => this.onRescheduleButtonClick('backward', connector.id)"
|
||||||
|
onRightButtonClick="() => this.onRescheduleButtonClick('forward', connector.id)"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<GanttResizeBadge reactive="resizeBadgeReactive" />
|
||||||
|
</div>
|
||||||
|
<t t-if="totalRow">
|
||||||
|
<t t-call="{{ constructor.totalRowTemplate }}"/>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.Header">
|
||||||
|
<t t-if="hasRowHeaders">
|
||||||
|
<b
|
||||||
|
class="o_gantt_title d-flex align-items-center justify-content-center bg-100 position-sticky start-0 p-2 border-end"
|
||||||
|
t-esc="model.metaData.string"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
<div class="o_gantt_header_groups o_gantt_grid_columns bg-100 position-sticky">
|
||||||
|
<t t-foreach="columnsGroups" t-as="column" t-key="column.id">
|
||||||
|
<div class="o_gantt_header_title position-sticky d-flex align-items-center ps-2 overflow-hidden bg-100"
|
||||||
|
t-att-style="getGridPosition({column: column.grid.column})"
|
||||||
|
>
|
||||||
|
<t t-esc="model.metaData.scale.groupHeaderFormatter(column.start, env)"/>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
<div class="o_gantt_header_columns o_gantt_grid_columns bg-view position-sticky">
|
||||||
|
<t t-foreach="columns" t-as="column" t-key="column.id">
|
||||||
|
<div class="o_gantt_header_cell d-flex align-items-center justify-content-center py-2"
|
||||||
|
t-att-class="{ o_gantt_today: column.isToday, 'bg-100': !column.isToday }"
|
||||||
|
t-att-style="getGridPosition({column: column.grid.column})"
|
||||||
|
>
|
||||||
|
<t t-if="'colHeaderFormatter' in model.metaData.scale">
|
||||||
|
<t t-esc="model.metaData.scale.colHeaderFormatter(column.start, env)"/>
|
||||||
|
</t>
|
||||||
|
<small t-else="" class="text-center">
|
||||||
|
<t t-if="is24HourFormat">
|
||||||
|
<b t-esc="column.start.toFormat('H')"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<b t-esc="column.start.toFormat('h')"/>
|
||||||
|
<div class="d-xl-inline-block" t-esc="column.start.toFormat('a').toLowerCase()"/>
|
||||||
|
</t>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.ConnectorCreator">
|
||||||
|
<div
|
||||||
|
class="o_connector_creator_wrapper position-absolute w-100"
|
||||||
|
t-attf-class="o_connector_creator_wrapper_{{ alignment.vertical }} {{ '_color' in pill ? 'o_gantt_color_' + pill._color : '' }}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="o_connector_creator position-absolute"
|
||||||
|
t-attf-class="o_connector_creator_{{ alignment.vertical }} o_connector_creator_{{ alignment.horizontal }}"
|
||||||
|
>
|
||||||
|
<div class="o_connector_creator_bullet position-absolute rounded-circle" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.RowHeader">
|
||||||
|
<div
|
||||||
|
class="o_gantt_row_header o_gantt_row_sidebar position-sticky start-0 bg-view align-items-center"
|
||||||
|
t-att-class="{
|
||||||
|
o_sample_data_disabled: isDisabled(row),
|
||||||
|
o_gantt_row_sidebar_empty: !row.name,
|
||||||
|
o_gantt_group: row.isGroup,
|
||||||
|
o_gantt_hoverable: isHoverable(row),
|
||||||
|
o_mobile_progress_bar: row.progressBar and isTouchDevice,
|
||||||
|
o_group_open: !model.isClosed(row.id),
|
||||||
|
}"
|
||||||
|
t-att-style="getGridPosition({ row: row.grid.row })"
|
||||||
|
t-att-data-row-id="row.id"
|
||||||
|
t-on-click.synthetic="() => row.isGroup ? this.model.toggleRow(row.id) : this.focusFirstPill(row.id)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="o_gantt_row_title d-flex align-items-center h-100 w-100 pe-1"
|
||||||
|
t-att-class="{ 'fw-bold': row.isGroup }"
|
||||||
|
t-att-style="getRowTitleStyle(row)"
|
||||||
|
t-att-title="row.name or ''"
|
||||||
|
>
|
||||||
|
<i t-if="row.isGroup" t-attf-class="o_group_caret fa fa-fw me-1 fa-caret-{{ model.isClosed(row.id) ? 'right' : 'down' }}" />
|
||||||
|
<span t-if="row.thumbnailUrl and row.resId"
|
||||||
|
class="o_gantt_row_thumbnail_wrapper"
|
||||||
|
t-att-class="{ 'me-1' : row.isGroup }"
|
||||||
|
>
|
||||||
|
<img t-att-src="row.thumbnailUrl" class="o_gantt_row_thumbnail o_avatar rounded"/>
|
||||||
|
</span>
|
||||||
|
<span class="text-truncate w-0 flex-grow-1">
|
||||||
|
<t t-esc="row.name" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<t t-if="row.progressBar">
|
||||||
|
<GanttRowProgressBar t-props="getProgressBarProps(row)" />
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.RowContent">
|
||||||
|
<!-- Cells -->
|
||||||
|
<t t-foreach="columns" t-as="column" t-key="column.id">
|
||||||
|
<t t-set="col" t-value="column.grid.column[0]" />
|
||||||
|
<div
|
||||||
|
class="o_gantt_cell"
|
||||||
|
t-att-class="ganttCellAttClass(row, column)"
|
||||||
|
t-attf-style="{{ getGridPosition({ column: column.grid.column, row: row.grid.row }) }};{{ row.cellColors[column.id] || '' }}"
|
||||||
|
t-att-data-row-id="row.id"
|
||||||
|
t-att-data-col="col"
|
||||||
|
t-on-click.synthetic="(ev) => row.isGroup ? this.model.toggleRow(row.id) : this.onCellClicked(row.id, col)"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.Pill">
|
||||||
|
<t t-set="renderConnectors" t-value="shouldRenderRecordConnectors(pill.record)" />
|
||||||
|
<div class="o_gantt_pill_wrapper"
|
||||||
|
t-att-class="{
|
||||||
|
o_sample_data_disabled: isDisabled(row),
|
||||||
|
o_draggable: !pill.disableDrag,
|
||||||
|
o_undraggable: pill.disableDrag,
|
||||||
|
o_resizable: !pill.disableStartResize or !pill.disableStopResize,
|
||||||
|
'position-relative': renderConnectors
|
||||||
|
}"
|
||||||
|
t-att-style="getGridPosition(pill.grid)"
|
||||||
|
t-att-data-pill-id="pill.id"
|
||||||
|
>
|
||||||
|
<t t-if="renderConnectors" t-call="{{ constructor.connectorCreatorTemplate }}">
|
||||||
|
<t t-set="alignment" t-value="getConnectorCreatorAlignment('top')" />
|
||||||
|
</t>
|
||||||
|
<div class="o_gantt_pill position-relative h-100 d-flex align-items-center"
|
||||||
|
t-att-class="pill.className"
|
||||||
|
t-on-click.synthetic="(ev) => this.onPillClicked(ev, pill)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
t-if="pill._progress"
|
||||||
|
class="position-absolute h-100 o_gantt_progress"
|
||||||
|
t-attf-style="width:{{ pill._progress }}%;"
|
||||||
|
/>
|
||||||
|
<span class="o_gantt_pill_title text-truncate mx-1" t-esc="pill.displayName" />
|
||||||
|
<div t-if="pill.disableDrag" class="o_gantt_lock fa fa-lock ms-auto me-2" />
|
||||||
|
</div>
|
||||||
|
<t t-if="renderConnectors" t-call="{{ constructor.connectorCreatorTemplate }}">
|
||||||
|
<t t-set="alignment" t-value="getConnectorCreatorAlignment('bottom')" />
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.GroupPill">
|
||||||
|
<div
|
||||||
|
class="o_gantt_pill_wrapper o_gantt_group_pill align-items-center"
|
||||||
|
t-att-class="{
|
||||||
|
o_sample_data_disabled: isDisabled(row),
|
||||||
|
o_group_open: !model.isClosed(row.id),
|
||||||
|
}"
|
||||||
|
t-att-style="getGridPosition(pill.grid)"
|
||||||
|
>
|
||||||
|
<div class="o_gantt_pill o_gantt_consolidated_pill position-relative overflow-visible"
|
||||||
|
t-att-class="pill.className"
|
||||||
|
t-att-title="pill.displayName"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
t-if="pill._progress"
|
||||||
|
class="position-absolute h-100 o_gantt_progress"
|
||||||
|
t-attf-style="width:{{ pill._progress }}%;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class="o_gantt_pill_title bg-view text-truncate px-1 z-1" t-esc="pill.displayName" />
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRenderer.TotalRow">
|
||||||
|
<t t-if="hasRowHeaders">
|
||||||
|
<div class="o_gantt_row_total o_gantt_row_sidebar border-end position-sticky start-0 bg-view d-flex justify-content-end">
|
||||||
|
<h4
|
||||||
|
class="o_gantt_row_title d-flex align-items-center pe-3 my-0 fw-bold"
|
||||||
|
t-att-class="{ o_sample_data_disabled: isDisabled() }"
|
||||||
|
t-att-title="totalRow.name"
|
||||||
|
t-esc="totalRow.name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
<div class="o_gantt_row_total o_gantt_grid_columns bg-view">
|
||||||
|
<t t-foreach="columns" t-as="column" t-key="column.id">
|
||||||
|
<div
|
||||||
|
class="o_gantt_cell"
|
||||||
|
t-att-class="{ o_gantt_today: column.isToday, o_sample_data_disabled: isDisabled() }"
|
||||||
|
t-att-style="getGridPosition({ column: column.grid.column, row: [1, 2] })"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
<t t-foreach="totalRow.pills" t-as="pill" t-key="pill.id">
|
||||||
|
<div
|
||||||
|
class="o_gantt_pill_wrapper position-relative p-0 h-100 d-flex align-items-end"
|
||||||
|
t-att-class="{ o_sample_data_disabled: isDisabled() }"
|
||||||
|
t-att-style="getGridPosition({ column: pill.grid.column, row: [1, 2] })"
|
||||||
|
>
|
||||||
|
<div class="o_gantt_pill o_gantt_consolidated_pill w-100 d-flex align-items-end justify-content-center"
|
||||||
|
t-att-title="pill.displayName"
|
||||||
|
t-attf-style="height: {{ totalRow.factor * pill.aggregateValue }}%;"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="o_gantt_consolidated_pill_title bg-view text-truncate px-1 mb-1"
|
||||||
|
t-att-class="{ 'o_gantt_consolidated_pill_small': this.isPillSmall(pill) }"
|
||||||
|
t-esc="pill.displayName"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
import { Component, useState } from "@odoo/owl";
|
||||||
|
import { useDateTimePicker } from "@web/core/datetime/datetime_hook";
|
||||||
|
import { Dropdown } from "@web/core/dropdown/dropdown";
|
||||||
|
import { useDropdownState } from "@web/core/dropdown/dropdown_hooks";
|
||||||
|
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
|
||||||
|
import { formatDate } from "@web/core/l10n/dates";
|
||||||
|
import { _t } from "@web/core/l10n/translation";
|
||||||
|
import { pick } from "@web/core/utils/objects";
|
||||||
|
import { debounce } from "@web/core/utils/timing";
|
||||||
|
import {
|
||||||
|
diffColumn,
|
||||||
|
getRangeFromDate,
|
||||||
|
localStartOf,
|
||||||
|
useGanttResponsivePopover,
|
||||||
|
} from "./gantt_helpers";
|
||||||
|
|
||||||
|
const { DateTime } = luxon;
|
||||||
|
|
||||||
|
const KEYS = ["startDate", "stopDate", "rangeId", "focusDate"];
|
||||||
|
|
||||||
|
export class GanttRendererControls extends Component {
|
||||||
|
static template = "web_gantt.GanttRendererControls";
|
||||||
|
static components = {
|
||||||
|
Dropdown,
|
||||||
|
DropdownItem,
|
||||||
|
};
|
||||||
|
static props = ["model", "displayExpandCollapseButtons", "focusToday", "getCurrentFocusDate"];
|
||||||
|
static toolbarContentTemplate = "web_gantt.GanttRendererControls.ToolbarContent";
|
||||||
|
static rangeMenuTemplate = "web_gantt.GanttRendererControls.RangeMenu";
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.model = this.props.model;
|
||||||
|
this.updateMetaData = debounce(() => this.model.fetchData(this.makeParams()), 500);
|
||||||
|
|
||||||
|
const { metaData } = this.model;
|
||||||
|
this.state = useState({
|
||||||
|
scaleIndex: this.getScaleIndex(metaData.scale.id),
|
||||||
|
...pick(metaData, ...KEYS),
|
||||||
|
});
|
||||||
|
this.pickerValues = useState({
|
||||||
|
startDate: metaData.startDate,
|
||||||
|
stopDate: metaData.stopDate,
|
||||||
|
});
|
||||||
|
this.scalesRange = { min: 0, max: Object.keys(metaData.scales).length - 1 };
|
||||||
|
|
||||||
|
const getPickerProps = (key) => ({ type: "date", value: this.pickerValues[key] });
|
||||||
|
this.startPicker = useDateTimePicker({
|
||||||
|
target: "start-picker",
|
||||||
|
onApply: (date) => {
|
||||||
|
this.pickerValues.startDate = date;
|
||||||
|
if (this.pickerValues.stopDate < date) {
|
||||||
|
this.pickerValues.stopDate = date;
|
||||||
|
} else if (date.plus({ year: 10, day: -1 }) < this.pickerValues.stopDate) {
|
||||||
|
this.pickerValues.stopDate = date.plus({ year: 10, day: -1 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get pickerProps() {
|
||||||
|
return getPickerProps("startDate");
|
||||||
|
},
|
||||||
|
createPopover: (...args) => useGanttResponsivePopover(_t("Gantt start date"), ...args),
|
||||||
|
ensureVisibility: () => false,
|
||||||
|
});
|
||||||
|
this.stopPicker = useDateTimePicker({
|
||||||
|
target: "stop-picker",
|
||||||
|
onApply: (date) => {
|
||||||
|
this.pickerValues.stopDate = date;
|
||||||
|
if (date < this.pickerValues.startDate) {
|
||||||
|
this.pickerValues.startDate = date;
|
||||||
|
} else if (this.pickerValues.startDate.plus({ year: 10, day: -1 }) < date) {
|
||||||
|
this.pickerValues.startDate = date.minus({ year: 10, day: -1 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get pickerProps() {
|
||||||
|
return getPickerProps("stopDate");
|
||||||
|
},
|
||||||
|
createPopover: (...args) => useGanttResponsivePopover(_t("Gantt stop date"), ...args),
|
||||||
|
ensureVisibility: () => false,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dropdownState = useDropdownState();
|
||||||
|
}
|
||||||
|
|
||||||
|
get dateDescription() {
|
||||||
|
const { focusDate, rangeId } = this.state;
|
||||||
|
switch (rangeId) {
|
||||||
|
case "quarter":
|
||||||
|
return focusDate.toFormat(`Qq yyyy`);
|
||||||
|
case "day":
|
||||||
|
return formatDate(focusDate);
|
||||||
|
default:
|
||||||
|
return this.model.metaData.scales[rangeId].groupHeaderFormatter(
|
||||||
|
focusDate,
|
||||||
|
this.env
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormattedDate(date) {
|
||||||
|
return formatDate(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
getScaleIdFromIndex(index) {
|
||||||
|
const keys = Object.keys(this.model.metaData.scales);
|
||||||
|
return keys[keys.length - 1 - index];
|
||||||
|
}
|
||||||
|
|
||||||
|
getScaleIndex(scaleId) {
|
||||||
|
const keys = Object.keys(this.model.metaData.scales);
|
||||||
|
return keys.length - 1 - keys.findIndex((id) => id === scaleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getScaleIndexFromRangeId(rangeId) {
|
||||||
|
const { ranges } = this.model.metaData;
|
||||||
|
const scaleId = ranges[rangeId].scaleId;
|
||||||
|
return this.getScaleIndex(scaleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {1|-1} inc
|
||||||
|
*/
|
||||||
|
incrementScale(inc) {
|
||||||
|
if (
|
||||||
|
inc === 1
|
||||||
|
? this.state.scaleIndex < this.scalesRange.max
|
||||||
|
: this.scalesRange.min < this.state.scaleIndex
|
||||||
|
) {
|
||||||
|
this.state.scaleIndex += inc;
|
||||||
|
this.updateMetaData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelected(rangeId) {
|
||||||
|
if (rangeId === "custom") {
|
||||||
|
return (
|
||||||
|
this.state.rangeId === rangeId ||
|
||||||
|
!localStartOf(this.state.focusDate, this.state.rangeId).equals(
|
||||||
|
localStartOf(DateTime.now(), this.state.rangeId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.state.rangeId === rangeId &&
|
||||||
|
localStartOf(this.state.focusDate, rangeId).equals(
|
||||||
|
localStartOf(DateTime.now(), rangeId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeParams() {
|
||||||
|
return {
|
||||||
|
currentFocusDate: this.props.getCurrentFocusDate(),
|
||||||
|
scaleId: this.getScaleIdFromIndex(this.state.scaleIndex),
|
||||||
|
...pick(this.state, ...KEYS),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onApply() {
|
||||||
|
this.state.startDate = this.pickerValues.startDate;
|
||||||
|
this.state.stopDate = this.pickerValues.stopDate;
|
||||||
|
this.state.rangeId = "custom";
|
||||||
|
this.updateMetaData();
|
||||||
|
this.dropdownState.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onTodayClicked() {
|
||||||
|
const success = this.props.focusToday();
|
||||||
|
if (success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.state.focusDate = DateTime.local().startOf("day");
|
||||||
|
if (this.state.rangeId === "custom") {
|
||||||
|
const diff = diffColumn(this.state.startDate, this.state.stopDate, "day");
|
||||||
|
const n = Math.floor(diff / 2);
|
||||||
|
const m = diff - n;
|
||||||
|
this.state.startDate = this.state.focusDate.minus({ day: n });
|
||||||
|
this.state.stopDate = this.state.focusDate.plus({ day: m - 1 });
|
||||||
|
} else {
|
||||||
|
this.state.startDate = this.state.focusDate.startOf(this.state.rangeId);
|
||||||
|
this.state.stopDate = this.state.focusDate.endOf(this.state.rangeId).startOf("day");
|
||||||
|
}
|
||||||
|
this.updatePickerValues();
|
||||||
|
this.updateMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectRange(direction) {
|
||||||
|
const sign = direction === "next" ? 1 : -1;
|
||||||
|
const { focusDate, rangeId, startDate, stopDate } = this.state;
|
||||||
|
if (rangeId === "custom") {
|
||||||
|
const diff = diffColumn(startDate, stopDate, "day") + 1;
|
||||||
|
this.state.focusDate = focusDate.plus({ day: sign * diff });
|
||||||
|
this.state.startDate = startDate.plus({ day: sign * diff });
|
||||||
|
this.state.stopDate = stopDate.plus({ day: sign * diff });
|
||||||
|
} else {
|
||||||
|
Object.assign(
|
||||||
|
this.state,
|
||||||
|
getRangeFromDate(rangeId, focusDate.plus({ [rangeId]: sign }))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.updatePickerValues();
|
||||||
|
this.updateMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectRangeId(rangeId) {
|
||||||
|
Object.assign(this.state, getRangeFromDate(rangeId, DateTime.now().startOf("day")));
|
||||||
|
this.state.scaleIndex = this.getScaleIndexFromRangeId(rangeId);
|
||||||
|
this.updatePickerValues();
|
||||||
|
this.updateMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectScale(index) {
|
||||||
|
this.state.scaleIndex = Number(index);
|
||||||
|
this.updateMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePickerValues() {
|
||||||
|
this.pickerValues.startDate = this.state.startDate;
|
||||||
|
this.pickerValues.stopDate = this.state.stopDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRendererControls">
|
||||||
|
<div
|
||||||
|
class="o_gantt_renderer_controls d-inline-flex d-print-none flex-wrap column-gap-2 align-items-center w-100 bg-view border-bottom sticky-top start-0"
|
||||||
|
t-att-class="{ 'p-1': !env.isSmall, 'gap-1 py-1': env.isSmall }"
|
||||||
|
>
|
||||||
|
<t t-call="{{ constructor.rangeMenuTemplate }}" />
|
||||||
|
<hr t-if="env.isSmall" class="my-0 w-100"/>
|
||||||
|
<button
|
||||||
|
class="o_gantt_button_today btn btn-secondary"
|
||||||
|
t-att-class="{ 'ms-3': env.isSmall }"
|
||||||
|
title="Focus Today"
|
||||||
|
data-hotkey="t"
|
||||||
|
t-on-click="onTodayClicked"
|
||||||
|
>
|
||||||
|
<i class="fa fa-crosshairs"/>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-secondary"
|
||||||
|
t-att-disabled="state.scaleIndex === scalesRange.min"
|
||||||
|
data-hotkey="j"
|
||||||
|
t-on-click="() => this.incrementScale(-1)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-search-minus"/>
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
class="form-range flex-grow-1 w-0"
|
||||||
|
t-att-min="scalesRange.min" t-att-max="scalesRange.max" step="1"
|
||||||
|
t-att-value="state.scaleIndex"
|
||||||
|
t-on-change="(ev) => this.selectScale(ev.target.value)"
|
||||||
|
/>
|
||||||
|
<button class="btn btn-secondary"
|
||||||
|
t-att-disabled="state.scaleIndex === scalesRange.max"
|
||||||
|
data-hotkey="i"
|
||||||
|
t-on-click="() => this.incrementScale(1)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-search-plus"/>
|
||||||
|
</button>
|
||||||
|
<t t-if="env.isSmall">
|
||||||
|
<div class="flex-grow-1 w-0"/>
|
||||||
|
<Dropdown>
|
||||||
|
<button class="btn btn-secondary me-3" aria-label="Toolbar menu">
|
||||||
|
<i class="fa fa-cog"/>
|
||||||
|
</button>
|
||||||
|
<t t-set-slot="content">
|
||||||
|
<t t-call="{{ constructor.toolbarContentTemplate }}" />
|
||||||
|
</t>
|
||||||
|
</Dropdown>
|
||||||
|
</t>
|
||||||
|
<t t-else="" t-call="{{ constructor.toolbarContentTemplate }}" />
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRendererControls.ToolbarContent">
|
||||||
|
<t t-if="!env.isSmall">
|
||||||
|
<div class="btn-toolbar gap-2" role="toolbar" name="ganttToolbar">
|
||||||
|
<button class="btn btn-secondary fa"
|
||||||
|
t-att-class="{ 'fa-compress': model.displayParams.displayMode === 'sparse', 'fa-expand': model.displayParams.displayMode === 'dense' }"
|
||||||
|
t-att-title="model.displayParams.displayMode === 'dense' ? 'Activate sparse mode' : 'Activate dense mode'"
|
||||||
|
t-on-click="model.toggleDisplayMode.bind(model)"
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
<div class="btn-group" t-att-class="{ invisible: !props.displayExpandCollapseButtons }" name="expandCollapseButtons">
|
||||||
|
<button class="o_gantt_button_expand_rows btn btn-secondary" title="Expand rows" t-on-click="model.expandRows.bind(model)">
|
||||||
|
<i class="fa fa-caret-square-o-right"/>
|
||||||
|
</button>
|
||||||
|
<button class="o_gantt_button_collapse_rows btn btn-secondary" title="Collapse rows" t-on-click="model.collapseRows.bind(model)">
|
||||||
|
<i class="fa fa-caret-square-o-down"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<DropdownItem onSelected="model.toggleDisplayMode.bind(model)">
|
||||||
|
<t t-if="model.displayParams.displayMode === 'dense'">
|
||||||
|
<i class="fa fa-fw fa-expand"/>
|
||||||
|
<span class="ms-1">Activate sparse mode</span>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<i class="fa fa-fw fa-compress"/>
|
||||||
|
<span class="ms-1">Activate dense mode</span>
|
||||||
|
</t>
|
||||||
|
</DropdownItem>
|
||||||
|
<t t-if="props.displayExpandCollapseButtons">
|
||||||
|
<div class="dropdown-divider" role="separator"/>
|
||||||
|
<DropdownItem onSelected="model.expandRows.bind(model)">
|
||||||
|
<i class="fa fa-fw fa-caret-square-o-right"/>
|
||||||
|
<span class="ms-1">Expand rows</span>
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem onSelected="model.collapseRows.bind(model)">
|
||||||
|
<i class="fa fa-fw fa-caret-square-o-down"/>
|
||||||
|
<span class="ms-1">Collapse rows</span>
|
||||||
|
</DropdownItem>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttRendererControls.RangeMenu">
|
||||||
|
<div class="btn-group" t-att-class="{ 'ms-3': env.isSmall }">
|
||||||
|
<button class="btn btn-secondary" data-hotkey="p" t-on-click="() => this.selectRange('previous')" >
|
||||||
|
<i class="fa fa-arrow-left"/>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-secondary" data-hotkey="n" t-on-click="() => this.selectRange('next')">
|
||||||
|
<i class="fa fa-arrow-right"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Dropdown state="dropdownState" menuClass="'o_gantt_range_menu'">
|
||||||
|
<div class="btn btn-secondary">
|
||||||
|
<i class="fa fa-calendar me-1"/>
|
||||||
|
<t t-if="state.rangeId === 'custom'">
|
||||||
|
<t t-esc="`From: ${getFormattedDate(state.startDate)} to: ${getFormattedDate(state.stopDate)}`"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<t t-esc="dateDescription"/>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
<t t-set-slot="content">
|
||||||
|
<t t-foreach="Object.entries(model.metaData.ranges)" t-as="range" t-key="range[0]">
|
||||||
|
<DropdownItem class="{ 'selected': isSelected(range[0]) }" onSelected="() => this.selectRangeId(range[0])">
|
||||||
|
<t t-esc="range[1].description" />
|
||||||
|
</DropdownItem>
|
||||||
|
</t>
|
||||||
|
<div class="dropdown-divider"/>
|
||||||
|
<DropdownItem class="{ 'o_gantt_range_custom_item py-0': true, 'selected': isSelected('custom') }" closingMode="'none'">
|
||||||
|
<div class="d-flex align-items-center gap-1">
|
||||||
|
<label>From </label>
|
||||||
|
<span class="o_gantt_picker o_input cursor-pointer px-1" t-ref="start-picker" t-on-click="() => startPicker.open()">
|
||||||
|
<t t-esc="getFormattedDate(pickerValues.startDate)" />
|
||||||
|
</span>
|
||||||
|
<label>to </label>
|
||||||
|
<span class="o_gantt_picker o_input cursor-pointer px-1" t-ref="stop-picker" t-on-click="() => stopPicker.open()">
|
||||||
|
<t t-esc="getFormattedDate(pickerValues.stopDate)" />
|
||||||
|
</span>
|
||||||
|
<button class="btn btn-sm btn-primary ms-1" t-on-click="onApply">Apply</button>
|
||||||
|
</div>
|
||||||
|
</DropdownItem>
|
||||||
|
</t>
|
||||||
|
</Dropdown>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Component } from "@odoo/owl";
|
||||||
|
|
||||||
|
export class GanttResizeBadge extends Component {
|
||||||
|
static props = {
|
||||||
|
reactive: {
|
||||||
|
type: Object,
|
||||||
|
shape: {
|
||||||
|
position: {
|
||||||
|
type: Object,
|
||||||
|
shape: {
|
||||||
|
top: Number,
|
||||||
|
right: { type: Number, optional: true },
|
||||||
|
left: { type: Number, optional: true },
|
||||||
|
},
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
diff: { type: Number, optional: true },
|
||||||
|
scale: { type: String, optional: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static template = "web_gantt.GanttResizeBadge";
|
||||||
|
|
||||||
|
get diff() {
|
||||||
|
return this.props.reactive.diff || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get diffText() {
|
||||||
|
const { diff, props } = this;
|
||||||
|
const prefix = this.diff > 0 ? "+" : "";
|
||||||
|
return `${prefix}${diff} ${props.reactive.scale}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get positionStyle() {
|
||||||
|
const { position } = this.props.reactive;
|
||||||
|
const style = [`top:${position.top}px`];
|
||||||
|
if ("left" in position) {
|
||||||
|
style.push(`left:${position.left}px`);
|
||||||
|
} else {
|
||||||
|
style.push(`right:${position.right}px`);
|
||||||
|
}
|
||||||
|
return style.join(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="web_gantt.GanttResizeBadge">
|
||||||
|
<span
|
||||||
|
t-if="props.reactive.position"
|
||||||
|
class="o_gantt_pill_resize_badge badge rounded-pill bg-view position-fixed"
|
||||||
|
t-att-class="{ 'text-success': diff > 0, 'text-danger': diff < 0 }"
|
||||||
|
t-att-style="positionStyle"
|
||||||
|
t-esc="diffText"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Component } from "@odoo/owl";
|
||||||
|
import { hasTouch, isMobileOS } from "@web/core/browser/feature_detection";
|
||||||
|
|
||||||
|
export class GanttRowProgressBar extends Component {
|
||||||
|
static props = {
|
||||||
|
reactive: {
|
||||||
|
type: Object,
|
||||||
|
shape: {
|
||||||
|
hoveredRowId: [String, { value: null }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowId: String,
|
||||||
|
progressBar: {
|
||||||
|
type: Object,
|
||||||
|
shape: {
|
||||||
|
max_value: Number,
|
||||||
|
max_value_formatted: String,
|
||||||
|
ratio: Number,
|
||||||
|
value_formatted: String,
|
||||||
|
warning: { type: String, optional: true },
|
||||||
|
"*": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static template = "web_gantt.GanttRowProgressBar";
|
||||||
|
|
||||||
|
get show() {
|
||||||
|
const { reactive, rowId } = this.props;
|
||||||
|
return reactive.hoveredRowId === rowId || isMobileOS() || hasTouch();
|
||||||
|
}
|
||||||
|
|
||||||
|
get status() {
|
||||||
|
const { ratio } = this.props.progressBar;
|
||||||
|
return ratio > 100 ? "danger" : ratio > 0 ? "success" : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.1" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
<t t-name="web_gantt.GanttRowProgressBar">
|
||||||
|
<span
|
||||||
|
class="o_gantt_progress_bar position-relative h-100 pe-none"
|
||||||
|
t-att-class="`o_gantt_group_${status || 'none'}`"
|
||||||
|
>
|
||||||
|
<t t-if="props.progressBar.max_value gt 0">
|
||||||
|
<span
|
||||||
|
class="bg-opacity-25 position-absolute top-0 end-0 h-100"
|
||||||
|
t-att-class="status and `bg-${status}`"
|
||||||
|
t-attf-style="width:{{ Math.min(props.progressBar.ratio, 100) }}%;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
t-if="show"
|
||||||
|
class="position-absolute top-0 end-0 h-100 d-flex align-items-center px-1"
|
||||||
|
t-att-class="status ? `text-bg-${status}` : 'bg-view'"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="o_gantt_group_hours"
|
||||||
|
t-esc="`${props.progressBar.value_formatted} / ${props.progressBar.max_value_formatted}`"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
<t t-elif="show and props.progressBar.warning">
|
||||||
|
<span
|
||||||
|
class="o_gantt_group_hours position-absolute top-0 end-0 h-100 d-flex align-items-center px-1 pe-auto bg-view"
|
||||||
|
t-attf-title="{{ props.progressBar.warning }}"
|
||||||
|
>
|
||||||
|
<t t-esc="props.progressBar.value_formatted"/>
|
||||||
|
<i class="fa fa-exclamation-triangle" />
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
|
||||||
|
function _mockGetGanttData(params) {
|
||||||
|
const lazy = !params.limit && !params.offset && params.groupby.length === 1;
|
||||||
|
let { groups, length } = this._mockWebReadGroup({
|
||||||
|
...params,
|
||||||
|
lazy,
|
||||||
|
fields: ["__record_ids:array_agg(id)"],
|
||||||
|
});
|
||||||
|
if (params.limit) {
|
||||||
|
// we don't care about pager feature in sample mode
|
||||||
|
// but we want to present something coherent
|
||||||
|
groups = groups.slice(0, params.limit);
|
||||||
|
length = groups.length;
|
||||||
|
}
|
||||||
|
groups.forEach((g) => (g.__record_ids = g.id)); // the sample server does not use the key __record_ids
|
||||||
|
|
||||||
|
const recordIds = [];
|
||||||
|
for (const group of groups) {
|
||||||
|
recordIds.push(...(group.__record_ids || []));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { records } = this._mockWebSearchReadUnity({
|
||||||
|
model: params.model,
|
||||||
|
domain: [["id", "in", recordIds]],
|
||||||
|
context: params.context,
|
||||||
|
specification: params.read_specification,
|
||||||
|
});
|
||||||
|
|
||||||
|
const unavailabilities = {};
|
||||||
|
for (const fieldName of params.unavailability_fields || []) {
|
||||||
|
unavailabilities[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress_bars = {};
|
||||||
|
for (const fieldName of params.progress_bar_fields || []) {
|
||||||
|
progress_bars[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { groups, length, records, unavailabilities, progress_bars };
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.category("sample_server").add("get_gantt_data", _mockGetGanttData);
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// = Gantt View
|
||||||
|
// ============================================================================
|
||||||
|
// No CSS hacks, variables overrides only
|
||||||
|
|
||||||
|
.o_web_client .o_gantt_view {
|
||||||
|
--Gantt__DayOff-background-color: rgba(255, 255, 255, .05);
|
||||||
|
// Mix between $gantt-highlight-today-bg and $o-view-background-color
|
||||||
|
// to simulate the superposition of these two colors
|
||||||
|
--Gantt__DayOffToday-background-color: #553F3A;
|
||||||
|
|
||||||
|
.o_gantt_connector {
|
||||||
|
--Connector__ButtonBackground-color: #{$o-view-background-color};
|
||||||
|
--Connector__ButtonReschedule-color: #{darken($o-component-active-border, 10%)};
|
||||||
|
--Connector__ButtonBorder-color: #{$o-gray-500};
|
||||||
|
--Connector__ButtonAccent-color: #{$o-black};
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_renderer {
|
||||||
|
--Gantt__DayOff-background-color: #{$o-gray-300};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
import { scrollSymbol } from "@web/search/action_hook";
|
||||||
|
import { GanttArchParser } from "./gantt_arch_parser";
|
||||||
|
import { GanttController } from "./gantt_controller";
|
||||||
|
import { GanttModel } from "./gantt_model";
|
||||||
|
import { GanttRenderer } from "./gantt_renderer";
|
||||||
|
import { omit } from "@web/core/utils/objects";
|
||||||
|
|
||||||
|
const viewRegistry = registry.category("views");
|
||||||
|
|
||||||
|
export const ganttView = {
|
||||||
|
type: "gantt",
|
||||||
|
Controller: GanttController,
|
||||||
|
Renderer: GanttRenderer,
|
||||||
|
Model: GanttModel,
|
||||||
|
ArchParser: GanttArchParser,
|
||||||
|
searchMenuTypes: ["filter", "groupBy", "favorite"],
|
||||||
|
buttonTemplate: "web_gantt.GanttView.Buttons",
|
||||||
|
|
||||||
|
props: (genericProps, view, config) => {
|
||||||
|
const modelParams = {};
|
||||||
|
let scrollPosition;
|
||||||
|
if (genericProps.state) {
|
||||||
|
scrollPosition = genericProps.state[scrollSymbol];
|
||||||
|
modelParams.metaData = genericProps.state.metaData;
|
||||||
|
modelParams.displayParams = genericProps.state.displayParams;
|
||||||
|
} else {
|
||||||
|
const { arch, fields, resModel } = genericProps;
|
||||||
|
const parser = new view.ArchParser();
|
||||||
|
const archInfo = parser.parse(arch);
|
||||||
|
|
||||||
|
let formViewId = archInfo.formViewId;
|
||||||
|
if (!formViewId) {
|
||||||
|
const formView = config.views.find((v) => v[1] === "form");
|
||||||
|
if (formView) {
|
||||||
|
formViewId = formView[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modelParams.metaData = {
|
||||||
|
...omit(archInfo, "displayMode"),
|
||||||
|
fields,
|
||||||
|
resModel,
|
||||||
|
formViewId,
|
||||||
|
};
|
||||||
|
modelParams.displayParams = {
|
||||||
|
displayMode: archInfo.displayMode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...genericProps,
|
||||||
|
modelParams,
|
||||||
|
Model: view.Model,
|
||||||
|
Renderer: view.Renderer,
|
||||||
|
buttonTemplate: view.buttonTemplate,
|
||||||
|
scrollPosition,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
viewRegistry.add("gantt", ganttView);
|
||||||
|
|
@ -0,0 +1,682 @@
|
||||||
|
.o_gantt_view {
|
||||||
|
--Gantt__Buttons-height: 45px;
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
--Gantt__Buttons-height: 91px; // = 2 times the height in normal display + 1px for the <hr> element
|
||||||
|
}
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.o_view_nocontent {
|
||||||
|
@include o-gantt-zindex(view-nocontent);
|
||||||
|
position: fixed;
|
||||||
|
top: 225px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_view_sample_data .o_sample_data_disabled {
|
||||||
|
@include o-sample-data-disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_renderer_controls {
|
||||||
|
@include o-gantt-zindex(controls);
|
||||||
|
height: var(--Gantt__Buttons-height) !important;
|
||||||
|
input[type="range"] {
|
||||||
|
min-width: 80px;
|
||||||
|
max-width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-only(print) {
|
||||||
|
> .o_content {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_range_menu {
|
||||||
|
.o_gantt_range_custom_item.dropdown-item:not(.disabled):not(:disabled) {
|
||||||
|
background-color: inherit !important;
|
||||||
|
cursor: default !important;
|
||||||
|
label {
|
||||||
|
cursor: default !important;
|
||||||
|
}
|
||||||
|
&.selected {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_view .o_gantt_renderer {
|
||||||
|
|
||||||
|
// Renderer grid
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
grid-template-columns:
|
||||||
|
[row-headers] var(--Gantt__RowHeader-width) [content] 1fr;
|
||||||
|
|
||||||
|
--Gantt__RowHeader-template-column: 16px;
|
||||||
|
|
||||||
|
// Allows to use color variables in js
|
||||||
|
--Gantt__Day-background-color: #{$o-view-background-color};
|
||||||
|
--Gantt__DayOff-background-color: #e9ecef;
|
||||||
|
--Gantt__DayOffToday-background-color: #fffaeb;
|
||||||
|
|
||||||
|
// Group colors
|
||||||
|
--Gantt__Group-background: linear-gradient(#{darken($gantt-row-open-bg, 5%)},
|
||||||
|
#{$gantt-row-open-bg});
|
||||||
|
--Gantt__GroupOpen-background: linear-gradient(#{$gantt-row-open-bg},
|
||||||
|
#{darken($gantt-row-open-bg, 5%)});
|
||||||
|
--Gantt__GroupToday-background: #{mix($gantt-row-open-bg, $gantt-highlight-today-bg)};
|
||||||
|
|
||||||
|
// ============================= Main Layout ==============================
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
// Utilities to use the grid-template-rows or grid-template-columns
|
||||||
|
.o_gantt_grid_rows {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: var(--Gantt__GridRows-grid-template-rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_grid_columns {
|
||||||
|
display: grid;
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
grid-template-columns: var(--Gantt__GridColumns-grid-template-columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row headers
|
||||||
|
.o_gantt_row_header {
|
||||||
|
cursor: pointer;
|
||||||
|
display: grid;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-row: 3;
|
||||||
|
grid-template-columns: repeat(auto-fill,
|
||||||
|
minmax(var(--Gantt__RowHeader-template-column), 1fr));
|
||||||
|
line-height: var(--Gantt__Pill-height);
|
||||||
|
|
||||||
|
.o_gantt_progress_bar {
|
||||||
|
grid-row: 1;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_row_title {
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_gantt_group {
|
||||||
|
line-height: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_mobile_progress_bar {
|
||||||
|
grid-template-rows: 1fr var(--Gantt__Pill-height);
|
||||||
|
|
||||||
|
.o_gantt_progress_bar {
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================== Buttons ================================
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
.o_gantt_buttons_container {
|
||||||
|
gap: 0.25rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All rows (Regular, Group Header and Total)
|
||||||
|
// ==========================================
|
||||||
|
.o_gantt_row_thumbnail_wrapper .o_gantt_row_thumbnail {
|
||||||
|
width: auto;
|
||||||
|
max-height: var(--Gantt__Thumbnail-max-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============== Cursors while dragging ==============
|
||||||
|
// =======================================================
|
||||||
|
|
||||||
|
&.o_grabbing,
|
||||||
|
&.o_grabbing .o_gantt_pill {
|
||||||
|
cursor: move !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_copying,
|
||||||
|
&.o_copying .o_gantt_pill {
|
||||||
|
cursor: copy !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_grabbing_locked,
|
||||||
|
&.o_grabbing_locked .o_gantt_pill {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(md) {
|
||||||
|
& {
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_dragged_pill_ghost {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================ Header ===============
|
||||||
|
// =======================================
|
||||||
|
|
||||||
|
.o_gantt_title {
|
||||||
|
top: var(--Gantt__Buttons-height);
|
||||||
|
@include o-gantt-zindex(title);
|
||||||
|
border-bottom: 1px solid $gantt-border-color;
|
||||||
|
grid-row: 1 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_header_groups {
|
||||||
|
top: var(--Gantt__Buttons-height);
|
||||||
|
@include o-gantt-zindex(column-header-groups);
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_header_columns {
|
||||||
|
top: var(--Gantt__Buttons-height);
|
||||||
|
@include o-gantt-zindex(headers);
|
||||||
|
grid-row: 2;
|
||||||
|
margin-top: calc(var(--Gantt__Pill-height) * -1);
|
||||||
|
padding-top: var(--Gantt__Pill-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_header_cell {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-bottom-color: $gantt-border-color;
|
||||||
|
border-right-color: $gantt-border-color;
|
||||||
|
height: var(--Gantt__Pill-height);
|
||||||
|
color: $headings-color;
|
||||||
|
position: relative;
|
||||||
|
@include o-gantt-cell;
|
||||||
|
|
||||||
|
@include media-breakpoint-down(md) {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_header_title {
|
||||||
|
height: var(--Gantt__Pill-height);
|
||||||
|
left: calc(var(--Gantt__RowHeader-width) - 1px);
|
||||||
|
border: solid $gantt-border-color;
|
||||||
|
border-width: 0 0 1px 1px;
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= All sidebar headers (Header, Regular, Groups and Total) ========
|
||||||
|
// ========================================================================
|
||||||
|
.o_gantt_row_sidebar {
|
||||||
|
@include o-gantt-zindex(headers);
|
||||||
|
grid-column: 1;
|
||||||
|
color: $headings-color;
|
||||||
|
|
||||||
|
&:not(.o_gantt_row_headers) {
|
||||||
|
border-bottom: 1px solid $gantt-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_progressbar,
|
||||||
|
.o_gantt_text_hoverable {
|
||||||
|
right: 0;
|
||||||
|
height: 100%;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================== "Regular" & "Group Header" cells ===================
|
||||||
|
// ========================================================================
|
||||||
|
.o_gantt_cell {
|
||||||
|
border: solid $gantt-border-color;
|
||||||
|
border-width: 0 1px 1px 0;
|
||||||
|
@include o-gantt-cell;
|
||||||
|
@include o-gantt-zindex(grid);
|
||||||
|
|
||||||
|
&.o_drag_hover {
|
||||||
|
background: $gantt-highlight-cell-color !important;
|
||||||
|
@include o-gantt-zindex(grid-interact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================ Pills =================================
|
||||||
|
// ========================================================================
|
||||||
|
.o_gantt_pill_wrapper {
|
||||||
|
padding: 2px 2px 3px 3px;
|
||||||
|
min-height: var(--Gantt__Pill-height);
|
||||||
|
@include o-gantt-zindex(pill);
|
||||||
|
|
||||||
|
// Group pills
|
||||||
|
&.o_gantt_group_pill {
|
||||||
|
pointer-events: none;
|
||||||
|
min-height: auto;
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
.o_gantt_pill {
|
||||||
|
grid-area: 1 / 1;
|
||||||
|
background-color: $primary;
|
||||||
|
border-color: $primary;
|
||||||
|
height: 2px;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
border-top: 4px solid transparent;
|
||||||
|
border-bottom: 5px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
border-left: 5px solid;
|
||||||
|
border-left-color: inherit;
|
||||||
|
@include o-position-absolute($top: -3px, $left: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-right: 5px solid;
|
||||||
|
border-right-color: inherit;
|
||||||
|
@include o-position-absolute($top: -3px, $right: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_group_open .o_gantt_pill {
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
top: 2px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-top-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
border-left-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-right-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_pill_title {
|
||||||
|
grid-area: 1 / 1;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_resizable {
|
||||||
|
.o_resize_handle {
|
||||||
|
width: 0.5rem
|
||||||
|
/* 6px */
|
||||||
|
;
|
||||||
|
pointer-events: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
|
||||||
|
&.o_handle_start {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_handle_end {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include o-gantt-hover() {
|
||||||
|
&:not(.o_resized) .o_resize_handle {
|
||||||
|
background-color: rgba(230, 230, 230, 0.5);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(230, 230, 230, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_draggable,
|
||||||
|
&.o_undraggable {
|
||||||
|
transition: transform 0.6s, box-shadow 0.3s;
|
||||||
|
|
||||||
|
&.o_dragged {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: rotate(-3deg);
|
||||||
|
box-shadow: 0 5px 25px -10px black;
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
|
||||||
|
.o_gantt_pill {
|
||||||
|
box-shadow: 0 5px 25px -10px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_resize_handle {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_undraggable:not(.o_dragged) .o_gantt_lock {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_resizable.o_resized {
|
||||||
|
.o_gantt_pill {
|
||||||
|
cursor: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_resize_handle {
|
||||||
|
background-color: rgba(black, 0.5);
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_consolidated_pill_title {
|
||||||
|
background: none !important;
|
||||||
|
color: $headings-color;
|
||||||
|
position: absolute;
|
||||||
|
top: 21px;
|
||||||
|
font-size: 0.7em;
|
||||||
|
|
||||||
|
&.o_gantt_consolidated_pill_small {
|
||||||
|
transform: rotate(75deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.o_connector_creator_lock):not(.o_connector_creator_highlight) .o_connector_creator_wrapper {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include o-gantt-hover() {
|
||||||
|
.o_connector_creator_wrapper {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// used for `color` attribute on <gantt>
|
||||||
|
@for $index from 1 through length($o-colors-complete) {
|
||||||
|
$color: nth($o-colors-complete, $index);
|
||||||
|
|
||||||
|
.o_gantt_pill.o_gantt_color_#{$index - 1} .o_gantt_progress {
|
||||||
|
opacity: 0.2;
|
||||||
|
background-color: darken($color, 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.highlight .o_gantt_pill.o_gantt_color_#{$index - 1} {
|
||||||
|
color: color-contrast($color);
|
||||||
|
background-color: $color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================== Main pill content ===========================
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
.o_gantt_cells {
|
||||||
|
grid-row: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_cells .o_gantt_pill {
|
||||||
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
box-sizing: content-box;
|
||||||
|
cursor: pointer;
|
||||||
|
@include o-gantt-hoverable-colors(nth($o-colors-complete, 1));
|
||||||
|
|
||||||
|
.o_gantt_pill_title {
|
||||||
|
// Prevent displaying pill's description when size is smaller than 50px
|
||||||
|
max-width: calc((100% - 50px) * 9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_pill_avatar {
|
||||||
|
// Prevent displaying pill's avatar when size is smaller than 100px
|
||||||
|
max-width: calc((100% - 100px) * 9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.decoration-info {
|
||||||
|
@include o-gantt-gradient-decorations(nth($o-colors-complete, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// used for `color` attribute on <gantt>
|
||||||
|
@for $index from 1 through length($o-colors-complete) {
|
||||||
|
&.o_gantt_color_#{$index - 1} {
|
||||||
|
$gantt-color: nth($o-colors-complete, $index);
|
||||||
|
|
||||||
|
@include o-gantt-hoverable-colors($gantt-color);
|
||||||
|
|
||||||
|
&.decoration-info {
|
||||||
|
@include o-gantt-gradient-decorations($gantt-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_progress {
|
||||||
|
opacity: 0.2;
|
||||||
|
background-color: darken($gantt-color, 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&.decoration-#{$color}:before {
|
||||||
|
@include o-gantt-ribbon-decoration($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================= "Group Header" rows ==========================
|
||||||
|
// ========================================================================
|
||||||
|
.o_gantt_group {
|
||||||
|
background: var(--Gantt__Group-background);
|
||||||
|
|
||||||
|
&.o_gantt_today {
|
||||||
|
background: var(--Gantt__GroupToday-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_gantt_group_hovered:not(.o_gantt_today) {
|
||||||
|
background: var(--Gantt__GroupOpen-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_group_open {
|
||||||
|
border-left-width: 0;
|
||||||
|
background: var(--Gantt__GroupOpen-background);
|
||||||
|
|
||||||
|
&.o_gantt_group_hovered {
|
||||||
|
background: var(--Gantt__Group-background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_gantt_row_header b {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================== Connector creators ==========================
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
.o_connector_creator_wrapper {
|
||||||
|
height: $o-connector-wrapper-height;
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
|
||||||
|
// used for `color` attribute on <gantt>
|
||||||
|
@for $index from 1 through length($o-colors-complete) {
|
||||||
|
&.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 {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
border-left: solid 1px $color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_connector_creator_bottom {
|
||||||
|
border-bottom: solid 1px $color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_connector_creator_left {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
border-right: solid 1px $color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_connector_creator_top {
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
.o_connector_creator_bullet {
|
||||||
|
top: -0.5 * $o-connector-creator-bullet-diameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_connector_creator_right {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
right: $o-connector-creator-size;
|
||||||
|
|
||||||
|
.o_connector_creator_bullet {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
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 {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
left: $o-connector-creator-size;
|
||||||
|
|
||||||
|
.o_connector_creator_bullet {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
left: -0.5 * $o-connector-creator-bullet-diameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================= "TOTAL" row ==============================
|
||||||
|
// ========================================================================
|
||||||
|
.o_gantt_row_total {
|
||||||
|
grid-row: 4;
|
||||||
|
|
||||||
|
.o_gantt_cell,
|
||||||
|
.o_gantt_row_title,
|
||||||
|
.o_gantt_pill_wrapper {
|
||||||
|
min-height: calc(var(--Gantt__Pill-height) * 1.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_pill {
|
||||||
|
color: inherit;
|
||||||
|
margin-left: 1px;
|
||||||
|
background-color: rgba($o-brand-odoo, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_pill_wrapper:hover {
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
.o_gantt_pill {
|
||||||
|
color: inherit;
|
||||||
|
background-color: rgba($o-brand-odoo, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
border: 1px solid $o-brand-odoo;
|
||||||
|
border-width: 0 1px;
|
||||||
|
background: rgba($o-brand-odoo, 0.1);
|
||||||
|
height: 100vh;
|
||||||
|
pointer-events: none;
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
@include o-position-absolute(auto, -1px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_cell:last-child .o_gantt_pill_wrapper:hover:before {
|
||||||
|
border-right: 0px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_pill_resize_badge {
|
||||||
|
transition: all 0.15s ease-in-out;
|
||||||
|
box-shadow: 0 1px 2px 0 rgba(black, 0.28);
|
||||||
|
@include o-gantt-zindex(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_gantt_connector {
|
||||||
|
--Connector__ButtonBorder-color: #091124;
|
||||||
|
--Connector__ButtonBackground-color: #ffffff;
|
||||||
|
--Connector__ButtonReschedule-color: #00a09d;
|
||||||
|
--Connector__ButtonRemove-color: #dd3c4f;
|
||||||
|
--Connector__ButtonAccent-color: #ffffff;
|
||||||
|
|
||||||
|
&.o_connector_highlighted {
|
||||||
|
@include o-gantt-zindex(interact);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_connector_stroke_button {
|
||||||
|
>rect {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: var(--Connector__ButtonBackground-color);
|
||||||
|
stroke: var(--Connector__ButtonBorder-color);
|
||||||
|
stroke-width: 24px;
|
||||||
|
transition: fill 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_connector_stroke_reschedule_button {
|
||||||
|
line {
|
||||||
|
stroke: var(--Connector__ButtonReschedule-color);
|
||||||
|
transition: stroke 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
>rect {
|
||||||
|
fill: var(--Connector__ButtonReschedule-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
line {
|
||||||
|
stroke: var(--Connector__ButtonAccent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.o_connector_stroke_remove_button {
|
||||||
|
g rect {
|
||||||
|
fill: var(--Connector__ButtonRemove-color);
|
||||||
|
transition: fill 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
>rect {
|
||||||
|
fill: var(--Connector__ButtonRemove-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
g rect {
|
||||||
|
fill: var(--Connector__ButtonAccent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// = Gantt View Variables
|
||||||
|
// ============================================================================
|
||||||
|
// No CSS hacks, variables overrides only
|
||||||
|
|
||||||
|
$gantt-highlight-today-border: rgba($o-warning, 0.5) !default;
|
||||||
|
$gantt-highlight-today-bg: rgba($o-warning, 0.15)!default;
|
||||||
|
$gantt-highlight-hover-row: rgba($o-brand-primary, .1) !default;
|
||||||
|
$gantt-row-open-bg: $o-gray-100 !default;
|
||||||
|
$gantt-unavailability-bg: $o-gray-200 !default;
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
// = Gantt View Variables
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Define the necessary conditions to provide visual feedback on hover,
|
||||||
|
// focus, drag, clone and resize.
|
||||||
|
@mixin o-gantt-hover() {
|
||||||
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&.o_dragged_pill,
|
||||||
|
&.ui-resizable-resize {
|
||||||
|
// Avoid visual feedback if 'o_gantt_renderer' has class 'o_grabbing', 'o_copying', 'o_no_dragging' or 'o_connect'
|
||||||
|
@at-root #{selector-replace(&, ".o_gantt_renderer", ".o_gantt_renderer:not(.o_grabbing):not(.o_copying):not(.o_no_dragging):not(.o_connect)")} {
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@include o-gantt-hover() {
|
||||||
|
background-color: $color;
|
||||||
|
color: color-contrast($color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate stripes decorations for each color.
|
||||||
|
@mixin o-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 o-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 o-gantt-cell {
|
||||||
|
&.o_gantt_today {
|
||||||
|
background-color: $gantt-highlight-today-bg;
|
||||||
|
border-left-color: $gantt-highlight-today-border;
|
||||||
|
border-top-color: $gantt-highlight-today-border;
|
||||||
|
|
||||||
|
+ .o_gantt_header_cell,
|
||||||
|
+ .o_gantt_cell {
|
||||||
|
border-left-color: $gantt-highlight-today-border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin o-gantt-zindex($level) {
|
||||||
|
z-index: map-get(
|
||||||
|
(
|
||||||
|
// Grid and grid interactions level
|
||||||
|
grid: 0,
|
||||||
|
grid-interact: 1,
|
||||||
|
// Pills level
|
||||||
|
pill: 10,
|
||||||
|
// Interactions => over pills
|
||||||
|
interact: 20,
|
||||||
|
// No-content helper
|
||||||
|
view-nocontent: 25,
|
||||||
|
headers: 30,
|
||||||
|
// Top-most elements
|
||||||
|
column-header-groups: 35,
|
||||||
|
title: 40,
|
||||||
|
controls: 50,
|
||||||
|
badge: 50,
|
||||||
|
),
|
||||||
|
$level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$gantt-border-color: $o-gray-300 !default;
|
||||||
|
$gantt-highlight-cell-color: rgba(0, 160, 157, 0.3) !default;
|
||||||
|
$gantt-highlight-today-border: #dca665 !default;
|
||||||
|
$gantt-highlight-today-bg: #fffaeb !default;
|
||||||
|
$gantt-highlight-hover-row: rgba($o-brand-primary, 0.1) !default;
|
||||||
|
$gantt-row-open-bg: $o-gray-100 !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;
|
||||||
|
|
@ -0,0 +1,921 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import {
|
||||||
|
hover,
|
||||||
|
pointerDown,
|
||||||
|
queryAll,
|
||||||
|
queryFirst,
|
||||||
|
queryOne,
|
||||||
|
queryRect,
|
||||||
|
resize,
|
||||||
|
} from "@odoo/hoot-dom";
|
||||||
|
import { advanceFrame, animationFrame, mockDate, runAllTimers } from "@odoo/hoot-mock";
|
||||||
|
import {
|
||||||
|
contains,
|
||||||
|
defineModels,
|
||||||
|
fields,
|
||||||
|
findComponent,
|
||||||
|
models,
|
||||||
|
onRpc,
|
||||||
|
patchWithCleanup,
|
||||||
|
} from "@web/../tests/web_test_helpers";
|
||||||
|
import {
|
||||||
|
clickConnectorButton,
|
||||||
|
getConnector,
|
||||||
|
getConnectorMap,
|
||||||
|
} from "@web_gantt/../tests/gantt_dependency_helpers";
|
||||||
|
import { COLORS } from "@web_gantt/gantt_connector";
|
||||||
|
import {
|
||||||
|
CLASSES,
|
||||||
|
SELECTORS,
|
||||||
|
getPill,
|
||||||
|
getPillWrapper,
|
||||||
|
mountGanttView,
|
||||||
|
} from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
import { GanttRenderer } from "@web_gantt/gantt_renderer";
|
||||||
|
|
||||||
|
/** @typedef {import("@web_gantt/gantt_renderer").ConnectorProps} ConnectorProps */
|
||||||
|
/** @typedef {import("@web_gantt/gantt_renderer").PillId} PillId */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {`[${ResId},${ResId},${ResId},${ResId}]`} ConnectorTaskIds
|
||||||
|
* In the following order: [masterTaskId, masterTaskUserId, taskId, taskUserId]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @typedef {number | false} ResId */
|
||||||
|
|
||||||
|
const ganttViewParams = {
|
||||||
|
resModel: "project.task",
|
||||||
|
arch: /* xml */ `<gantt date_start="planned_date_begin" date_stop="date_deadline" default_scale="month" dependency_field="depend_on_ids" color="color" />`,
|
||||||
|
groupBy: ["user_ids"],
|
||||||
|
};
|
||||||
|
|
||||||
|
let nextColor = 1;
|
||||||
|
class ProjectTask extends models.Model {
|
||||||
|
_name = "project.task";
|
||||||
|
|
||||||
|
name = fields.Char();
|
||||||
|
planned_date_begin = fields.Datetime({ string: "Start Date" });
|
||||||
|
date_deadline = fields.Datetime({ string: "Stop Date" });
|
||||||
|
user_ids = fields.Many2many({ string: "Assignees", relation: "res.users" });
|
||||||
|
allow_task_dependencies = fields.Boolean({ default: true });
|
||||||
|
depend_on_ids = fields.One2many({ string: "Depends on", relation: "project.task" });
|
||||||
|
display_warning_dependency_in_gantt = fields.Boolean({ default: true });
|
||||||
|
color = fields.Integer({ default: () => nextColor++ });
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Task 1",
|
||||||
|
planned_date_begin: "2021-10-11 18:30:00",
|
||||||
|
date_deadline: "2021-10-11 19:29:59",
|
||||||
|
user_ids: [1],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
planned_date_begin: "2021-10-12 11:30:00",
|
||||||
|
date_deadline: "2021-10-12 12:29:59",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Task 3",
|
||||||
|
planned_date_begin: "2021-10-13 06:30:00",
|
||||||
|
date_deadline: "2021-10-13 07:29:59",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Task 4",
|
||||||
|
planned_date_begin: "2021-10-14 22:30:00",
|
||||||
|
date_deadline: "2021-10-14 23:29:59",
|
||||||
|
user_ids: [2, 3],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Task 5",
|
||||||
|
planned_date_begin: "2021-10-15 01:53:10",
|
||||||
|
date_deadline: "2021-10-15 02:34:34",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Task 6",
|
||||||
|
planned_date_begin: "2021-10-16 23:00:00",
|
||||||
|
date_deadline: "2021-10-16 23:21:01",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [4, 5],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Task 7",
|
||||||
|
planned_date_begin: "2021-10-17 10:30:12",
|
||||||
|
date_deadline: "2021-10-17 11:29:59",
|
||||||
|
user_ids: [1, 2, 3],
|
||||||
|
depend_on_ids: [6],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Task 8",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-18 07:29:59",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [7],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "Task 9",
|
||||||
|
planned_date_begin: "2021-10-19 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [8],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "Task 10",
|
||||||
|
planned_date_begin: "2021-10-19 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: "Task 11",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-18 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [10],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
name: "Task 12",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
name: "Task 13",
|
||||||
|
planned_date_begin: "2021-10-18 07:29:59",
|
||||||
|
date_deadline: "2021-10-20 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [12],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResUsers extends models.Model {
|
||||||
|
_name = "res.users";
|
||||||
|
|
||||||
|
name = fields.Char();
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{ id: 1, name: "User 1" },
|
||||||
|
{ id: 2, name: "User 2" },
|
||||||
|
{ id: 3, name: "User 3" },
|
||||||
|
{ id: 4, name: "User 4" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
defineModels([ProjectTask, ResUsers]);
|
||||||
|
|
||||||
|
describe.current.tags("desktop");
|
||||||
|
|
||||||
|
beforeEach(() => mockDate("2021-10-10T08:00:00", +1));
|
||||||
|
|
||||||
|
test("Connectors are correctly computed and rendered.", async () => {
|
||||||
|
/**
|
||||||
|
* @type {Map<ConnectorTaskIds, keyof typeof COLORS>}
|
||||||
|
* => Check that there is a connector between masterTaskId from group masterTaskUserId and taskId from group taskUserId with normal|error color.
|
||||||
|
*/
|
||||||
|
const testMap = new Map([
|
||||||
|
["[1,1,2,1]", "default"],
|
||||||
|
["[1,1,2,3]", "default"],
|
||||||
|
["[2,1,3,false]", "default"],
|
||||||
|
["[2,3,3,false]", "default"],
|
||||||
|
["[2,1,4,2]", "default"],
|
||||||
|
["[2,3,4,3]", "default"],
|
||||||
|
["[4,2,6,1]", "default"],
|
||||||
|
["[4,3,6,3]", "default"],
|
||||||
|
["[5,false,6,1]", "default"],
|
||||||
|
["[5,false,6,3]", "default"],
|
||||||
|
["[6,1,7,1]", "default"],
|
||||||
|
["[6,1,7,2]", "default"],
|
||||||
|
["[6,3,7,2]", "default"],
|
||||||
|
["[6,3,7,3]", "default"],
|
||||||
|
["[7,1,8,1]", "default"],
|
||||||
|
["[7,2,8,1]", "default"],
|
||||||
|
["[7,2,8,3]", "default"],
|
||||||
|
["[7,3,8,3]", "default"],
|
||||||
|
["[8,1,9,2]", "default"],
|
||||||
|
["[8,3,9,2]", "default"],
|
||||||
|
["[10,2,11,2]", "error"],
|
||||||
|
["[12,2,13,2]", "warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const view = await mountGanttView(ganttViewParams);
|
||||||
|
const renderer = findComponent(view, (c) => c instanceof GanttRenderer);
|
||||||
|
|
||||||
|
const connectorMap = getConnectorMap(renderer);
|
||||||
|
|
||||||
|
for (const [testKey, colorCode] of testMap.entries()) {
|
||||||
|
const [masterTaskId, masterTaskUserId, taskId, taskUserId] = JSON.parse(testKey);
|
||||||
|
|
||||||
|
expect(connectorMap.has(testKey)).toBe(true, {
|
||||||
|
message: `There should be a connector between task ${masterTaskId} from group user ${masterTaskUserId} and task ${taskId} from group user ${taskUserId}.`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const connector = connectorMap.get(testKey);
|
||||||
|
const connectorEl = getConnector(connector.id);
|
||||||
|
expect(connectorEl).not.toBe(null);
|
||||||
|
const connectorStroke = queryFirst(SELECTORS.connectorStroke, { root: connectorEl });
|
||||||
|
expect(connectorStroke).toHaveAttribute("stroke", COLORS[colorCode].color);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(testMap).toHaveLength(connectorMap.size);
|
||||||
|
expect(SELECTORS.connector).toHaveCount(testMap.size);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connectors are correctly rendered.", async () => {
|
||||||
|
patchWithCleanup(GanttRenderer.prototype, {
|
||||||
|
shouldRenderRecordConnectors(record) {
|
||||||
|
return record.id !== 1;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ProjectTask._records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Task 1",
|
||||||
|
planned_date_begin: "2021-10-11 18:30:00",
|
||||||
|
date_deadline: "2021-10-11 19:29:59",
|
||||||
|
user_ids: [1],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
planned_date_begin: "2021-10-12 11:30:00",
|
||||||
|
date_deadline: "2021-10-12 12:29:59",
|
||||||
|
user_ids: [1],
|
||||||
|
depend_on_ids: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Task 3",
|
||||||
|
planned_date_begin: "2021-10-13 06:30:00",
|
||||||
|
date_deadline: "2021-10-13 07:29:59",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [1, 2],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const view = await mountGanttView(ganttViewParams);
|
||||||
|
const renderer = findComponent(view, (c) => c instanceof GanttRenderer);
|
||||||
|
const connectorMap = getConnectorMap(renderer);
|
||||||
|
expect([...connectorMap.keys()]).toEqual(["[2,1,3,false]"], {
|
||||||
|
message: "The only rendered connector should be the one from task_id 2 to task_id 3",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connectors are correctly computed and rendered when consolidation is active.", async () => {
|
||||||
|
ProjectTask._records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Task 1",
|
||||||
|
planned_date_begin: "2021-10-11 18:30:00",
|
||||||
|
date_deadline: "2021-10-11 19:29:59",
|
||||||
|
user_ids: [1],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
planned_date_begin: "2021-10-12 11:30:00",
|
||||||
|
date_deadline: "2021-10-12 12:29:59",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Task 3",
|
||||||
|
planned_date_begin: "2021-10-13 06:30:00",
|
||||||
|
date_deadline: "2021-10-13 07:29:59",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Task 4",
|
||||||
|
planned_date_begin: "2021-10-14 22:30:00",
|
||||||
|
date_deadline: "2021-10-14 23:29:59",
|
||||||
|
user_ids: [2, 3],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Task 5",
|
||||||
|
planned_date_begin: "2021-10-15 01:53:10",
|
||||||
|
date_deadline: "2021-10-15 02:34:34",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Task 6",
|
||||||
|
planned_date_begin: "2021-10-16 23:00:00",
|
||||||
|
date_deadline: "2021-10-16 23:21:01",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [4, 5],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Task 7",
|
||||||
|
planned_date_begin: "2021-10-17 10:30:12",
|
||||||
|
date_deadline: "2021-10-17 11:29:59",
|
||||||
|
user_ids: [1, 2, 3],
|
||||||
|
depend_on_ids: [6],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Task 8",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-18 07:29:59",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [7],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "Task 9",
|
||||||
|
planned_date_begin: "2021-10-19 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [8],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "Task 10",
|
||||||
|
planned_date_begin: "2021-10-19 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: "Task 11",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-18 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [10],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
name: "Task 12",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
name: "Task 13",
|
||||||
|
planned_date_begin: "2021-10-18 07:29:59",
|
||||||
|
date_deadline: "2021-10-20 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [12],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await mountGanttView({
|
||||||
|
...ganttViewParams,
|
||||||
|
arch: /* xml */ `<gantt date_start="planned_date_begin" date_stop="date_deadline" default_scale="month" dependency_field="depend_on_ids" consolidation_max="{'user_ids': 100 }"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// groups have been created of r
|
||||||
|
expect(".o_gantt_row_header.o_gantt_group.o_group_open").toHaveCount(4);
|
||||||
|
|
||||||
|
function getGroupRow(index) {
|
||||||
|
return queryAll(".o_gantt_row_header.o_gantt_group")[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(SELECTORS.connector).toHaveCount(22);
|
||||||
|
|
||||||
|
await contains(getGroupRow(1)).click();
|
||||||
|
expect(getGroupRow(1)).not.toHaveClass("o_group_open");
|
||||||
|
expect(SELECTORS.connector).toHaveCount(13);
|
||||||
|
|
||||||
|
await contains(getGroupRow(1)).click();
|
||||||
|
expect(SELECTORS.connector).toHaveCount(22);
|
||||||
|
|
||||||
|
await contains(getGroupRow(1)).click();
|
||||||
|
expect(SELECTORS.connector).toHaveCount(13);
|
||||||
|
|
||||||
|
await contains(getGroupRow(2)).click();
|
||||||
|
expect(SELECTORS.connector).toHaveCount(6);
|
||||||
|
|
||||||
|
await contains(getGroupRow(0)).click();
|
||||||
|
expect(SELECTORS.connector).toHaveCount(4);
|
||||||
|
|
||||||
|
await contains(getGroupRow(3)).click();
|
||||||
|
expect(SELECTORS.connector).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector hovered state is triggered and color is set accordingly.", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
expect(getConnector(1)).not.toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
expect(queryFirst(SELECTORS.connectorStroke, { root: getConnector(1) })).toHaveAttribute(
|
||||||
|
"stroke",
|
||||||
|
COLORS.default.color
|
||||||
|
);
|
||||||
|
|
||||||
|
await hover(getConnector(1));
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(getConnector(1)).toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
expect(queryFirst(SELECTORS.connectorStroke, { root: getConnector(1) })).toHaveAttribute(
|
||||||
|
"stroke",
|
||||||
|
COLORS.default.highlightedColor
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Buttons are displayed when hovering a connector.", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: getConnector(1) })).toHaveCount(0);
|
||||||
|
|
||||||
|
await hover(getConnector(1));
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: getConnector(1) })).toHaveCount(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Buttons are displayed when hovering a connector after a pill has been hovered.", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: getConnector(1) })).toHaveCount(0);
|
||||||
|
|
||||||
|
await hover(getPill("Task 1"));
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: getConnector(1) })).toHaveCount(0);
|
||||||
|
expect(getConnector(1)).toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
|
||||||
|
await hover(getConnector(1));
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(getConnector(1)).toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: getConnector(1) })).toHaveCount(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector buttons: remove a dependency", async () => {
|
||||||
|
onRpc(({ method, model, args }) => {
|
||||||
|
if (model === "project.task" && ["web_gantt_reschedule", "write"].includes(method)) {
|
||||||
|
expect.step([method, args]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
await clickConnectorButton(getConnector(1), "remove");
|
||||||
|
expect.verifySteps([["write", [[2], { depend_on_ids: [[3, 1, false]] }]]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector buttons: reschedule task backward date.", async () => {
|
||||||
|
onRpc(({ method, model, args }) => {
|
||||||
|
if (model === "project.task" && ["web_gantt_reschedule", "write"].includes(method)) {
|
||||||
|
expect.step([method, args]);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
await clickConnectorButton(getConnector(1), "reschedule-backward");
|
||||||
|
expect.verifySteps([
|
||||||
|
[
|
||||||
|
"web_gantt_reschedule",
|
||||||
|
["backward", 1, 2, "depend_on_ids", null, "planned_date_begin", "date_deadline"],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector buttons: reschedule task forward date.", async () => {
|
||||||
|
onRpc(({ args, method, model }) => {
|
||||||
|
if (model === "project.task" && ["web_gantt_reschedule", "write"].includes(method)) {
|
||||||
|
expect.step([method, args]);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
await clickConnectorButton(getConnector(1), "reschedule-forward");
|
||||||
|
expect.verifySteps([
|
||||||
|
[
|
||||||
|
"web_gantt_reschedule",
|
||||||
|
["forward", 1, 2, "depend_on_ids", null, "planned_date_begin", "date_deadline"],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector buttons: reschedule task start backward, different data.", async () => {
|
||||||
|
onRpc(({ method, model, args }) => {
|
||||||
|
if (model === "project.task" && ["web_gantt_reschedule", "write"].includes(method)) {
|
||||||
|
expect.step([method, args]);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
await clickConnectorButton(getConnector(1), "reschedule-backward");
|
||||||
|
expect.verifySteps([
|
||||||
|
[
|
||||||
|
"web_gantt_reschedule",
|
||||||
|
["backward", 1, 2, "depend_on_ids", null, "planned_date_begin", "date_deadline"],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector buttons: reschedule task forward, different data.", async () => {
|
||||||
|
onRpc(({ method, model, args }) => {
|
||||||
|
if (model === "project.task" && ["web_gantt_reschedule", "write"].includes(method)) {
|
||||||
|
expect.step([method, args]);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
await clickConnectorButton(getConnector(1), "reschedule-forward");
|
||||||
|
expect.verifySteps([
|
||||||
|
[
|
||||||
|
"web_gantt_reschedule",
|
||||||
|
["forward", 1, 2, "depend_on_ids", null, "planned_date_begin", "date_deadline"],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Hovering a task pill should highlight related tasks and dependencies", async () => {
|
||||||
|
/** @type {Map<ConnectorTaskIds, boolean>} */
|
||||||
|
const testMap = new Map([
|
||||||
|
["[1,1,2,1]", true],
|
||||||
|
["[1,1,2,3]", true],
|
||||||
|
["[2,1,3,false]", true],
|
||||||
|
["[2,3,3,false]", true],
|
||||||
|
["[2,1,4,2]", true],
|
||||||
|
["[2,3,4,3]", true],
|
||||||
|
["[10,2,11,2]", false],
|
||||||
|
]);
|
||||||
|
|
||||||
|
ProjectTask._records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Task 1",
|
||||||
|
planned_date_begin: "2021-10-10 18:30:00",
|
||||||
|
date_deadline: "2021-10-11 19:29:59",
|
||||||
|
user_ids: [1],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
planned_date_begin: "2021-10-12 11:30:00",
|
||||||
|
date_deadline: "2021-10-12 12:29:59",
|
||||||
|
user_ids: [1, 3],
|
||||||
|
depend_on_ids: [1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Task 3",
|
||||||
|
planned_date_begin: "2021-10-13 06:30:00",
|
||||||
|
date_deadline: "2021-10-13 07:29:59",
|
||||||
|
user_ids: [],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Task 4",
|
||||||
|
planned_date_begin: "2021-10-14 22:30:00",
|
||||||
|
date_deadline: "2021-10-14 23:29:59",
|
||||||
|
user_ids: [2, 3],
|
||||||
|
depend_on_ids: [2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "Task 10",
|
||||||
|
planned_date_begin: "2021-10-19 06:30:12",
|
||||||
|
date_deadline: "2021-10-19 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
display_warning_dependency_in_gantt: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: "Task 11",
|
||||||
|
planned_date_begin: "2021-10-18 06:30:12",
|
||||||
|
date_deadline: "2021-10-18 07:29:59",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [10],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const view = await mountGanttView(ganttViewParams);
|
||||||
|
const renderer = findComponent(view, (c) => c instanceof GanttRenderer);
|
||||||
|
|
||||||
|
const connectorMap = getConnectorMap(renderer);
|
||||||
|
const pills = [];
|
||||||
|
for (const wrapper of queryAll(SELECTORS.pillWrapper)) {
|
||||||
|
const pillId = wrapper.dataset.pillId;
|
||||||
|
pills.push({
|
||||||
|
el: queryFirst(SELECTORS.pill, { root: wrapper }),
|
||||||
|
recordId: renderer.pills[pillId].record.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const task2Pills = pills.filter((p) => p.recordId === 2);
|
||||||
|
|
||||||
|
expect(task2Pills).toHaveLength(2);
|
||||||
|
expect(CLASSES.highlightedPill).toHaveCount(0);
|
||||||
|
|
||||||
|
// Check that all connectors are not in hover state.
|
||||||
|
for (const testKey of testMap.keys()) {
|
||||||
|
expect(getConnector(connectorMap.get(testKey).id)).not.toHaveClass(
|
||||||
|
CLASSES.highlightedConnector
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await contains(getPill("Task 2", { nth: 1 })).hover();
|
||||||
|
// Both pills should be highlighted
|
||||||
|
expect(getPillWrapper("Task 2", { nth: 1 })).toHaveClass(CLASSES.highlightedPill);
|
||||||
|
expect(getPillWrapper("Task 2", { nth: 2 })).toHaveClass(CLASSES.highlightedPill);
|
||||||
|
|
||||||
|
// The rest of the pills should not be highlighted nor display connector creators
|
||||||
|
for (const { el, recordId } of pills) {
|
||||||
|
if (recordId !== 2) {
|
||||||
|
expect(el).not.toHaveClass(CLASSES.highlightedPill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all connectors are in the expected hover state.
|
||||||
|
for (const [testKey, shouldBeHighlighted] of testMap.entries()) {
|
||||||
|
const connector = getConnector(connectorMap.get(testKey).id);
|
||||||
|
if (shouldBeHighlighted) {
|
||||||
|
expect(connector).toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
} else {
|
||||||
|
expect(connector).not.toHaveClass(CLASSES.highlightedConnector);
|
||||||
|
}
|
||||||
|
expect(queryAll(SELECTORS.connectorStrokeButton, { root: connector })).toHaveCount(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Hovering a connector should cause the connected pills to get highlighted.", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
expect(SELECTORS.highlightedConnector).toHaveCount(0);
|
||||||
|
expect(SELECTORS.highlightedPill).toHaveCount(0);
|
||||||
|
|
||||||
|
await contains(getConnector(1)).hover();
|
||||||
|
expect(SELECTORS.highlightedConnector).toHaveCount(1);
|
||||||
|
expect(SELECTORS.highlightedPill).toHaveCount(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connectors are displayed behind pills, except on hover.", async () => {
|
||||||
|
const getZIndex = (el) => Number(getComputedStyle(el).zIndex) || 0;
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
expect(getZIndex(getPillWrapper("Task 2"))).toBeGreaterThan(getZIndex(getConnector(1)));
|
||||||
|
|
||||||
|
await contains(getConnector(1)).hover();
|
||||||
|
expect(getZIndex(getPillWrapper("Task 2"))).toBeLessThan(getZIndex(getConnector(1)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Create a connector from the gantt view.", async () => {
|
||||||
|
onRpc("write", ({ args, method }) => expect.step([method, args]));
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper);
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
await contains(
|
||||||
|
`${SELECTORS.connectorCreatorWrapper} ${SELECTORS.connectorCreatorBullet}:first`
|
||||||
|
).dragAndDrop(getPill("Task 2"));
|
||||||
|
expect.verifySteps([["write", [[2], { depend_on_ids: [[4, 3, false]] }]]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Create a connector from the gantt view: going fast", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
...ganttViewParams,
|
||||||
|
domain: [["id", "in", [1, 3]]],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper, {
|
||||||
|
root: getPillWrapper("Task 1"),
|
||||||
|
});
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
const connectorBullet = queryFirst(SELECTORS.connectorCreatorBullet, { root: rightWrapper });
|
||||||
|
const bulletRect = queryRect(connectorBullet);
|
||||||
|
const initialPosition = {
|
||||||
|
x: Math.floor(bulletRect.left + bulletRect.width / 2), // floor to avoid sub-pixel positioning
|
||||||
|
y: Math.floor(bulletRect.top + bulletRect.height / 2), // floor to avoid sub-pixel positioning
|
||||||
|
};
|
||||||
|
await pointerDown(connectorBullet, {
|
||||||
|
position: { clientX: initialPosition.x, clientY: initialPosition.y },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Here we simulate a fast move, using arbitrary values.
|
||||||
|
const currentPosition = {
|
||||||
|
x: Math.floor(initialPosition.x + 123), // floor to avoid sub-pixel positioning
|
||||||
|
y: Math.floor(initialPosition.y + 12), // floor to avoid sub-pixel positioning
|
||||||
|
};
|
||||||
|
await hover(SELECTORS.cellContainer, {
|
||||||
|
position: { clientX: currentPosition.x, clientY: currentPosition.y },
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
// Then we check that the connector stroke is correctly positioned.
|
||||||
|
const connectorStroke = queryOne(SELECTORS.connectorStroke, { root: getConnector("new") });
|
||||||
|
expect(connectorStroke).toHaveRect({
|
||||||
|
top: initialPosition.y,
|
||||||
|
right: currentPosition.x,
|
||||||
|
bottom: currentPosition.y,
|
||||||
|
left: initialPosition.x,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connectors should be rendered if connected pill is not visible", async () => {
|
||||||
|
// We first need to bump all the ids for users 2, 3 and 4 to make them disappear.
|
||||||
|
for (const record of ResUsers._records.slice(1)) {
|
||||||
|
record.id += 1000;
|
||||||
|
}
|
||||||
|
for (const record of ProjectTask._records) {
|
||||||
|
record.user_ids = record.user_ids.map((id) => (id > 1 ? id + 1000 : id));
|
||||||
|
}
|
||||||
|
// Generate a lot of users so that the connectors are far beyond the visible
|
||||||
|
// viewport, hence generating fake extra pills to render the connectors.
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
const id = 100 + i;
|
||||||
|
ResUsers._records.push({ id, name: `User ${id}` });
|
||||||
|
ProjectTask._records.push({
|
||||||
|
id,
|
||||||
|
name: `Task ${id}`,
|
||||||
|
planned_date_begin: "2021-10-11 18:30:00",
|
||||||
|
date_deadline: "2021-10-11 19:29:59",
|
||||||
|
user_ids: [id],
|
||||||
|
depend_on_ids: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ProjectTask._records[12].user_ids = [199];
|
||||||
|
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
expect(queryAll(SELECTORS.connector, { visible: true })).toHaveCount(13);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("No display of resize handles when creating a connector", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper);
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
// Creating a connector and hover another pill while dragging it
|
||||||
|
const { cancel, moveTo } = await contains(SELECTORS.connectorCreatorBullet, {
|
||||||
|
root: rightWrapper,
|
||||||
|
}).drag();
|
||||||
|
await moveTo(getPill("Task 2"));
|
||||||
|
|
||||||
|
expect(SELECTORS.resizeHandle).toHaveCount(0);
|
||||||
|
|
||||||
|
await cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Renderer in connect mode when creating a connector", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper);
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
// Creating a connector and hover another pill while dragging it
|
||||||
|
const { cancel, moveTo } = await contains(SELECTORS.connectorCreatorBullet, {
|
||||||
|
root: rightWrapper,
|
||||||
|
}).drag();
|
||||||
|
await moveTo(getPill("Task 2"));
|
||||||
|
|
||||||
|
expect(SELECTORS.renderer).toHaveClass("o_connect");
|
||||||
|
|
||||||
|
await cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector creators of initial pill are highlighted when creating a connector", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst`${SELECTORS.pillWrapper} ${SELECTORS.connectorCreatorWrapper}`;
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
// Creating a connector and hover another pill while dragging it
|
||||||
|
const { cancel, moveTo } = await contains(SELECTORS.connectorCreatorBullet, {
|
||||||
|
root: rightWrapper,
|
||||||
|
}).drag();
|
||||||
|
await moveTo(getPill("Task 2"));
|
||||||
|
|
||||||
|
expect(`${SELECTORS.pillWrapper}:first`).toHaveClass(CLASSES.lockedConnectorCreator);
|
||||||
|
|
||||||
|
await cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connector creators of hovered pill are highlighted when creating a connector", async () => {
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper);
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
// Creating a connector and hover another pill while dragging it
|
||||||
|
const { cancel, moveTo } = await contains(SELECTORS.connectorCreatorBullet, {
|
||||||
|
root: rightWrapper,
|
||||||
|
}).drag();
|
||||||
|
|
||||||
|
const destinationWrapper = getPillWrapper("Task 2");
|
||||||
|
const destinationPill = queryFirst(SELECTORS.pill, { root: destinationWrapper });
|
||||||
|
await moveTo(destinationPill);
|
||||||
|
|
||||||
|
// moveTo only triggers a pointerenter event on destination pill,
|
||||||
|
// a pointermove event is still needed to highlight it
|
||||||
|
await contains(destinationPill).hover();
|
||||||
|
expect(destinationWrapper).toHaveClass(CLASSES.highlightedConnectorCreator);
|
||||||
|
|
||||||
|
await cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Switch to full-size browser: the connections between pills should be diplayed", async () => {
|
||||||
|
await resize({ width: 375, height: 667 });
|
||||||
|
|
||||||
|
await mountGanttView(ganttViewParams);
|
||||||
|
|
||||||
|
// Mobile view
|
||||||
|
expect("svg.o_gantt_connector").toHaveCount(0, {
|
||||||
|
message: "Gantt connectors should not be visible in small/mobile view",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resizing browser to leave mobile view
|
||||||
|
await resize({ width: 1366, height: 768 });
|
||||||
|
await runAllTimers();
|
||||||
|
|
||||||
|
expect("svg.o_gantt_connector").toHaveCount(22, {
|
||||||
|
message: "Gantt connectors should be visible when switching to desktop view",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Connect two very distant pills", async () => {
|
||||||
|
ProjectTask._records = [
|
||||||
|
ProjectTask._records[0],
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
planned_date_begin: "2021-11-18 08:00:00",
|
||||||
|
date_deadline: "2021-11-18 16:00:00",
|
||||||
|
user_ids: [2],
|
||||||
|
depend_on_ids: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("write", ({ args }) => {
|
||||||
|
expect.step(JSON.stringify(args));
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
...ganttViewParams,
|
||||||
|
context: {
|
||||||
|
default_start_date: "2021-10-01",
|
||||||
|
default_stop_date: "2021-11-30",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(SELECTORS.connector).toHaveCount(0);
|
||||||
|
|
||||||
|
// Explicitly shows the connector creator wrapper since its "display: none"
|
||||||
|
// disappears on native CSS hover, which cannot be programatically emulated.
|
||||||
|
const rightWrapper = queryFirst(SELECTORS.connectorCreatorWrapper);
|
||||||
|
rightWrapper.classList.add("d-block");
|
||||||
|
|
||||||
|
// Creating a connector and hover another pill while dragging it
|
||||||
|
const { drop, moveTo } = await contains(SELECTORS.connectorCreatorBullet, {
|
||||||
|
root: rightWrapper,
|
||||||
|
}).drag();
|
||||||
|
|
||||||
|
const selector = `${SELECTORS.pill}:contains('Task 2')`;
|
||||||
|
expect(selector).toHaveCount(0);
|
||||||
|
await moveTo(SELECTORS.pill, { relative: true, position: { x: 1500 } });
|
||||||
|
await advanceFrame(200);
|
||||||
|
await drop(selector);
|
||||||
|
expect.verifySteps([`[[2],{"depend_on_ids":[[4,1,false]]}]`]);
|
||||||
|
expect(SELECTORS.connector).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { hover, queryFirst } from "@odoo/hoot-dom";
|
||||||
|
import { runAllTimers } from "@odoo/hoot-mock";
|
||||||
|
import { contains } from "@web/../tests/web_test_helpers";
|
||||||
|
import { SELECTORS } from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("@odoo/hoot-dom").Target} target
|
||||||
|
* @param {"remove" | "reschedule-forward" | "reschedule-backward"} button
|
||||||
|
*/
|
||||||
|
export async function clickConnectorButton(target, button) {
|
||||||
|
await hover(target);
|
||||||
|
await runAllTimers();
|
||||||
|
let element = null;
|
||||||
|
switch (button) {
|
||||||
|
case "remove": {
|
||||||
|
element = queryFirst(SELECTORS.connectorRemoveButton, { root: target });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "reschedule-backward": {
|
||||||
|
element = queryFirst(`${SELECTORS.connectorRescheduleButton}:first-of-type`, {
|
||||||
|
root: target,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "reschedule-forward": {
|
||||||
|
element = queryFirst(`${SELECTORS.connectorRescheduleButton}:last-of-type`, {
|
||||||
|
root: target,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return contains(element).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number | "new"} id
|
||||||
|
*/
|
||||||
|
export function getConnector(id) {
|
||||||
|
if (!/^__connector__/.test(id)) {
|
||||||
|
id = `__connector__${id}`;
|
||||||
|
}
|
||||||
|
return queryFirst(
|
||||||
|
`${SELECTORS.cellContainer} ${SELECTORS.connector}[data-connector-id='${id}']`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConnectorMap(renderer) {
|
||||||
|
/**
|
||||||
|
* @param {PillId} pillId
|
||||||
|
*/
|
||||||
|
const getIdAndUserIdFromPill = (pillId) => {
|
||||||
|
/** @type {[ResId, ResId]} */
|
||||||
|
const result = [renderer.pills[pillId]?.record.id || false, false];
|
||||||
|
if (result[0]) {
|
||||||
|
const pills = renderer.mappingRecordToPillsByRow[result[0]]?.pills;
|
||||||
|
if (pills) {
|
||||||
|
const pillEntry = Object.entries(pills).find((e) => e[1].id === pillId);
|
||||||
|
if (pillEntry) {
|
||||||
|
const [firstGroup] = JSON.parse(pillEntry[0]);
|
||||||
|
if (firstGroup.user_ids?.length) {
|
||||||
|
result[1] = firstGroup.user_ids[0] || false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {Map<ConnectorTaskIds, ConnectorProps>} */
|
||||||
|
const connectorMap = new Map();
|
||||||
|
for (const connector of Object.values(renderer.connectors)) {
|
||||||
|
const { sourcePillId, targetPillId } = renderer.mappingConnectorToPills[connector.id];
|
||||||
|
if (!sourcePillId || !targetPillId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const key = JSON.stringify([
|
||||||
|
...getIdAndUserIdFromPill(sourcePillId),
|
||||||
|
...getIdAndUserIdFromPill(targetPillId),
|
||||||
|
]);
|
||||||
|
connectorMap.set(key, connector);
|
||||||
|
}
|
||||||
|
return connectorMap;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
import { defineModels, fields, models } from "@web/../tests/web_test_helpers";
|
||||||
|
|
||||||
|
export const TASKS_STAGE_SELECTION = [
|
||||||
|
["todo", "To Do"],
|
||||||
|
["in_progress", "In Progress"],
|
||||||
|
["done", "Done"],
|
||||||
|
["cancel", "Cancelled"],
|
||||||
|
];
|
||||||
|
|
||||||
|
export class Project extends models.Model {
|
||||||
|
name = fields.Char();
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{ id: 1, name: "Project 1" },
|
||||||
|
{ id: 2, name: "Project 2" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ResUsers extends models.Model {
|
||||||
|
_name = "res.users";
|
||||||
|
|
||||||
|
name = fields.Char();
|
||||||
|
|
||||||
|
has_group() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{ id: 1, name: "User 1" },
|
||||||
|
{ id: 2, name: "User 2" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Stage extends models.Model {
|
||||||
|
name = fields.Char();
|
||||||
|
sequence = fields.Integer();
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "in_progress",
|
||||||
|
sequence: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "todo",
|
||||||
|
sequence: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "cancel",
|
||||||
|
sequence: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "done",
|
||||||
|
sequence: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Tasks extends models.Model {
|
||||||
|
name = fields.Char();
|
||||||
|
start = fields.Datetime({ string: "Start Date" });
|
||||||
|
stop = fields.Datetime({ string: "Stop Date" });
|
||||||
|
allocated_hours = fields.Float({ string: "Allocated Hours" });
|
||||||
|
stage = fields.Selection({
|
||||||
|
selection: TASKS_STAGE_SELECTION,
|
||||||
|
});
|
||||||
|
color = fields.Integer();
|
||||||
|
progress = fields.Integer();
|
||||||
|
exclude = fields.Boolean({ string: "Excluded from Consolidation" });
|
||||||
|
project_id = fields.Many2one({ relation: "project" });
|
||||||
|
stage_id = fields.Many2one({ relation: "stage" });
|
||||||
|
user_id = fields.Many2one({ string: "Assign To", relation: "res.users" });
|
||||||
|
|
||||||
|
_records = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Task 1",
|
||||||
|
start: "2018-11-30 18:30:00",
|
||||||
|
stop: "2018-12-31 18:29:59",
|
||||||
|
stage: "todo",
|
||||||
|
stage_id: 1,
|
||||||
|
project_id: 1,
|
||||||
|
user_id: 1,
|
||||||
|
color: 0,
|
||||||
|
progress: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Task 2",
|
||||||
|
start: "2018-12-17 11:30:00",
|
||||||
|
stop: "2018-12-22 06:29:59",
|
||||||
|
stage: "done",
|
||||||
|
stage_id: 4,
|
||||||
|
project_id: 1,
|
||||||
|
user_id: 2,
|
||||||
|
color: 2,
|
||||||
|
progress: 30,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Task 3",
|
||||||
|
start: "2018-12-27 06:30:00",
|
||||||
|
stop: "2019-01-03 06:29:59",
|
||||||
|
stage: "cancel",
|
||||||
|
stage_id: 3,
|
||||||
|
project_id: 1,
|
||||||
|
user_id: 2,
|
||||||
|
color: 10,
|
||||||
|
progress: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Task 4",
|
||||||
|
start: "2018-12-20 02:30:00",
|
||||||
|
stop: "2018-12-20 06:29:59",
|
||||||
|
stage: "in_progress",
|
||||||
|
stage_id: 3,
|
||||||
|
project_id: 1,
|
||||||
|
user_id: 1,
|
||||||
|
color: 1,
|
||||||
|
exclude: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Task 5",
|
||||||
|
start: "2018-11-08 01:53:10",
|
||||||
|
stop: "2018-12-04 01:34:34",
|
||||||
|
stage: "done",
|
||||||
|
stage_id: 2,
|
||||||
|
project_id: 2,
|
||||||
|
user_id: 1,
|
||||||
|
color: 2,
|
||||||
|
progress: 100,
|
||||||
|
exclude: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Task 6",
|
||||||
|
start: "2018-11-19 23:00:00",
|
||||||
|
stop: "2018-11-20 04:21:01",
|
||||||
|
stage: "in_progress",
|
||||||
|
stage_id: 4,
|
||||||
|
project_id: 2,
|
||||||
|
user_id: 1,
|
||||||
|
color: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Task 7",
|
||||||
|
start: "2018-12-20 12:30:12",
|
||||||
|
stop: "2018-12-20 18:29:59",
|
||||||
|
stage: "cancel",
|
||||||
|
stage_id: 1,
|
||||||
|
project_id: 2,
|
||||||
|
user_id: 2,
|
||||||
|
color: 10,
|
||||||
|
progress: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Task 8",
|
||||||
|
start: "2020-03-28 06:30:12",
|
||||||
|
stop: "2020-03-28 18:29:59",
|
||||||
|
stage: "in_progress",
|
||||||
|
stage_id: 1,
|
||||||
|
project_id: 2,
|
||||||
|
user_id: 2,
|
||||||
|
color: 10,
|
||||||
|
progress: 80,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
_views = {
|
||||||
|
search: /* xml */ `<search />`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defineGanttModels() {
|
||||||
|
defineModels([Stage, Project, ResUsers, Tasks]);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { makeKwArgs } from "@web/../tests/web_test_helpers";
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
|
||||||
|
function _mockGetGanttData({ kwargs, model }) {
|
||||||
|
kwargs = makeKwArgs(kwargs);
|
||||||
|
const lazy = !kwargs.limit && !kwargs.offset && kwargs.groupby.length === 1;
|
||||||
|
const { groups, length } = this.env[model].web_read_group({
|
||||||
|
...kwargs,
|
||||||
|
lazy,
|
||||||
|
fields: ["__record_ids:array_agg(id)"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const recordIds = [];
|
||||||
|
for (const group of groups) {
|
||||||
|
recordIds.push(...(group.__record_ids || []));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { records } = this.env[model].web_search_read(
|
||||||
|
[["id", "in", recordIds]],
|
||||||
|
kwargs.read_specification,
|
||||||
|
makeKwArgs({ context: kwargs.context })
|
||||||
|
);
|
||||||
|
|
||||||
|
const unavailabilities = {};
|
||||||
|
for (const fieldName of kwargs.unavailability_fields || []) {
|
||||||
|
unavailabilities[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress_bars = {};
|
||||||
|
for (const fieldName of kwargs.progress_bar_fields || []) {
|
||||||
|
progress_bars[fieldName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { groups, length, records, unavailabilities, progress_bars };
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.category("mock_rpc").add("get_gantt_data", _mockGetGanttData);
|
||||||
|
|
@ -0,0 +1,527 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import { mockDate } from "@odoo/hoot-mock";
|
||||||
|
import { onRpc } from "@web/../tests/web_test_helpers";
|
||||||
|
import { defineGanttModels } from "./gantt_mock_models";
|
||||||
|
import {
|
||||||
|
SELECTORS,
|
||||||
|
getCellColorProperties,
|
||||||
|
getGridContent,
|
||||||
|
mountGanttView,
|
||||||
|
} from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
describe.current.tags("desktop");
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
beforeEach(() => mockDate("2018-12-20T08:00:00", +1));
|
||||||
|
|
||||||
|
test("empty sparse gantt", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" />`,
|
||||||
|
domain: [["id", "=", 0]],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(34);
|
||||||
|
expect(rows).toEqual([{ title: "" }]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" />`,
|
||||||
|
domain: [["id", "=", 1]],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(34);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse grouped gantt", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" />`,
|
||||||
|
groupBy: ["stage"],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(34);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "To Do",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "In Progress",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Done",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Cancelled",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt with consolidation", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
consolidation="progress"
|
||||||
|
consolidation_max="{'user_id': 100}"
|
||||||
|
display_mode="sparse"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["stage"],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(34);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "To Do",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "In Progress",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Done",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Cancelled",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt with a group expand", async () => {
|
||||||
|
onRpc("get_gantt_data", () => {
|
||||||
|
return {
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
stage: "todo",
|
||||||
|
__record_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stage: "in_progress",
|
||||||
|
__record_ids: [4],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
length: 2,
|
||||||
|
records: [
|
||||||
|
{
|
||||||
|
display_name: "Task 4",
|
||||||
|
id: 4,
|
||||||
|
progress: 0,
|
||||||
|
stage: "in_progress",
|
||||||
|
start: "2018-12-20 02:30:00",
|
||||||
|
stop: "2018-12-20 06:29:59",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
display_mode="sparse"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["stage"],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(34);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
title: "To Do",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "In Progress",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("empty sparse gantt with unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 23:00:00",
|
||||||
|
stop: "2018-12-19 23:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", async ({ parent, kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.unavailability_fields).toEqual([]);
|
||||||
|
result.unavailabilities.__default = { false: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" display_unavailability="1" />`,
|
||||||
|
domain: [["id", "=", 0]],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt with unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 23:00:00",
|
||||||
|
stop: "2018-12-19 23:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", async ({ parent, kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.unavailability_fields).toEqual([]);
|
||||||
|
result.unavailabilities.__default = { false: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" display_unavailability="1" />`,
|
||||||
|
domain: [["id", "=", 1]],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse grouped gantt with unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 23:00:00",
|
||||||
|
stop: "2018-12-19 23:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", async ({ parent, kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.unavailability_fields).toEqual(["user_id"]);
|
||||||
|
result.unavailabilities.user_id = { 1: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_mode="sparse" display_unavailability="1" />`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 December 2018", "Task 5")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt with consolidation with unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 23:00:00",
|
||||||
|
stop: "2018-12-19 23:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", async ({ parent, kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.unavailability_fields).toEqual(["user_id"]);
|
||||||
|
result.unavailabilities.user_id = { 1: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
consolidation="progress"
|
||||||
|
consolidation_max="{'user_id': 100}"
|
||||||
|
display_mode="sparse"
|
||||||
|
display_unavailability="1"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 December 2018", "", { num: 2 })).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sparse gantt with a group expand and unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 23:00:00",
|
||||||
|
stop: "2018-12-19 23:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", ({ kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
expect(kwargs.unavailability_fields).toEqual(["user_id"]);
|
||||||
|
return {
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
user_id: [1, "Charles"],
|
||||||
|
__record_ids: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user_id: [2, "Louis"],
|
||||||
|
__record_ids: [4],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
length: 2,
|
||||||
|
records: [
|
||||||
|
{
|
||||||
|
display_name: "Task 4",
|
||||||
|
id: 4,
|
||||||
|
progress: 0,
|
||||||
|
user_id: 1,
|
||||||
|
start: "2018-12-20 02:30:00",
|
||||||
|
stop: "2018-12-20 06:29:59",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
unavailabilities: {
|
||||||
|
user_id: { 1: unavailabilities, 2: [] },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
display_mode="sparse"
|
||||||
|
display_unavailability="1"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
expect(getCellColorProperties("19 December 2018", "", { num: 2 })).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,986 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import { click, leave, queryAll, queryOne, queryFirst } from "@odoo/hoot-dom";
|
||||||
|
import { animationFrame, mockDate } from "@odoo/hoot-mock";
|
||||||
|
import { contains, defineParams, onRpc } from "@web/../tests/web_test_helpers";
|
||||||
|
import { Tasks, defineGanttModels } from "./gantt_mock_models";
|
||||||
|
import {
|
||||||
|
SELECTORS,
|
||||||
|
clickCell,
|
||||||
|
getActiveScale,
|
||||||
|
getCell,
|
||||||
|
getCellColorProperties,
|
||||||
|
getGridContent,
|
||||||
|
getPill,
|
||||||
|
getPillWrapper,
|
||||||
|
hoverGridCell,
|
||||||
|
mountGanttView,
|
||||||
|
resizePill,
|
||||||
|
} from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
describe.current.tags("desktop");
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
beforeEach(() => {
|
||||||
|
mockDate("2018-12-20T07:00:00", +1);
|
||||||
|
defineParams({
|
||||||
|
lang_parameters: {
|
||||||
|
time_format: "%I:%M:%S",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("create attribute", async () => {
|
||||||
|
Tasks._views.list = `<list><field name="name"/></list>`;
|
||||||
|
Tasks._views.search = `<search><field name="name"/></search>`;
|
||||||
|
onRpc("has_group", () => true);
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" create="0"/>`,
|
||||||
|
});
|
||||||
|
expect(".o_dialog").toHaveCount(0);
|
||||||
|
await hoverGridCell("06 December 2018");
|
||||||
|
await clickCell("06 December 2018");
|
||||||
|
expect(".o_dialog").toHaveCount(1);
|
||||||
|
expect(".modal-title").toHaveText("Plan");
|
||||||
|
expect(".o_create_button").toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("plan attribute", async () => {
|
||||||
|
Tasks._views.form = `<form><field name="name"/></form>`;
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" plan="0"/>`,
|
||||||
|
});
|
||||||
|
expect(".o_dialog").toHaveCount(0);
|
||||||
|
await hoverGridCell("06 December 2018");
|
||||||
|
await clickCell("06 December 2018");
|
||||||
|
expect(".o_dialog").toHaveCount(1);
|
||||||
|
expect(".modal-title").toHaveText("Create");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("edit attribute", async () => {
|
||||||
|
Tasks._views.form = `<form><field name="name"/></form>`;
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" edit="0"/>`,
|
||||||
|
});
|
||||||
|
expect(SELECTORS.resizable).toHaveCount(0);
|
||||||
|
expect(SELECTORS.draggable).toHaveCount(0);
|
||||||
|
expect(getGridContent().rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
title: "Task 5",
|
||||||
|
level: 0,
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{ title: "Task 1", level: 1, colSpan: "Out of bounds (1) -> 31 December 2018" },
|
||||||
|
{
|
||||||
|
title: "Task 2",
|
||||||
|
level: 0,
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 4",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 7",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
},
|
||||||
|
{ title: "Task 3", level: 0, colSpan: "27 December 2018 -> 03 (1/2) January 2019" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await contains(getPill("Task 1")).click();
|
||||||
|
expect(`.o_popover button.btn-primary`).toHaveText(/view/i);
|
||||||
|
await contains(`.o_popover button.btn-primary`).click();
|
||||||
|
expect(".modal .o_form_readonly").toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("total_row attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" total_row="1"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows } = getGridContent();
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
title: "Task 5",
|
||||||
|
level: 0,
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{ title: "Task 1", level: 1, colSpan: "Out of bounds (1) -> 31 December 2018" },
|
||||||
|
{
|
||||||
|
title: "Task 2",
|
||||||
|
level: 0,
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 4",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 7",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
},
|
||||||
|
{ title: "Task 3", level: 0, colSpan: "27 December 2018 -> 03 (1/2) January 2019" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isTotalRow: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "04 (1/2) December 2018 -> 17 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 19 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "21 December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "22 (1/2) December 2018 -> 26 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "01 January 2019 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("default_scale attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_scale="day"/>`,
|
||||||
|
});
|
||||||
|
expect(getActiveScale()).toBe(5); // day scale
|
||||||
|
const { columnHeaders, range } = getGridContent();
|
||||||
|
expect(range).toBe("From: 12/20/2018 to: 12/22/2018");
|
||||||
|
expect(columnHeaders).toHaveLength(38);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("scales attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" scales="month,day,trololo"/>`,
|
||||||
|
});
|
||||||
|
expect(queryOne(".o_gantt_renderer_controls input").max).toBe("1", {
|
||||||
|
message: "there are only 2 valid scales (starting from 0)",
|
||||||
|
});
|
||||||
|
expect(getActiveScale()).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("precision attribute", async () => {
|
||||||
|
onRpc("write", ({ args }) => expect.step(args));
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
precision="{'day': 'hour:quarter', 'week': 'day:half', 'month': 'day', 'year': 'month:quarter'}"
|
||||||
|
default_scale="day"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
domain: [["id", "=", 7]],
|
||||||
|
});
|
||||||
|
|
||||||
|
// resize of a quarter
|
||||||
|
const drop = await resizePill(getPillWrapper("Task 7"), "end", 0.25, false);
|
||||||
|
await animationFrame();
|
||||||
|
expect(SELECTORS.resizeBadge).toHaveText("+15 minutes");
|
||||||
|
|
||||||
|
// manually trigger the drop to trigger a write
|
||||||
|
await drop();
|
||||||
|
await animationFrame();
|
||||||
|
expect(SELECTORS.resizeBadge).toHaveCount(0);
|
||||||
|
expect.verifySteps([[[7], { stop: "2018-12-20 18:44:59" }]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("progress attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt string="Tasks" date_start="start" date_stop="stop" progress="progress"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
});
|
||||||
|
expect(`${SELECTORS.pill} .o_gantt_progress`).toHaveCount(3);
|
||||||
|
expect(
|
||||||
|
queryAll(SELECTORS.pill).map((el) => ({
|
||||||
|
text: el.innerText,
|
||||||
|
progress: el.querySelector(".o_gantt_progress")?.style?.width || null,
|
||||||
|
}))
|
||||||
|
).toEqual([
|
||||||
|
{ text: "Task 1", progress: null },
|
||||||
|
{ text: "Task 2", progress: "30%" },
|
||||||
|
{ text: "Task 4", progress: null },
|
||||||
|
{ text: "Task 3", progress: "60%" },
|
||||||
|
{ text: "Task 7", progress: "80%" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("form_view_id attribute", async () => {
|
||||||
|
Tasks._views[["form", 42]] = `<form><field name="name"/></form>`;
|
||||||
|
onRpc("get_views", ({ kwargs }) => expect.step(["get_views", kwargs.views]));
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt string="Tasks" date_start="start" date_stop="stop" form_view_id="42"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
});
|
||||||
|
await contains(queryFirst(SELECTORS.addButton + ":visible")).click();
|
||||||
|
expect(".modal .o_form_view").toHaveCount(1);
|
||||||
|
expect.verifySteps([
|
||||||
|
[
|
||||||
|
"get_views",
|
||||||
|
[
|
||||||
|
[123456789, "gantt"],
|
||||||
|
[987654321, "search"],
|
||||||
|
],
|
||||||
|
], // initial get_views
|
||||||
|
["get_views", [[42, "form"]]], // get_views when form view dialog opens
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("decoration attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt date_start="start" date_stop="stop" decoration-info="stage == 'todo'">
|
||||||
|
<field name="stage"/>
|
||||||
|
'</gantt>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(getPill("Task 1")).toHaveClass("decoration-info");
|
||||||
|
expect(getPill("Task 2")).not.toHaveClass("decoration-info");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("decoration attribute with date", async () => {
|
||||||
|
mockDate("2018-12-19T12:00:00");
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" decoration-danger="start < today"/>`,
|
||||||
|
});
|
||||||
|
expect(getPill("Task 1")).toHaveClass("decoration-danger");
|
||||||
|
expect(getPill("Task 2")).toHaveClass("decoration-danger");
|
||||||
|
expect(getPill("Task 5")).toHaveClass("decoration-danger");
|
||||||
|
expect(getPill("Task 3")).not.toHaveClass("decoration-danger");
|
||||||
|
expect(getPill("Task 4")).not.toHaveClass("decoration-danger");
|
||||||
|
expect(getPill("Task 7")).not.toHaveClass("decoration-danger");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("consolidation feature", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
consolidation="progress"
|
||||||
|
consolidation_max="{'user_id': 100}"
|
||||||
|
consolidation_exclude="exclude"
|
||||||
|
progress="progress"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["user_id", "project_id", "stage"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows } = getGridContent();
|
||||||
|
expect(rows).toHaveLength(18);
|
||||||
|
expect(rows.filter((r) => r.isGroup)).toHaveLength(12);
|
||||||
|
expect(".o_gantt_row_headers").toHaveCount(1);
|
||||||
|
|
||||||
|
// Check grouped rows
|
||||||
|
expect(rows[0].isGroup).toBe(true);
|
||||||
|
expect(rows[0].title).toBe("User 1");
|
||||||
|
expect(rows[9].isGroup).toBe(true);
|
||||||
|
expect(rows[9].title).toBe("User 2");
|
||||||
|
|
||||||
|
// Consolidation
|
||||||
|
// 0 over the size of Task 5 (Task 5 is 100 but is excluded!) then 0 over the rest of Task 1, cut by Task 4 which has progress 0
|
||||||
|
expect(rows[0].pills).toEqual([
|
||||||
|
{ colSpan: "Out of bounds (8) -> 19 December 2018", title: "0" },
|
||||||
|
{ colSpan: "20 December 2018 -> 20 (1/2) December 2018", title: "0" },
|
||||||
|
{ colSpan: "20 (1/2) December 2018 -> 31 December 2018", title: "0" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 30 over Task 2 until Task 7 then 110 (Task 2 (30) + Task 7 (80)) then 30 again until end of task 2 then 60 over Task 3
|
||||||
|
expect(rows[9].pills).toEqual([
|
||||||
|
{ colSpan: "17 (1/2) December 2018 -> 20 (1/2) December 2018", title: "30" },
|
||||||
|
{ colSpan: "20 (1/2) December 2018 -> 20 December 2018", title: "110" },
|
||||||
|
{ colSpan: "21 December 2018 -> 22 (1/2) December 2018", title: "30" },
|
||||||
|
{ colSpan: "27 December 2018 -> 03 (1/2) January 2019", title: "60" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const withStatus = [];
|
||||||
|
for (const el of queryAll(".o_gantt_consolidated_pill")) {
|
||||||
|
if (el.classList.contains("bg-success") || el.classList.contains("bg-danger")) {
|
||||||
|
withStatus.push({
|
||||||
|
title: el.title,
|
||||||
|
danger: el.classList.contains("border-danger"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(withStatus).toEqual([
|
||||||
|
{ title: "0", danger: false },
|
||||||
|
{ title: "0", danger: false },
|
||||||
|
{ title: "0", danger: false },
|
||||||
|
{ title: "30", danger: false },
|
||||||
|
{ title: "110", danger: true },
|
||||||
|
{ title: "30", danger: false },
|
||||||
|
{ title: "60", danger: false },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("consolidation feature (single level)", async () => {
|
||||||
|
Tasks._views.form = `
|
||||||
|
<form>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="start"/>
|
||||||
|
<field name="stop"/>
|
||||||
|
<field name="project_id"/>
|
||||||
|
</form>
|
||||||
|
`;
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" consolidation="progress" consolidation_max="{'user_id': 100}" consolidation_exclude="exclude"/>`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows, range } = getGridContent();
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(".o_gantt_button_expand_rows").toHaveCount(1);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (8) -> 19 December 2018",
|
||||||
|
title: "0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 31 December 2018",
|
||||||
|
title: "0",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "User 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
title: "110",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "21 December 2018 -> 22 (1/2) December 2018",
|
||||||
|
title: "30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
title: "60",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "User 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("color attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" color="color"/>`,
|
||||||
|
});
|
||||||
|
expect(getPill("Task 1")).toHaveClass("o_gantt_color_0");
|
||||||
|
expect(getPill("Task 2")).toHaveClass("o_gantt_color_2");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("color attribute in multi-level grouped", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" color="color"/>`,
|
||||||
|
groupBy: ["user_id", "project_id"],
|
||||||
|
domain: [["id", "=", 1]],
|
||||||
|
});
|
||||||
|
expect(`${SELECTORS.pill}.o_gantt_consolidated_pill`).not.toHaveClass("o_gantt_color_0");
|
||||||
|
expect(`${SELECTORS.pill}:not(.o_gantt_consolidated_pill)`).toHaveClass("o_gantt_color_0");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("color attribute on a many2one", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" color="project_id"/>`,
|
||||||
|
});
|
||||||
|
expect(getPill("Task 1")).toHaveClass("o_gantt_color_1");
|
||||||
|
expect(`${SELECTORS.pill}.o_gantt_color_1`).toHaveCount(4);
|
||||||
|
expect(`${SELECTORS.pill}.o_gantt_color_2`).toHaveCount(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Today style with unavailabilities ("week": "day:half")`, async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 10:00:00",
|
||||||
|
stop: "2018-12-20 14:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
onRpc("get_gantt_data", async ({ parent }) => {
|
||||||
|
const result = await parent();
|
||||||
|
result.unavailabilities.__default = { false: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="1" default_scale="week" scales="week" precision="{'week': 'day:half'}"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Normal day / unavailability
|
||||||
|
expect(getCellColorProperties("18 W51 2018")).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 W51 2018")).toEqual(["--Gantt__DayOff-background-color"]);
|
||||||
|
|
||||||
|
// Unavailability / today
|
||||||
|
expect(getCell("20 W51 2018")).toHaveClass("o_gantt_today");
|
||||||
|
expect(getCellColorProperties("20 W51 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOffToday-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Today style of group rows", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 10:00:00",
|
||||||
|
stop: "2018-12-20 14:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
Tasks._records = [Tasks._records[3]]; // id: 4
|
||||||
|
|
||||||
|
onRpc("get_gantt_data", async ({ parent }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
result.unavailabilities.project_id = { 1: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="1" default_scale="week" scales="week" precision="{'week': 'day:half'}"/>`,
|
||||||
|
groupBy: ["user_id", "project_id"],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
|
||||||
|
// Normal group cell: open
|
||||||
|
let cell4 = getCell("19 W51 2018");
|
||||||
|
expect(cell4).not.toHaveClass("o_gantt_today");
|
||||||
|
expect(cell4).toHaveClass("o_group_open");
|
||||||
|
expect(cell4).toHaveStyle({
|
||||||
|
backgroundImage: "linear-gradient(rgb(249, 250, 251), rgb(234, 237, 241))",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Today group cell: open
|
||||||
|
let cell5 = getCell("20 W51 2018");
|
||||||
|
expect(cell5).toHaveClass("o_gantt_today");
|
||||||
|
expect(cell5).toHaveClass("o_group_open");
|
||||||
|
expect(cell5).toHaveStyle({
|
||||||
|
backgroundImage: "linear-gradient(rgb(249, 250, 251), rgb(234, 237, 241))",
|
||||||
|
});
|
||||||
|
await contains(SELECTORS.group).click(); // fold group
|
||||||
|
await leave();
|
||||||
|
// Normal group cell: closed
|
||||||
|
cell4 = getCell("19 W51 2018");
|
||||||
|
expect(cell4).not.toHaveClass("o_gantt_today");
|
||||||
|
expect(cell4).not.toHaveClass("o_group_open");
|
||||||
|
expect(cell4).toHaveStyle({
|
||||||
|
backgroundImage: "linear-gradient(rgb(234, 237, 241), rgb(249, 250, 251))",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Today group cell: closed
|
||||||
|
cell5 = getCell("20 W51 2018");
|
||||||
|
expect(cell5).toHaveClass("o_gantt_today");
|
||||||
|
expect(cell5).not.toHaveClass("o_group_open");
|
||||||
|
expect(cell5).toHaveStyle({ backgroundImage: "none" });
|
||||||
|
expect(cell5).toHaveStyle({ backgroundColor: "rgb(252, 250, 243)" });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("style without unavailabilities", async () => {
|
||||||
|
mockDate("2018-12-05T02:00:00");
|
||||||
|
|
||||||
|
onRpc("get_gantt_data", ({ kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
expect(kwargs.unavailability_fields).toEqual([]);
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="1"/>`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
const cell5 = getCell("05 December 2018");
|
||||||
|
expect(cell5).toHaveClass("o_gantt_today");
|
||||||
|
expect(cell5).toHaveAttribute("style", "grid-column:c9/c11;grid-row:r1/r5;");
|
||||||
|
const cell6 = getCell("06 December 2018");
|
||||||
|
expect(cell6).toHaveAttribute("style", "grid-column:c11/c13;grid-row:r1/r5;");
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Unavailabilities ("month": "day:half")`, async () => {
|
||||||
|
mockDate("2018-12-05T02:00:00");
|
||||||
|
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-05 09:30:00",
|
||||||
|
stop: "2018-12-07 08:00:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: "2018-12-16 09:00:00",
|
||||||
|
stop: "2018-12-18 13:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", ({ model, kwargs, parent }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
expect(model).toBe("tasks");
|
||||||
|
expect(kwargs.unavailability_fields).toEqual([]);
|
||||||
|
expect(kwargs.start_date).toBe("2018-11-30 23:00:00");
|
||||||
|
expect(kwargs.stop_date).toBe("2019-02-28 23:00:00");
|
||||||
|
const result = parent();
|
||||||
|
result.unavailabilities = { __default: { false: unavailabilities } };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="1"/>`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
expect(getCell("05 December 2018")).toHaveClass("o_gantt_today");
|
||||||
|
expect(getCellColorProperties("05 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOffToday-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("06 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("07 December 2018")).toEqual([]);
|
||||||
|
expect(getCellColorProperties("16 December 2018")).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("17 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("18 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`Unavailabilities ("day": "hours:quarter")`, async () => {
|
||||||
|
Tasks._records = [];
|
||||||
|
const unavailabilities = [
|
||||||
|
// in utc
|
||||||
|
{
|
||||||
|
start: "2018-12-20 08:15:00",
|
||||||
|
stop: "2018-12-20 08:30:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: "2018-12-20 10:35:00",
|
||||||
|
stop: "2018-12-20 12:29:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: "2018-12-20 20:15:00",
|
||||||
|
stop: "2018-12-20 20:50:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", ({ kwargs, parent }) => {
|
||||||
|
expect(kwargs.unavailability_fields).toEqual([]);
|
||||||
|
const result = parent();
|
||||||
|
result.unavailabilities = { __default: { false: unavailabilities } };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="1" default_scale="day" scales="day" precision="{'day': 'hours:quarter'}"/>`,
|
||||||
|
});
|
||||||
|
expect(getCellColorProperties("9am 20 December 2018")).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("11am 20 December 2018")).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("12pm 20 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("1pm 20 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
]);
|
||||||
|
expect(getCellColorProperties("9pm 20 December 2018")).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("offset attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" offset="-4" default_scale="day"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { range } = getGridContent();
|
||||||
|
expect(range).toBe("From: 12/16/2018 to: 12/18/2018", {
|
||||||
|
message: "gantt view should be set to 4 days before initial date",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("default_group_by attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_group_by="user_id"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows } = getGridContent();
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
title: "User 1",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User 2",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("default_group_by attribute with groupBy", async () => {
|
||||||
|
// The default_group_by attribute should be ignored if a groupBy is given.
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_group_by="user_id"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows } = getGridContent();
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
title: "Project 1",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 2,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 2",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("default_group_by attribute with 2 fields", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_group_by="user_id,project_id"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rows } = getGridContent();
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
title: "User 1",
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (8) -> 19 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 31 December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 1",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 December 2018 -> 20 (1/2) December 2018",
|
||||||
|
level: 1,
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User 2",
|
||||||
|
isGroup: true,
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 20 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
title: "2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "21 December 2018 -> 22 (1/2) December 2018",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
title: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 1",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "27 December 2018 -> 03 (1/2) January 2019",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 2",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "20 (1/2) December 2018 -> 20 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("default_range attribute", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_range="day"/>`,
|
||||||
|
});
|
||||||
|
expect(getActiveScale()).toBe(2); // month scale
|
||||||
|
const { columnHeaders, range } = getGridContent();
|
||||||
|
expect(range).toBe("12/20/2018");
|
||||||
|
expect(columnHeaders).toHaveLength(1);
|
||||||
|
await click(SELECTORS.rangeMenuToggler);
|
||||||
|
await animationFrame();
|
||||||
|
const firstRangeMenuItem = queryFirst(`${SELECTORS.rangeMenu} .dropdown-item`);
|
||||||
|
expect(firstRangeMenuItem).toHaveClass("selected");
|
||||||
|
expect(firstRangeMenuItem).toHaveText("Today");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("consolidation and unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
{
|
||||||
|
start: "2018-12-18 10:00:00",
|
||||||
|
stop: "2018-12-20 14:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
onRpc("get_gantt_data", async ({ parent, kwargs }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.unavailability_fields).toEqual(["user_id"]);
|
||||||
|
result.unavailabilities.user_id = { 1: unavailabilities };
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt
|
||||||
|
date_start="start"
|
||||||
|
date_stop="stop"
|
||||||
|
consolidation="progress"
|
||||||
|
consolidation_max="{'user_id': 100}"
|
||||||
|
consolidation_exclude="exclude"
|
||||||
|
display_unavailability="1"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
// Normal day / unavailability
|
||||||
|
expect(getCellColorProperties("18 December 2018", "", { num: 2 })).toEqual([
|
||||||
|
"--Gantt__Day-background-color",
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Full unavailability
|
||||||
|
expect(getCellColorProperties("19 December 2018", "", { num: 2 })).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Unavailability / today
|
||||||
|
expect(getCell("20 December 2018")).toHaveClass("o_gantt_today");
|
||||||
|
expect(getCellColorProperties("20 December 2018", "", { num: 2 })).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
"--Gantt__DayOffToday-background-color",
|
||||||
|
]);
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,454 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import { Deferred, animationFrame, mockDate } from "@odoo/hoot-mock";
|
||||||
|
import { click } from "@odoo/hoot-dom";
|
||||||
|
import { onPatched } from "@odoo/owl";
|
||||||
|
import {
|
||||||
|
onRpc,
|
||||||
|
patchWithCleanup,
|
||||||
|
toggleMenuItem,
|
||||||
|
toggleSearchBarMenu,
|
||||||
|
} from "@web/../tests/web_test_helpers";
|
||||||
|
|
||||||
|
import { GanttRenderer } from "@web_gantt/gantt_renderer";
|
||||||
|
import { Tasks, defineGanttModels } from "./gantt_mock_models";
|
||||||
|
import {
|
||||||
|
SELECTORS,
|
||||||
|
editPill,
|
||||||
|
ganttControlsChanges,
|
||||||
|
getActiveScale,
|
||||||
|
getCellColorProperties,
|
||||||
|
getGridContent,
|
||||||
|
getPillWrapper,
|
||||||
|
mountGanttView,
|
||||||
|
resizePill,
|
||||||
|
selectGanttRange,
|
||||||
|
setScale,
|
||||||
|
} from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
describe.current.tags("desktop");
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
beforeEach(() => mockDate("2018-12-20T08:00:00", +1));
|
||||||
|
|
||||||
|
test("concurrent scale switches return in inverse order", async () => {
|
||||||
|
let model;
|
||||||
|
patchWithCleanup(GanttRenderer.prototype, {
|
||||||
|
setup() {
|
||||||
|
super.setup(...arguments);
|
||||||
|
model = this.model;
|
||||||
|
onPatched(() => {
|
||||||
|
expect.step("patched");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let firstReloadProm = null;
|
||||||
|
let reloadProm = null;
|
||||||
|
onRpc("get_gantt_data", () => reloadProm);
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["patched"]);
|
||||||
|
|
||||||
|
let content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(2);
|
||||||
|
expect(content.groupHeaders.map((gh) => gh.title)).toEqual(["December 2018", "January 2019"]);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
|
||||||
|
// switch to 'week' scale (this rpc will be delayed)
|
||||||
|
firstReloadProm = new Deferred();
|
||||||
|
reloadProm = firstReloadProm;
|
||||||
|
await setScale(4);
|
||||||
|
await ganttControlsChanges();
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(4);
|
||||||
|
expect(content.groupHeaders.map((gh) => gh.title)).toEqual(["December 2018", "January 2019"]);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
|
||||||
|
// switch to 'year' scale
|
||||||
|
reloadProm = null;
|
||||||
|
await setScale(0);
|
||||||
|
await ganttControlsChanges();
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(0);
|
||||||
|
expect(content.groupHeaders.map((gh) => gh.title)).toEqual(["2018", "2019"]);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
|
||||||
|
firstReloadProm.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(0);
|
||||||
|
expect(content.groupHeaders.map((gh) => gh.title)).toEqual(["2018", "2019"]);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
expect.verifySteps(["patched"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent scale switches return with gantt unavailabilities", async () => {
|
||||||
|
const unavailabilities = [
|
||||||
|
[{ start: "2018-12-10 23:00:00", stop: "2018-12-11 23:00:00" }],
|
||||||
|
[{ start: "2018-12-10 23:00:00", stop: "2018-12-11 23:00:00" }],
|
||||||
|
[
|
||||||
|
{ start: "2018-07-30 23:00:00", stop: "2018-08-31 23:00:00" },
|
||||||
|
{ start: "2018-12-10 23:00:00", stop: "2018-12-11 23:00:00" },
|
||||||
|
],
|
||||||
|
[{ start: "2018-07-30 23:00:00", stop: "2018-08-31 23:00:00" }],
|
||||||
|
];
|
||||||
|
|
||||||
|
let model;
|
||||||
|
patchWithCleanup(GanttRenderer.prototype, {
|
||||||
|
setup() {
|
||||||
|
super.setup(...arguments);
|
||||||
|
model = this.model;
|
||||||
|
onPatched(() => {
|
||||||
|
expect.step("patched");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let firstReloadProm = null;
|
||||||
|
let reloadProm = null;
|
||||||
|
onRpc("get_gantt_data", async ({ parent }) => {
|
||||||
|
const result = await parent();
|
||||||
|
result.unavailabilities.__default = { false: unavailabilities.shift() };
|
||||||
|
await reloadProm;
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" display_unavailability="true"/>`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["patched"]);
|
||||||
|
|
||||||
|
let content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(2);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(content.groupHeaders.map((h) => h.title)).toEqual(["December 2018", "January 2019"]);
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
expect(getCellColorProperties("08 December 2018")).toEqual([]);
|
||||||
|
expect(getCellColorProperties("11 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// switch to 'week' scale (this rpc will be delayed)
|
||||||
|
firstReloadProm = new Deferred();
|
||||||
|
reloadProm = firstReloadProm;
|
||||||
|
await setScale(4);
|
||||||
|
await ganttControlsChanges();
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(4);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(content.groupHeaders.map((h) => h.title)).toEqual(["December 2018", "January 2019"]);
|
||||||
|
expect(model.data.records).toHaveLength(6);
|
||||||
|
expect(getCellColorProperties("08 December 2018")).toEqual([]);
|
||||||
|
expect(getCellColorProperties("11 December 2018")).toEqual([
|
||||||
|
"--Gantt__DayOff-background-color",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// switch to 'year' scale
|
||||||
|
reloadProm = null;
|
||||||
|
await setScale(0);
|
||||||
|
await ganttControlsChanges();
|
||||||
|
expect.verifySteps(["patched"]);
|
||||||
|
await selectGanttRange({ startDate: "2018-01-01", stopDate: "2018-12-31" });
|
||||||
|
expect.verifySteps(["patched"]);
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(0);
|
||||||
|
expect(content.range).toBe("From: 01/01/2018 to: 12/31/2018");
|
||||||
|
expect(content.groupHeaders.map((h) => h.title)).toEqual(["2018"]);
|
||||||
|
expect(model.data.records).toHaveLength(7);
|
||||||
|
expect(getCellColorProperties("August 2018")).toEqual(["--Gantt__DayOff-background-color"]);
|
||||||
|
expect(getCellColorProperties("November 2018")).toEqual([]);
|
||||||
|
|
||||||
|
firstReloadProm.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(0);
|
||||||
|
expect(content.range).toBe("From: 01/01/2018 to: 12/31/2018");
|
||||||
|
expect(content.groupHeaders.map((h) => h.title)).toEqual(["2018"]);
|
||||||
|
expect(model.data.records).toHaveLength(7);
|
||||||
|
expect(getCellColorProperties("August 2018")).toEqual(["--Gantt__DayOff-background-color"]);
|
||||||
|
expect(getCellColorProperties("November 2018")).toEqual([]);
|
||||||
|
expect.verifySteps([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent range selections", async () => {
|
||||||
|
let reloadProm = null;
|
||||||
|
let firstReloadProm = null;
|
||||||
|
onRpc("get_gantt_data", () => reloadProm);
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
let content = getGridContent();
|
||||||
|
expect(getActiveScale()).toBe(2);
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
|
||||||
|
reloadProm = new Deferred();
|
||||||
|
firstReloadProm = reloadProm;
|
||||||
|
await selectGanttRange({ startDate: "2019-01-01", stopDate: "2019-02-28" });
|
||||||
|
reloadProm = null;
|
||||||
|
await selectGanttRange({ startDate: "2019-01-01", stopDate: "2019-01-31" });
|
||||||
|
firstReloadProm.resolve();
|
||||||
|
content = getGridContent();
|
||||||
|
expect(content.range).toBe("From: 01/01/2019 to: 01/31/2019");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent pill resize and groupBy change", async () => {
|
||||||
|
let awaitWriteDef = false;
|
||||||
|
const writeDef = new Deferred();
|
||||||
|
onRpc(({ args, method }) => {
|
||||||
|
expect.step([method, args]);
|
||||||
|
if (method === "write" && awaitWriteDef) {
|
||||||
|
return writeDef;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
searchViewArch: `
|
||||||
|
<search>
|
||||||
|
<filter name="group_by" string="Project" domain="[]" context="{ 'group_by': 'project_id' }"/>
|
||||||
|
</search>
|
||||||
|
`,
|
||||||
|
domain: [["id", "in", [2, 5]]],
|
||||||
|
});
|
||||||
|
expect.verifySteps([
|
||||||
|
["get_views", []],
|
||||||
|
["get_gantt_data", []],
|
||||||
|
]);
|
||||||
|
expect(getGridContent().rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// resize "Task 2" to 1 cell smaller (-1 day) ; this RPC will be delayed
|
||||||
|
awaitWriteDef = true;
|
||||||
|
await resizePill(getPillWrapper("Task 2"), "end", -1);
|
||||||
|
|
||||||
|
expect.verifySteps([["write", [[2], { stop: "2018-12-21 06:29:59" }]]]);
|
||||||
|
|
||||||
|
await toggleSearchBarMenu();
|
||||||
|
await toggleMenuItem("Project");
|
||||||
|
expect.verifySteps([["get_gantt_data", []]]);
|
||||||
|
expect(getGridContent().rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Project 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 5",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Project 2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
writeDef.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
expect.verifySteps([["get_gantt_data", []]]);
|
||||||
|
expect(getGridContent().rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 21 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Project 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 04 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 5",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Project 2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent pill resizes return in inverse order", async () => {
|
||||||
|
let awaitWriteDef = false;
|
||||||
|
const writeDef = new Deferred();
|
||||||
|
onRpc(({ args, method }) => {
|
||||||
|
expect.step([method, args]);
|
||||||
|
if (method === "write" && awaitWriteDef) {
|
||||||
|
return writeDef;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
domain: [["id", "=", 2]],
|
||||||
|
});
|
||||||
|
|
||||||
|
// resize to 1 cell smaller (-1 day) ; this RPC will be delayed
|
||||||
|
awaitWriteDef = true;
|
||||||
|
await resizePill(getPillWrapper("Task 2"), "end", -1);
|
||||||
|
|
||||||
|
// resize to two cells larger (+2 days) ; no delay
|
||||||
|
awaitWriteDef = false;
|
||||||
|
await resizePill(getPillWrapper("Task 2"), "end", +2);
|
||||||
|
|
||||||
|
writeDef.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect.verifySteps([
|
||||||
|
["get_views", []],
|
||||||
|
["get_gantt_data", []],
|
||||||
|
["write", [[2], { stop: "2018-12-21 06:29:59" }]],
|
||||||
|
["get_gantt_data", []],
|
||||||
|
["write", [[2], { stop: "2018-12-24 06:29:59" }]],
|
||||||
|
["get_gantt_data", []],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent pill resizes and open, dialog show updated number", async () => {
|
||||||
|
Tasks._views = {
|
||||||
|
form: `
|
||||||
|
<form>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="start"/>
|
||||||
|
<field name="stop"/>
|
||||||
|
</form>
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const def = new Deferred();
|
||||||
|
onRpc("write", () => def);
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
domain: [["id", "=", 2]],
|
||||||
|
});
|
||||||
|
|
||||||
|
await resizePill(getPillWrapper("Task 2"), "end", +2);
|
||||||
|
await editPill("Task 2");
|
||||||
|
|
||||||
|
def.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
expect(`.modal [name=stop] input`).toHaveValue("12/24/2018 07:29:59");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("concurrent display mode change and fetch", async () => {
|
||||||
|
let def;
|
||||||
|
onRpc("get_gantt_data", () => def);
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
domain: [["id", "in", [1, 2]]],
|
||||||
|
});
|
||||||
|
|
||||||
|
let content = getGridContent();
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
const initialRows = [
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{ title: "Task 1", level: 0, colSpan: "Out of bounds (1) -> 31 December 2018" },
|
||||||
|
{
|
||||||
|
title: "Task 2",
|
||||||
|
level: 1,
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
expect(content.rows).toEqual(initialRows);
|
||||||
|
|
||||||
|
def = new Deferred();
|
||||||
|
await selectGanttRange({ startDate: "2018-12-01", stopDate: "2019-06-15" });
|
||||||
|
content = getGridContent();
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 06/15/2019");
|
||||||
|
expect(content.rows).toEqual(initialRows);
|
||||||
|
|
||||||
|
await click(SELECTORS.sparse);
|
||||||
|
await animationFrame();
|
||||||
|
content = getGridContent();
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 06/15/2019");
|
||||||
|
expect(content.rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
def.resolve();
|
||||||
|
await animationFrame();
|
||||||
|
content = getGridContent();
|
||||||
|
expect(content.range).toBe("From: 12/01/2018 to: 06/15/2019");
|
||||||
|
expect(content.rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "Out of bounds (1) -> 31 December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
colSpan: "17 (1/2) December 2018 -> 22 (1/2) December 2018",
|
||||||
|
level: 0,
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
import { beforeEach, expect, test } from "@odoo/hoot";
|
||||||
|
import { queryFirst } from "@odoo/hoot-dom";
|
||||||
|
import { mockDate } from "@odoo/hoot-mock";
|
||||||
|
import { mountGanttView } from "./web_gantt_test_helpers";
|
||||||
|
import { ResUsers, TASKS_STAGE_SELECTION, Tasks, defineGanttModels } from "./gantt_mock_models";
|
||||||
|
|
||||||
|
function randomName(length) {
|
||||||
|
const CHARS = "abcdefghijklmnopqrstuvwxyzàùéèâîûêôäïüëö";
|
||||||
|
return [...Array(length)]
|
||||||
|
.map(() => {
|
||||||
|
const char = CHARS[Math.floor(Math.random() * CHARS.length)];
|
||||||
|
return Math.random() < 0.5 ? char : char.toUpperCase();
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
beforeEach(() => mockDate("2018-12-20T08:00:00", +1));
|
||||||
|
|
||||||
|
test.tags("manual testing").skip("large amount of records (ungrouped)", async () => {
|
||||||
|
const NB_TASKS = 10000;
|
||||||
|
|
||||||
|
Tasks._records = [...Array(NB_TASKS)].map((_, i) => ({
|
||||||
|
id: i + 1,
|
||||||
|
name: `Task ${i + 1}`,
|
||||||
|
start: `2018-12-01 00:00:00`,
|
||||||
|
stop: `2018-12-01 23:00:00`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.time("makeView");
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
});
|
||||||
|
console.timeEnd("makeView");
|
||||||
|
expect(1).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.tags("manual testing").skip("large amount of records (one level grouped)", async () => {
|
||||||
|
const NB_USERS = 10000;
|
||||||
|
const NB_TASKS = 10000;
|
||||||
|
|
||||||
|
ResUsers._records = [...Array(NB_USERS)].map((_, i) => ({
|
||||||
|
id: i + 1,
|
||||||
|
name: `${randomName(Math.floor(Math.random() * 8) + 8)} (${i + 1})`,
|
||||||
|
}));
|
||||||
|
Tasks._records = [...Array(NB_TASKS)].map((_, i) => {
|
||||||
|
let day1 = (i % 30) + 1;
|
||||||
|
let day2 = (i % 30) + 2;
|
||||||
|
if (day1 < 10) {
|
||||||
|
day1 = "0" + day1;
|
||||||
|
}
|
||||||
|
if (day2 < 10) {
|
||||||
|
day2 = "0" + day2;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: i + 1,
|
||||||
|
name: `Task ${i + 1}`,
|
||||||
|
user_id: Math.floor(Math.random() * Math.floor(NB_USERS)) + 1,
|
||||||
|
start: `2018-12-${day1} 00:00:00`,
|
||||||
|
stop: `2018-12-${day2} 00:00:00`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.time("makeView");
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
groupBy: ["user_id"],
|
||||||
|
});
|
||||||
|
console.timeEnd("makeView");
|
||||||
|
|
||||||
|
queryFirst(".o_content").style = "max-height: 600px; overflow-y: scroll;";
|
||||||
|
expect(1).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.tags("manual testing").skip("large amount of records (two level grouped)", async () => {
|
||||||
|
const NB_USERS = 100;
|
||||||
|
const NB_TASKS = 10000;
|
||||||
|
|
||||||
|
ResUsers._records = [...Array(NB_USERS)].map((_, i) => ({
|
||||||
|
id: i + 1,
|
||||||
|
name: `${randomName(Math.floor(Math.random() * 8) + 8)} (${i + 1})`,
|
||||||
|
}));
|
||||||
|
Tasks._records = [...Array(NB_TASKS)].map((_, i) => ({
|
||||||
|
id: i + 1,
|
||||||
|
name: `Task ${i + 1}`,
|
||||||
|
stage: TASKS_STAGE_SELECTION[i % 2][0],
|
||||||
|
user_id: (i % NB_USERS) + 1,
|
||||||
|
start: "2018-12-01 00:00:00",
|
||||||
|
stop: "2018-12-02 00:00:00",
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.time("makeView");
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
groupBy: ["user_id", "stage"],
|
||||||
|
});
|
||||||
|
console.timeEnd("makeView");
|
||||||
|
expect(1).toBe(1);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,378 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import { queryAll, queryAllTexts, queryFirst } from "@odoo/hoot-dom";
|
||||||
|
import { animationFrame, mockDate } from "@odoo/hoot-mock";
|
||||||
|
import { contains, getService, mountWithCleanup, onRpc } from "@web/../tests/web_test_helpers";
|
||||||
|
import { Domain } from "@web/core/domain";
|
||||||
|
import { deserializeDateTime } from "@web/core/l10n/dates";
|
||||||
|
import { WebClient } from "@web/webclient/webclient";
|
||||||
|
import { Tasks, defineGanttModels } from "./gantt_mock_models";
|
||||||
|
import {
|
||||||
|
CLASSES,
|
||||||
|
SELECTORS,
|
||||||
|
getActiveScale,
|
||||||
|
getGridContent,
|
||||||
|
mountGanttView,
|
||||||
|
} from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
|
||||||
|
describe.current.tags("mobile");
|
||||||
|
|
||||||
|
beforeEach(() => mockDate("2018-12-20T08:00:00", +1));
|
||||||
|
|
||||||
|
test("empty ungrouped gantt rendering", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" />`,
|
||||||
|
domain: [["id", "=", 0]],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe(null);
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(10);
|
||||||
|
expect(columnHeaders.at(0).title).toBe("15");
|
||||||
|
expect(columnHeaders.at(-1).title).toBe("24");
|
||||||
|
expect(rows).toEqual([{}]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ungrouped gantt rendering", async () => {
|
||||||
|
const task2 = Tasks._records[1];
|
||||||
|
const startDateLocalString = deserializeDateTime(task2.start).toFormat("f");
|
||||||
|
const stopDateLocalString = deserializeDateTime(task2.stop).toFormat("f");
|
||||||
|
Tasks._views.gantt = `<gantt date_start="start" date_stop="stop"/>`;
|
||||||
|
Tasks._views.search = `<search/>`;
|
||||||
|
|
||||||
|
onRpc("get_gantt_data", ({ model }) => expect.step(model));
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [[false, "gantt"]],
|
||||||
|
});
|
||||||
|
expect.verifySteps(["tasks"]);
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe(null);
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(10);
|
||||||
|
expect(columnHeaders.at(0).title).toBe("15");
|
||||||
|
expect(columnHeaders.at(-1).title).toBe("24");
|
||||||
|
expect(getActiveScale()).toBe(2);
|
||||||
|
expect(SELECTORS.expandCollapseButtons).not.toBeVisible();
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
pills: [
|
||||||
|
{ title: "Task 1", level: 1, colSpan: "Out of bounds (1) -> Out of bounds (63) " },
|
||||||
|
{
|
||||||
|
title: "Task 2",
|
||||||
|
level: 0,
|
||||||
|
colSpan: "17 (1/2) Dec 2018 -> 22 (1/2) Dec 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 4",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 Dec 2018 -> 20 (1/2) Dec 2018",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 7",
|
||||||
|
level: 2,
|
||||||
|
colSpan: "20 (1/2) Dec 2018 -> 20 Dec 2018",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// test popover and local timezone
|
||||||
|
expect(`.o_popover`).toHaveCount(0);
|
||||||
|
const task2Pill = queryAll(SELECTORS.pill)[1];
|
||||||
|
expect(task2Pill).toHaveText("Task 2");
|
||||||
|
|
||||||
|
await contains(task2Pill).click();
|
||||||
|
expect(`.o_popover`).toHaveCount(1);
|
||||||
|
expect(queryAllTexts`.o_popover .popover-body span`).toEqual([
|
||||||
|
"Task 2",
|
||||||
|
startDateLocalString,
|
||||||
|
stopDateLocalString,
|
||||||
|
]);
|
||||||
|
|
||||||
|
await contains(`.o_popover .popover-header i.fa.fa-close`).click();
|
||||||
|
expect(`.o_popover`).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ordered gantt view", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" progress="progress"/>`,
|
||||||
|
groupBy: ["stage_id"],
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(10);
|
||||||
|
expect(columnHeaders.at(0).title).toBe("16");
|
||||||
|
expect(columnHeaders.at(-1).title).toBe("25");
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
title: "todo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "in_progress",
|
||||||
|
pills: [
|
||||||
|
{ level: 0, colSpan: "Out of bounds (1) -> Out of bounds (63) ", title: "Task 1" },
|
||||||
|
{
|
||||||
|
level: 1,
|
||||||
|
colSpan: "20 (1/2) Dec 2018 -> 20 Dec 2018",
|
||||||
|
title: "Task 7",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "done",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
colSpan: "17 (1/2) Dec 2018 -> 22 (1/2) Dec 2018",
|
||||||
|
title: "Task 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "cancel",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
colSpan: "20 Dec 2018 -> 20 (1/2) Dec 2018",
|
||||||
|
title: "Task 4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("empty single-level grouped gantt rendering", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
domain: Domain.FALSE.toList(),
|
||||||
|
});
|
||||||
|
const { viewTitle, range, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(viewTitle).toBe("Gantt View");
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(columnHeaders).toHaveLength(10);
|
||||||
|
expect(columnHeaders.at(0).title).toBe("16");
|
||||||
|
expect(columnHeaders.at(-1).title).toBe("25");
|
||||||
|
expect(rows).toEqual([{ title: "" }]);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("single-level grouped gantt rendering", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt string="Tasks" date_start="start" date_stop="stop"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
});
|
||||||
|
expect(getActiveScale()).toBe(2);
|
||||||
|
expect(SELECTORS.expandCollapseButtons).not.toBeVisible();
|
||||||
|
|
||||||
|
const { range, viewTitle, columnHeaders, rows } = getGridContent();
|
||||||
|
expect(range).toBe("From: 12/01/2018 to: 02/28/2019");
|
||||||
|
expect(viewTitle).toBe("Tasks");
|
||||||
|
expect(columnHeaders).toHaveLength(10);
|
||||||
|
expect(columnHeaders.at(0).title).toBe("16");
|
||||||
|
expect(columnHeaders.at(-1).title).toBe("25");
|
||||||
|
expect(rows).toEqual([
|
||||||
|
{
|
||||||
|
title: "Project 1",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
title: "Task 1",
|
||||||
|
colSpan: "Out of bounds (1) -> Out of bounds (63) ",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 2",
|
||||||
|
colSpan: "17 (1/2) Dec 2018 -> 22 (1/2) Dec 2018",
|
||||||
|
level: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Task 4",
|
||||||
|
colSpan: "20 Dec 2018 -> 20 (1/2) Dec 2018",
|
||||||
|
level: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Project 2",
|
||||||
|
pills: [
|
||||||
|
{
|
||||||
|
title: "Task 7",
|
||||||
|
colSpan: "20 (1/2) Dec 2018 -> 20 Dec 2018",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Controls: rendering is mobile friendly", async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" />`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// check toolbar's dropdown
|
||||||
|
await contains("button.dropdown-toggle").click();
|
||||||
|
expect(queryAllTexts`.o-dropdown-item`).toEqual(["Activate sparse mode"]);
|
||||||
|
|
||||||
|
// check that pickers open in dialog
|
||||||
|
await contains(SELECTORS.rangeMenuToggler).click();
|
||||||
|
expect(".modal").toHaveCount(0);
|
||||||
|
await contains(SELECTORS.startDatePicker).click();
|
||||||
|
expect(".modal").toHaveCount(1);
|
||||||
|
expect(".modal-title").toHaveText("Gantt start date");
|
||||||
|
expect(".modal-body .o_datetime_picker").toHaveCount(1);
|
||||||
|
await contains(".modal-header .btn").click();
|
||||||
|
expect(".modal").toHaveCount(0);
|
||||||
|
await contains(SELECTORS.stopDatePicker).click();
|
||||||
|
expect(".modal").toHaveCount(1);
|
||||||
|
expect(".modal-title").toHaveText("Gantt stop date");
|
||||||
|
expect(".modal-body .o_datetime_picker").toHaveCount(1);
|
||||||
|
await contains(".modal-header .btn").click();
|
||||||
|
expect(".modal").toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Progressbar: check the progressbar percentage visibility.", async () => {
|
||||||
|
onRpc("get_gantt_data", async ({ kwargs, parent }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.progress_bar_fields).toEqual(["user_id"]);
|
||||||
|
result.progress_bars.user_id = {
|
||||||
|
1: { value: 50, max_value: 100 },
|
||||||
|
2: { value: 25, max_value: 200 },
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
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>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
|
||||||
|
expect(SELECTORS.progressBar).toHaveCount(2);
|
||||||
|
const [progressBar1, progressBar2] = queryAll(SELECTORS.progressBar);
|
||||||
|
expect(progressBar1).toHaveClass("o_gantt_group_success");
|
||||||
|
expect(progressBar2).toHaveClass("o_gantt_group_success");
|
||||||
|
const [rowHeader1, rowHeader2] = [progressBar1.parentElement, progressBar2.parentElement];
|
||||||
|
expect(rowHeader1.matches(SELECTORS.rowHeader)).toBe(true);
|
||||||
|
expect(rowHeader2.matches(SELECTORS.rowHeader)).toBe(true);
|
||||||
|
expect(rowHeader1).not.toHaveClass(CLASSES.group);
|
||||||
|
expect(rowHeader2).not.toHaveClass(CLASSES.group);
|
||||||
|
expect(queryAll(SELECTORS.progressBarBackground).map((el) => el.style.width)).toEqual([
|
||||||
|
"50%",
|
||||||
|
"12.5%",
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.progressBarForeground).toHaveCount(2);
|
||||||
|
expect(queryAllTexts(SELECTORS.progressBarForeground)).toEqual(["50h / 100h", "25h / 200h"]);
|
||||||
|
|
||||||
|
// Check the style of one of the progress bars
|
||||||
|
expect(rowHeader1.children).toHaveLength(2);
|
||||||
|
const rowTitle1 = rowHeader1.children[0];
|
||||||
|
expect(rowTitle1.matches(SELECTORS.rowTitle)).toBe(true);
|
||||||
|
expect(rowTitle1.nextElementSibling).toBe(progressBar1);
|
||||||
|
|
||||||
|
expect(rowHeader1).toHaveStyle({ gridTemplateRows: "36px 35px" });
|
||||||
|
expect(rowTitle1).toHaveStyle({ height: "36px" });
|
||||||
|
expect(progressBar1).toHaveStyle({ height: "35px" });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Progressbar: grouped row", async () => {
|
||||||
|
onRpc("get_gantt_data", async ({ kwargs, parent }) => {
|
||||||
|
expect.step("get_gantt_data");
|
||||||
|
const result = await parent();
|
||||||
|
expect(kwargs.progress_bar_fields).toEqual(["user_id"]);
|
||||||
|
result.progress_bars.user_id = {
|
||||||
|
1: { value: 50, max_value: 100 },
|
||||||
|
2: { value: 25, max_value: 200 },
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `
|
||||||
|
<gantt date_start="start" date_stop="stop" default_scale="week" scales="week" default_group_by="user_id,user_id" progress_bar="user_id">
|
||||||
|
<field name="user_id"/>
|
||||||
|
</gantt>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect.verifySteps(["get_gantt_data"]);
|
||||||
|
|
||||||
|
expect(SELECTORS.progressBar).toHaveCount(4);
|
||||||
|
const [progressBar1, progressBar2] = queryAll(SELECTORS.progressBar);
|
||||||
|
expect(progressBar1).toHaveClass("o_gantt_group_success");
|
||||||
|
expect(progressBar2).toHaveClass("o_gantt_group_success");
|
||||||
|
const [rowHeader1, rowHeader2] = [progressBar1.parentElement, progressBar2.parentElement];
|
||||||
|
expect(rowHeader1.matches(SELECTORS.rowHeader)).toBe(true);
|
||||||
|
expect(rowHeader2.matches(SELECTORS.rowHeader)).toBe(true);
|
||||||
|
expect(rowHeader1).toHaveClass(CLASSES.group);
|
||||||
|
expect(rowHeader2).not.toHaveClass(CLASSES.group);
|
||||||
|
expect(queryAll(SELECTORS.progressBarBackground).map((el) => el.style.width)).toEqual([
|
||||||
|
"50%",
|
||||||
|
"50%",
|
||||||
|
"12.5%",
|
||||||
|
"12.5%",
|
||||||
|
]);
|
||||||
|
expect(SELECTORS.progressBarForeground).toHaveCount(4);
|
||||||
|
expect(queryAllTexts(SELECTORS.progressBarForeground)).toEqual([
|
||||||
|
"50h / 100h",
|
||||||
|
"50h / 100h",
|
||||||
|
"25h / 200h",
|
||||||
|
"25h / 200h",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Check the style of one of the progress bars
|
||||||
|
expect(rowHeader1.children).toHaveLength(2);
|
||||||
|
const rowTitle1 = rowHeader1.children[0];
|
||||||
|
expect(rowTitle1.matches(SELECTORS.rowTitle)).toBe(true);
|
||||||
|
expect(rowTitle1.nextElementSibling).toBe(progressBar1);
|
||||||
|
|
||||||
|
expect(rowHeader1).toHaveStyle({ gridTemplateRows: "24px 35px" });
|
||||||
|
expect(rowTitle1).toHaveStyle({ height: "24px" });
|
||||||
|
expect(progressBar1).toHaveStyle({ height: "35px" });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("horizontal scroll applies to the content [SMALL SCREEN]", async () => {
|
||||||
|
Tasks._views.search = `<search/>`;
|
||||||
|
Tasks._views.gantt = `<gantt date_start="start" date_stop="stop"><field name="user_id"/></gantt>`;
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [[false, "gantt"]],
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
const o_view_controller = queryFirst(".o_view_controller");
|
||||||
|
const o_content = queryFirst(".o_content");
|
||||||
|
const firstColumnHeader = queryFirst(SELECTORS.columnHeader);
|
||||||
|
const initialXHeaderCell = firstColumnHeader.getBoundingClientRect().x;
|
||||||
|
|
||||||
|
expect(o_view_controller).toHaveClass("o_action_delegate_scroll");
|
||||||
|
expect(o_view_controller).toHaveStyle({ overflow: "hidden" });
|
||||||
|
expect(o_content).toHaveStyle({ overflow: "auto" });
|
||||||
|
expect(o_content).toHaveProperty("scrollLeft", 762);
|
||||||
|
|
||||||
|
// Horizontal scroll
|
||||||
|
const newScrollLeft = o_content.scrollLeft - 50;
|
||||||
|
await contains(".o_content").scroll({ left: newScrollLeft });
|
||||||
|
|
||||||
|
expect(o_content).toHaveProperty("scrollLeft", newScrollLeft);
|
||||||
|
expect(firstColumnHeader.getBoundingClientRect().x).toBe(initialXHeaderCell + 50);
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,214 @@
|
||||||
|
import { beforeEach, describe, expect, test } from "@odoo/hoot";
|
||||||
|
import { queryFirst, queryAll } from "@odoo/hoot-dom";
|
||||||
|
import { mockDate, animationFrame } from "@odoo/hoot-mock";
|
||||||
|
import { markup } from "@odoo/owl";
|
||||||
|
import {
|
||||||
|
getService,
|
||||||
|
mountWithCleanup,
|
||||||
|
switchView,
|
||||||
|
toggleMenuItem,
|
||||||
|
toggleSearchBarMenu,
|
||||||
|
} from "@web/../tests/web_test_helpers";
|
||||||
|
import { Tasks, defineGanttModels } from "./gantt_mock_models";
|
||||||
|
import { SELECTORS, mountGanttView } from "./web_gantt_test_helpers";
|
||||||
|
|
||||||
|
import { Domain } from "@web/core/domain";
|
||||||
|
import { WebClient } from "@web/webclient/webclient";
|
||||||
|
|
||||||
|
describe.current.tags("desktop");
|
||||||
|
|
||||||
|
defineGanttModels();
|
||||||
|
beforeEach(() => mockDate("2018-12-20T08:00:00", +1));
|
||||||
|
|
||||||
|
test(`empty grouped gantt with sample="1"`, async () => {
|
||||||
|
Tasks._views = {
|
||||||
|
gantt: `<gantt date_start="start" date_stop="stop" sample="1"/>`,
|
||||||
|
graph: `<graph/>`,
|
||||||
|
search: `<search/>`,
|
||||||
|
};
|
||||||
|
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [
|
||||||
|
[false, "gantt"],
|
||||||
|
[false, "graph"],
|
||||||
|
],
|
||||||
|
domain: Domain.FALSE.toList(),
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(queryAll(SELECTORS.pill).length).toBeWithin(0, 16);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
|
||||||
|
const content = queryFirst(SELECTORS.viewContent).innerHTML;
|
||||||
|
await switchView("gantt");
|
||||||
|
await animationFrame();
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.viewContent).toHaveProperty("innerHTML", content);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("empty gantt with sample data and default_group_by", async () => {
|
||||||
|
Tasks._views = {
|
||||||
|
gantt: `<gantt date_start="start" date_stop="stop" sample="1" default_group_by="project_id"/>`,
|
||||||
|
graph: `<graph/>`,
|
||||||
|
search: `<search/>`,
|
||||||
|
};
|
||||||
|
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [
|
||||||
|
[false, "gantt"],
|
||||||
|
[false, "graph"],
|
||||||
|
],
|
||||||
|
domain: Domain.FALSE.toList(),
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(queryAll(SELECTORS.pill).length).toBeWithin(0, 16);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
|
||||||
|
const content = queryFirst(SELECTORS.viewContent).innerHTML;
|
||||||
|
await switchView("gantt");
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.viewContent).toHaveProperty("innerHTML", content);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("empty gantt with sample data and default_group_by (switch view)", async () => {
|
||||||
|
Tasks._views = {
|
||||||
|
gantt: `<gantt date_start="start" date_stop="stop" sample="1" default_group_by="project_id"/>`,
|
||||||
|
list: `<list/>`,
|
||||||
|
search: `<search/>`,
|
||||||
|
};
|
||||||
|
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [
|
||||||
|
[false, "gantt"],
|
||||||
|
[false, "list"],
|
||||||
|
],
|
||||||
|
domain: Domain.FALSE.toList(),
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
// the gantt view should be in sample mode
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(queryAll(SELECTORS.pill).length).toBeWithin(0, 16);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
const content = queryFirst(SELECTORS.viewContent).innerHTML;
|
||||||
|
|
||||||
|
// switch to list view
|
||||||
|
await switchView("list");
|
||||||
|
expect(SELECTORS.view).toHaveCount(0);
|
||||||
|
|
||||||
|
// go back to gantt view
|
||||||
|
await switchView("gantt");
|
||||||
|
await animationFrame();
|
||||||
|
|
||||||
|
expect(SELECTORS.view).toHaveCount(1);
|
||||||
|
|
||||||
|
// the gantt view should be still in sample mode
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
expect(SELECTORS.viewContent).toHaveProperty("innerHTML", content);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`empty gantt with sample="1"`, async () => {
|
||||||
|
Tasks._views = {
|
||||||
|
gantt: `<gantt date_start="start" date_stop="stop" sample="1"/>`,
|
||||||
|
graph: `<graph/>`,
|
||||||
|
search: `<search/>`,
|
||||||
|
};
|
||||||
|
|
||||||
|
await mountWithCleanup(WebClient);
|
||||||
|
await getService("action").doAction({
|
||||||
|
res_model: "tasks",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
views: [
|
||||||
|
[false, "gantt"],
|
||||||
|
[false, "graph"],
|
||||||
|
],
|
||||||
|
domain: Domain.FALSE.toList(),
|
||||||
|
});
|
||||||
|
await animationFrame();
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(queryAll(SELECTORS.pill).length).toBeWithin(0, 16);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
|
||||||
|
const content = queryFirst(SELECTORS.viewContent).innerHTML;
|
||||||
|
|
||||||
|
await switchView("gantt");
|
||||||
|
await animationFrame();
|
||||||
|
expect(SELECTORS.viewContent).toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.viewContent).toHaveProperty("innerHTML", content);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`non empty gantt with sample="1"`, async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_scale="year" sample="1"/>`,
|
||||||
|
searchViewArch: `
|
||||||
|
<search>
|
||||||
|
<filter name="filter" string="False Domain" domain="[(0, '=', 1)]"/>
|
||||||
|
</search>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(SELECTORS.viewContent).not.toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.cell).toHaveCount(12);
|
||||||
|
expect(SELECTORS.pill).toHaveCount(7);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
|
||||||
|
await toggleSearchBarMenu();
|
||||||
|
await toggleMenuItem("False Domain");
|
||||||
|
expect(SELECTORS.viewContent).not.toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.pill).toHaveCount(0);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
expect(SELECTORS.cell).toHaveCount(12);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`non empty grouped gantt with sample="1"`, async () => {
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" default_scale="year" sample="1"/>`,
|
||||||
|
groupBy: ["project_id"],
|
||||||
|
searchViewArch: `
|
||||||
|
<search>
|
||||||
|
<filter name="filter" string="False Domain" domain="[(0, '=', 1)]"/>
|
||||||
|
</search>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(SELECTORS.viewContent).not.toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.cell).toHaveCount(24);
|
||||||
|
expect(SELECTORS.pill).toHaveCount(7);
|
||||||
|
|
||||||
|
await toggleSearchBarMenu();
|
||||||
|
await toggleMenuItem("False Domain");
|
||||||
|
expect(SELECTORS.viewContent).not.toHaveClass("o_view_sample_data");
|
||||||
|
expect(SELECTORS.pill).toHaveCount(0);
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(0);
|
||||||
|
expect(SELECTORS.cell).toHaveCount(12);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("no content helper from action when no data and sample mode", async () => {
|
||||||
|
Tasks._records = [];
|
||||||
|
await mountGanttView({
|
||||||
|
resModel: "tasks",
|
||||||
|
arch: `<gantt date_start="start" date_stop="stop" sample="1"/>`,
|
||||||
|
noContentHelp: markup(`<p class="hello">click to add a partner</p>`),
|
||||||
|
});
|
||||||
|
expect(SELECTORS.noContentHelper).toHaveCount(1);
|
||||||
|
expect(`${SELECTORS.noContentHelper} p.hello:contains(add a partner)`).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,580 @@
|
||||||
|
import {
|
||||||
|
click,
|
||||||
|
hover,
|
||||||
|
queryAll,
|
||||||
|
queryAllTexts,
|
||||||
|
queryFirst,
|
||||||
|
queryOne,
|
||||||
|
queryText,
|
||||||
|
setInputRange,
|
||||||
|
} from "@odoo/hoot-dom";
|
||||||
|
import { advanceTime, animationFrame, runAllTimers } from "@odoo/hoot-mock";
|
||||||
|
import { getPickerCell, zoomOut } from "@web/../tests/core/datetime/datetime_test_helpers";
|
||||||
|
import { contains, mountView } from "@web/../tests/web_test_helpers";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef CellHelperOptions
|
||||||
|
* @property {number} [part=1] -- starts at 1
|
||||||
|
* @property {boolean} [ignoreHoverableClass=false]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PillHelperOptions
|
||||||
|
* @property {number} [nth=1] -- starts at 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef DragPillHelpers
|
||||||
|
* @property {() => Promise<void>} cancel
|
||||||
|
* @property {(params: DragParams) => Promise<void>} drop
|
||||||
|
* @property {(params: DragParams) => Promise<void>} moveTo
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @typedef {(columnHeader: string, rowHeader: string, options: CellHelperOptions) => T} CellHelper
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @typedef {(text: string, options: PillHelperOptions) => T} PillHelper
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @typedef {CellHelperOptions & { row: number, column: number }} DragGridParams */
|
||||||
|
|
||||||
|
/** @typedef {PillHelperOptions & { pill: string }} DragPillParams */
|
||||||
|
|
||||||
|
/** @typedef {DragGridParams | DragPillParams} DragParams */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template {String} T
|
||||||
|
* @param {T} key
|
||||||
|
* @returns {`.${T}`}
|
||||||
|
*/
|
||||||
|
function makeClassSelector(key) {
|
||||||
|
return `.${key}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CLASSES = {
|
||||||
|
draggable: "o_draggable",
|
||||||
|
group: "o_gantt_group",
|
||||||
|
highlightedPill: "highlight",
|
||||||
|
resizable: "o_resizable",
|
||||||
|
|
||||||
|
// Connectors
|
||||||
|
highlightedConnector: "o_connector_highlighted",
|
||||||
|
highlightedConnectorCreator: "o_connector_creator_highlight",
|
||||||
|
lockedConnectorCreator: "o_connector_creator_lock", // Connector creators highlight for initial pill
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SELECTORS = {
|
||||||
|
addButton: ".o_gantt_button_add",
|
||||||
|
cell: ".o_gantt_cell",
|
||||||
|
cellContainer: ".o_gantt_cells",
|
||||||
|
collapseButton: ".o_gantt_button_collapse_rows",
|
||||||
|
dense: ".fa-compress",
|
||||||
|
sparse: ".fa-expand",
|
||||||
|
draggable: makeClassSelector(CLASSES.draggable),
|
||||||
|
expandButton: ".o_gantt_button_expand_rows",
|
||||||
|
expandCollapseButtons: ".o_gantt_button_expand_rows, .o_gantt_button_collapse_rows",
|
||||||
|
group: makeClassSelector(CLASSES.group),
|
||||||
|
groupHeader: ".o_gantt_header_title",
|
||||||
|
columnHeader: ".o_gantt_header_cell",
|
||||||
|
highlightedPill: makeClassSelector(CLASSES.highlightedPill),
|
||||||
|
hoverable: ".o_gantt_hoverable",
|
||||||
|
noContentHelper: ".o_view_nocontent",
|
||||||
|
pill: ".o_gantt_pill",
|
||||||
|
pillWrapper: ".o_gantt_pill_wrapper",
|
||||||
|
progressBar: ".o_gantt_row_header .o_gantt_progress_bar",
|
||||||
|
progressBarBackground: ".o_gantt_row_header .o_gantt_progress_bar > span.bg-opacity-25",
|
||||||
|
progressBarForeground:
|
||||||
|
".o_gantt_row_header .o_gantt_progress_bar > span > .o_gantt_group_hours",
|
||||||
|
progressBarWarning:
|
||||||
|
".o_gantt_row_header .o_gantt_progress_bar > .o_gantt_group_hours > .fa-exclamation-triangle",
|
||||||
|
renderer: ".o_gantt_renderer",
|
||||||
|
resizable: makeClassSelector(CLASSES.resizable),
|
||||||
|
resizeBadge: ".o_gantt_pill_resize_badge",
|
||||||
|
resizeEndHandle: ".o_handle_end",
|
||||||
|
resizeHandle: ".o_resize_handle",
|
||||||
|
resizeStartHandle: ".o_handle_start",
|
||||||
|
rowHeader: ".o_gantt_row_header",
|
||||||
|
rowTitle: ".o_gantt_row_title",
|
||||||
|
rowTotal: ".o_gantt_row_total",
|
||||||
|
startDatePicker: ".o_gantt_picker:nth-child(2)",
|
||||||
|
stopDatePicker: ".o_gantt_picker:nth-child(4)",
|
||||||
|
thumbnail: ".o_gantt_row_thumbnail",
|
||||||
|
rangeMenu: ".o_gantt_range_menu",
|
||||||
|
rangeMenuToggler: ".o_gantt_renderer_controls div.dropdown:nth-child(2)",
|
||||||
|
todayButton: ".o_gantt_button_today",
|
||||||
|
toolbar: ".o_gantt_renderer_controls div[name='ganttToolbar']",
|
||||||
|
undraggable: ".o_undraggable",
|
||||||
|
view: ".o_gantt_view",
|
||||||
|
viewContent: ".o_gantt_view .o_content",
|
||||||
|
previousButton: ".o_gantt_renderer_controls button:has(> .fa-arrow-left)",
|
||||||
|
nextButton: ".o_gantt_renderer_controls button:has(> .fa-arrow-right)",
|
||||||
|
minusButton: ".o_gantt_renderer_controls button:has(> .fa-search-minus)",
|
||||||
|
plusButton: ".o_gantt_renderer_controls button:has(> .fa-search-plus)",
|
||||||
|
|
||||||
|
// Connectors
|
||||||
|
connector: ".o_gantt_connector",
|
||||||
|
connectorCreatorBullet: ".o_connector_creator_bullet",
|
||||||
|
connectorCreatorRight: ".o_connector_creator_right",
|
||||||
|
connectorCreatorWrapper: ".o_connector_creator_wrapper",
|
||||||
|
connectorRemoveButton: ".o_connector_stroke_remove_button",
|
||||||
|
connectorRescheduleButton: ".o_connector_stroke_reschedule_button",
|
||||||
|
connectorStroke: ".o_connector_stroke",
|
||||||
|
connectorStrokeButton: ".o_connector_stroke_button",
|
||||||
|
highlightedConnector: makeClassSelector(CLASSES.highlightedConnector),
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function mountGanttView(params) {
|
||||||
|
const gantt = await mountView({ ...params, type: "gantt" });
|
||||||
|
await animationFrame();
|
||||||
|
return gantt;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function ganttControlsChanges() {
|
||||||
|
await runAllTimers();
|
||||||
|
await animationFrame();
|
||||||
|
await animationFrame(); // for potential focusDate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} selector
|
||||||
|
* @param {DateTime} datetime
|
||||||
|
*/
|
||||||
|
async function selectDateInDatePicker(selector, datetime) {
|
||||||
|
await contains(selector).click();
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
await zoomOut();
|
||||||
|
}
|
||||||
|
await contains(getPickerCell(datetime.year - (datetime.year % 10))).click();
|
||||||
|
await contains(getPickerCell(datetime.year)).click();
|
||||||
|
await contains(getPickerCell(datetime.monthShort)).click();
|
||||||
|
await contains(getPickerCell(datetime.day, true)).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} param0
|
||||||
|
* @param {string} [param0.startDate]
|
||||||
|
* @param {string} [param0.stopDate]
|
||||||
|
*/
|
||||||
|
export async function selectGanttRange({ startDate, stopDate }) {
|
||||||
|
const {
|
||||||
|
startDatePicker: START_SELECTOR,
|
||||||
|
stopDatePicker: STOP_SELECTOR,
|
||||||
|
rangeMenuToggler,
|
||||||
|
} = SELECTORS;
|
||||||
|
await click(rangeMenuToggler);
|
||||||
|
await animationFrame();
|
||||||
|
if (startDate) {
|
||||||
|
await selectDateInDatePicker(START_SELECTOR, luxon.DateTime.fromISO(startDate));
|
||||||
|
}
|
||||||
|
if (stopDate) {
|
||||||
|
await selectDateInDatePicker(STOP_SELECTOR, luxon.DateTime.fromISO(stopDate));
|
||||||
|
}
|
||||||
|
await click(".dropdown-item button:contains(Apply)");
|
||||||
|
await ganttControlsChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function selectRange(label) {
|
||||||
|
await click(SELECTORS.rangeMenuToggler);
|
||||||
|
await animationFrame();
|
||||||
|
await click(`${SELECTORS.rangeMenu} .dropdown-item:contains(/^${label}$/)`);
|
||||||
|
await ganttControlsChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getActiveScale() {
|
||||||
|
return Number(queryFirst(".o_gantt_renderer_controls input").value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} scale
|
||||||
|
*/
|
||||||
|
export async function setScale(scale) {
|
||||||
|
await setInputRange(".o_gantt_renderer_controls input", scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function focusToday() {
|
||||||
|
await click(SELECTORS.todayButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {PillHelper<Promise<DragPillHelpers>>} */
|
||||||
|
export async function dragPill(text, options) {
|
||||||
|
/**
|
||||||
|
* @param {DragParams} [params]
|
||||||
|
*/
|
||||||
|
const drop = async (params) => {
|
||||||
|
if (params) {
|
||||||
|
await moveTo(params);
|
||||||
|
}
|
||||||
|
await dragActions.drop();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DragParams} params
|
||||||
|
*/
|
||||||
|
const moveTo = async (params) => {
|
||||||
|
let cell;
|
||||||
|
if (params?.column) {
|
||||||
|
cell = await hoverGridCell(params.column, params.row, params);
|
||||||
|
} else if (params?.pill) {
|
||||||
|
({ cell } = await hoverPillCell(getPillWrapper(params.pill, params)));
|
||||||
|
}
|
||||||
|
return dragActions.moveTo(cell, {
|
||||||
|
position: getCellPositionOffset(cell, params.part),
|
||||||
|
relative: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pill = getPillWrapper(text, options);
|
||||||
|
pill.scrollIntoView({ behavior: "instant", inline: "center" });
|
||||||
|
const { cell, part } = await hoverPillCell(pill);
|
||||||
|
const dragActions = await contains(pill).drag({
|
||||||
|
// D&D needs the correct initial position since it will attempt an implicit
|
||||||
|
// hover on the pill.
|
||||||
|
position: getCellPositionOffset(cell, part - 1),
|
||||||
|
relative: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...dragActions, drop, moveTo };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {PillHelper<Promise<void>>} */
|
||||||
|
export async function editPill(text, options) {
|
||||||
|
await contains(getPill(text, options)).click();
|
||||||
|
await contains(".o_popover .popover-footer .btn-primary").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} header
|
||||||
|
*/
|
||||||
|
function findColumnFromHeader(header) {
|
||||||
|
const columnHeaders = getHeaders(SELECTORS.columnHeader);
|
||||||
|
const groupHeaders = getHeaders(SELECTORS.groupHeader);
|
||||||
|
const columnHeader = header.substring(0, header.indexOf(" "));
|
||||||
|
const groupHeader = header.substring(header.indexOf(" ") + 1);
|
||||||
|
const groupRange = groupHeaders.find((header) => header.title === groupHeader).range;
|
||||||
|
return columnHeaders.find(
|
||||||
|
(header) =>
|
||||||
|
header.title === columnHeader &&
|
||||||
|
header.range[0] >= groupRange[0] &&
|
||||||
|
header.range[1] <= groupRange[1]
|
||||||
|
).range[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {CellHelper<HTMLElement>} */
|
||||||
|
export function getCell(columnHeader, rowHeader = null, options) {
|
||||||
|
const columnIndex = findColumnFromHeader(columnHeader);
|
||||||
|
const cells = queryAll(`${SELECTORS.cell}[data-col='${columnIndex}']`);
|
||||||
|
if (!cells.length) {
|
||||||
|
throw new Error(`Could not find cell at column ${columnHeader}`);
|
||||||
|
}
|
||||||
|
if (rowHeader === null) {
|
||||||
|
return cells[0];
|
||||||
|
}
|
||||||
|
const row = queryAll(`.o_gantt_row_header:contains(${rowHeader})`)?.[(options?.num || 1) - 1];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error(`Could not find row ${rowHeader}`);
|
||||||
|
}
|
||||||
|
const rowId = row.getAttribute("data-row-id");
|
||||||
|
return cells.find((cell) => cell.getAttribute("data-row-id") === rowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {CellHelper<string[]>} */
|
||||||
|
export function getCellColorProperties(columnHeader, rowHeader = null, options) {
|
||||||
|
const cell = getCell(columnHeader, rowHeader, options);
|
||||||
|
const cssVarRegex = /(--[\w-]+)/g;
|
||||||
|
|
||||||
|
if (cell.style.background) {
|
||||||
|
return cell.style.background.match(cssVarRegex);
|
||||||
|
} else if (cell.style.backgroundColor) {
|
||||||
|
return cell.style.backgroundColor.match(cssVarRegex);
|
||||||
|
} else if (cell.style.backgroundImage) {
|
||||||
|
return cell.style.backgroundImage.match(cssVarRegex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} pill
|
||||||
|
* @returns {HTMLElement}
|
||||||
|
*/
|
||||||
|
export function getCellFromPill(pill) {
|
||||||
|
if (!pill.matches(SELECTORS.pillWrapper)) {
|
||||||
|
pill = pill.closest(SELECTORS.pillWrapper);
|
||||||
|
}
|
||||||
|
const { row, column } = getGridStyle(pill);
|
||||||
|
for (const cell of queryAll(SELECTORS.cell)) {
|
||||||
|
const { row: cellRow, column: cellColumn } = getGridStyle(cell);
|
||||||
|
if (row[0] < cellRow[1] && column[0] < cellColumn[1]) {
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Could not find hoverable cell for pill "${queryText(pill)}".`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} str
|
||||||
|
*/
|
||||||
|
function parseNumber(str) {
|
||||||
|
return parseInt(str.match(/\d+/)?.[0]) || 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} selector
|
||||||
|
*/
|
||||||
|
function getHeaders(selector) {
|
||||||
|
const groupHeaders = [];
|
||||||
|
for (const el of queryAll(selector)) {
|
||||||
|
const { column: range } = getGridStyle(el);
|
||||||
|
groupHeaders.push({
|
||||||
|
range,
|
||||||
|
title: el.textContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return groupHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGridContent() {
|
||||||
|
const columnHeaders = getHeaders(SELECTORS.columnHeader);
|
||||||
|
const groupHeaders = getHeaders(SELECTORS.groupHeader);
|
||||||
|
const range = queryAllTexts(SELECTORS.rangeMenuToggler)[0] || null;
|
||||||
|
const viewTitle = queryAllTexts(".o_gantt_title")[0] || null;
|
||||||
|
const colsRange = queryFirst(SELECTORS.columnHeader)
|
||||||
|
.style.getPropertyValue("grid-column")
|
||||||
|
.split("/");
|
||||||
|
const cellParts = parseNumber(colsRange[1]) - parseNumber(colsRange[0]);
|
||||||
|
const pillEls = new Set(queryAll(`${SELECTORS.cellContainer} ${SELECTORS.pillWrapper}`));
|
||||||
|
const rowEls = queryAll(`.o_gantt_row_headers > ${SELECTORS.rowHeader}`);
|
||||||
|
const singleRowMode = rowEls.length === 0;
|
||||||
|
if (singleRowMode) {
|
||||||
|
rowEls.push(document.createElement("div"));
|
||||||
|
}
|
||||||
|
const totalRow = queryFirst(SELECTORS.rowTotal);
|
||||||
|
const totalPillEls = new Set(queryAll(`.o_gantt_row_total ${SELECTORS.pillWrapper}`));
|
||||||
|
if (totalRow) {
|
||||||
|
totalRow._isTotal = true;
|
||||||
|
rowEls.push(totalRow);
|
||||||
|
}
|
||||||
|
const rows = [];
|
||||||
|
for (const rowEl of rowEls) {
|
||||||
|
const isGroup = rowEl.classList.contains(CLASSES.group);
|
||||||
|
const { row: gridRow } = getGridStyle(rowEl);
|
||||||
|
const row = singleRowMode ? {} : { title: queryText(rowEl) };
|
||||||
|
if (isGroup) {
|
||||||
|
row.isGroup = true;
|
||||||
|
}
|
||||||
|
if (rowEl._isTotal) {
|
||||||
|
row.isTotalRow = true;
|
||||||
|
}
|
||||||
|
const pills = [];
|
||||||
|
for (const pillEl of rowEl._isTotal ? totalPillEls : pillEls) {
|
||||||
|
const pillRowLevel = parseNumber(pillEl.style.gridRowStart);
|
||||||
|
const { column: gridColumn } = getGridStyle(pillEl);
|
||||||
|
const pillInRow = pillRowLevel >= gridRow[0] && pillRowLevel < gridRow[1];
|
||||||
|
if (singleRowMode || pillInRow || rowEl._isTotal) {
|
||||||
|
let start = columnHeaders.find(
|
||||||
|
(header) => gridColumn[0] >= header.range[0] && gridColumn[0] < header.range[1]
|
||||||
|
)?.title;
|
||||||
|
let end = columnHeaders.find(
|
||||||
|
(header) => gridColumn[1] > header.range[0] && gridColumn[1] <= header.range[1]
|
||||||
|
)?.title;
|
||||||
|
const startPart = (gridColumn[0] - 1) % cellParts;
|
||||||
|
const endPart = (gridColumn[1] - 1) % cellParts;
|
||||||
|
if (startPart && start) {
|
||||||
|
start += ` (${startPart}/${cellParts})`;
|
||||||
|
}
|
||||||
|
if (endPart && end) {
|
||||||
|
end += ` (${endPart}/${cellParts})`;
|
||||||
|
}
|
||||||
|
const pill = {
|
||||||
|
title: queryText(pillEl),
|
||||||
|
colSpan: `${start || "Out of bounds (" + gridColumn[0] + ")"} ${
|
||||||
|
start
|
||||||
|
? groupHeaders.find(
|
||||||
|
(header) =>
|
||||||
|
gridColumn[0] >= header.range[0] &&
|
||||||
|
gridColumn[0] < header.range[1]
|
||||||
|
).title
|
||||||
|
: ""
|
||||||
|
} -> ${end || "Out of bounds (" + gridColumn[1] + ")"} ${
|
||||||
|
end
|
||||||
|
? groupHeaders.find(
|
||||||
|
(header) =>
|
||||||
|
gridColumn[1] > header.range[0] &&
|
||||||
|
gridColumn[1] <= header.range[1]
|
||||||
|
).title
|
||||||
|
: ""
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
if (!isGroup) {
|
||||||
|
pill.level = singleRowMode ? pillRowLevel - 1 : pillRowLevel - gridRow[0];
|
||||||
|
}
|
||||||
|
pills.push(pill);
|
||||||
|
pillEls.delete(pillEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pills.length) {
|
||||||
|
row.pills = pills;
|
||||||
|
}
|
||||||
|
rows.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { columnHeaders, groupHeaders, range, rows, viewTitle };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} el
|
||||||
|
*/
|
||||||
|
export function getGridStyle(el) {
|
||||||
|
/**
|
||||||
|
* @param {"row" | "column"} prop
|
||||||
|
* @returns {[number, number]}
|
||||||
|
*/
|
||||||
|
const getGridProp = (prop) => {
|
||||||
|
return [
|
||||||
|
parseNumber(style.getPropertyValue(`grid-${prop}-start`)),
|
||||||
|
parseNumber(style.getPropertyValue(`grid-${prop}-end`)),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const style = getComputedStyle(el);
|
||||||
|
|
||||||
|
return {
|
||||||
|
row: getGridProp("row"),
|
||||||
|
column: getGridProp("column"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCellPositionOffset(cell, part) {
|
||||||
|
const position = { x: 1 };
|
||||||
|
if (part > 1) {
|
||||||
|
const rect = cell.getBoundingClientRect();
|
||||||
|
// Calculate cell parts
|
||||||
|
const colsRange = queryFirst(SELECTORS.columnHeader)
|
||||||
|
.style.getPropertyValue("grid-column")
|
||||||
|
.split("/");
|
||||||
|
const cellParts = parseNumber(colsRange[1]) - parseNumber(colsRange[0]);
|
||||||
|
const partWidth = rect.width / cellParts;
|
||||||
|
position.x += Math.ceil(partWidth * (part - 1));
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} cell
|
||||||
|
* @param {CellHelperOptions} [options]
|
||||||
|
*/
|
||||||
|
async function hoverCell(cell, options) {
|
||||||
|
const part = options?.part ?? 1;
|
||||||
|
await hover(cell, { position: getCellPositionOffset(cell, part), relative: true });
|
||||||
|
await animationFrame();
|
||||||
|
await advanceTime(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hovers a cell found from given grid coordinates.
|
||||||
|
* @type {CellHelper<Promise<HTMLElement>>}
|
||||||
|
*/
|
||||||
|
export async function hoverGridCell(columnHeader, rowHeader = null, options) {
|
||||||
|
const cell = getCell(columnHeader, rowHeader, options);
|
||||||
|
await hoverCell(cell, options);
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click on a cell found from given grid coordinates.
|
||||||
|
* @type {CellHelper<Promise<HTMLElement>>}
|
||||||
|
*/
|
||||||
|
export async function clickCell(columnHeader, rowHeader = null, options) {
|
||||||
|
const cell = getCell(columnHeader, rowHeader, options);
|
||||||
|
await contains(cell).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hovers a cell found from a pill element.
|
||||||
|
* @param {HTMLElement} pill
|
||||||
|
*/
|
||||||
|
async function hoverPillCell(pill) {
|
||||||
|
const cell = getCellFromPill(pill);
|
||||||
|
const pStart = getGridStyle(pill).column[0];
|
||||||
|
const cellStyle = getGridStyle(cell).column[0];
|
||||||
|
const part = pStart - cellStyle + 1;
|
||||||
|
await hoverCell(cell, { part });
|
||||||
|
return { cell, part };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} pill
|
||||||
|
* @param {"start" | "end"} side
|
||||||
|
* @param {number | { x: number }} deltaOrPosition
|
||||||
|
* @param {boolean} [shouldDrop=true]
|
||||||
|
*/
|
||||||
|
export async function resizePill(pill, side, deltaOrPosition, shouldDrop = true) {
|
||||||
|
await hover(pill);
|
||||||
|
|
||||||
|
const { row, column } = getGridStyle(pill);
|
||||||
|
|
||||||
|
// Calculate cell parts
|
||||||
|
const colsRange = queryFirst(SELECTORS.columnHeader)
|
||||||
|
.style.getPropertyValue("grid-column")
|
||||||
|
.split("/");
|
||||||
|
const cellParts = parseNumber(colsRange[1]) - parseNumber(colsRange[0]);
|
||||||
|
|
||||||
|
// Calculate delta or position
|
||||||
|
const delta = typeof deltaOrPosition === "object" ? 0 : deltaOrPosition;
|
||||||
|
const position = typeof deltaOrPosition === "object" ? deltaOrPosition : {};
|
||||||
|
const targetColumn = (side === "start" ? column[0] : column[1]) + delta * cellParts;
|
||||||
|
|
||||||
|
let targetCell;
|
||||||
|
let targetPart;
|
||||||
|
for (const cell of queryAll(SELECTORS.cell)) {
|
||||||
|
const { row: cRow, column: cCol } = getGridStyle(cell);
|
||||||
|
if (cRow[0] > row[0] || cRow[1] < row[1]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cCol[1] < targetColumn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetColumn < cCol[0]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetCell = cell;
|
||||||
|
targetPart = targetColumn - cCol[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign position if delta
|
||||||
|
if (!position.x) {
|
||||||
|
const { width } = targetCell.getBoundingClientRect();
|
||||||
|
position.x = targetPart * Math.floor(width / cellParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual drag actions
|
||||||
|
const { moveTo, drop } = await contains(
|
||||||
|
pill.querySelector(
|
||||||
|
side === "start" ? SELECTORS.resizeStartHandle : SELECTORS.resizeEndHandle
|
||||||
|
)
|
||||||
|
).drag();
|
||||||
|
|
||||||
|
await moveTo(targetCell, { position, relative: true });
|
||||||
|
|
||||||
|
if (shouldDrop) {
|
||||||
|
await drop();
|
||||||
|
} else {
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {PillHelper<HTMLElement>} */
|
||||||
|
export function getPill(text, options) {
|
||||||
|
return queryOne(`${SELECTORS.pill}:contains(${text}):eq(${(options?.nth ?? 1) - 1})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {PillHelper<HTMLElement>} */
|
||||||
|
export function getPillWrapper(text, options) {
|
||||||
|
return getPill(text, options).closest(SELECTORS.pillWrapper);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from . import test_acl
|
||||||
|
|
@ -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'))
|
||||||
Loading…
Reference in New Issue