From bfd7890cbc029daa77c94489a3106fe12e315e0d Mon Sep 17 00:00:00 2001 From: Pranay Date: Wed, 3 Dec 2025 10:16:19 +0530 Subject: [PATCH] Documents preview, binary field widget, menu control center changes --- .../menu_control_center/__init__.py | 2 +- .../menu_control_center/__manifest__.py | 4 +- .../controllers/__init__.py | 1 + .../menu_control_center/controllers/main.py | 26 + .../menu_control_center/models/__init__.py | 1 + .../menu_control_center/models/masters.py | 95 +++ .../menu_control_center/models/menu.py | 5 +- .../menu_control_center/models/models.py | 160 ++++- .../security/ir.model.access.csv | 5 +- .../menu_control_center/views/login.xml | 17 + .../menu_control_center/views/masters.xml | 76 ++ .../views/menu_access_control_views.xml | 50 +- addons_extensions/onlyoffice_odoo/__init__.py | 2 + .../onlyoffice_odoo/__manifest__.py | 37 + .../onlyoffice_odoo/controllers/__init__.py | 1 + .../controllers/controllers.py | 654 ++++++++++++++++++ .../onlyoffice_odoo/doc/index.rst | 31 + .../onlyoffice_odoo/doc/settings.png | Bin 0 -> 44900 bytes addons_extensions/onlyoffice_odoo/i18n/de.po | 368 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/en.po | 361 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/es.po | 368 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/fr.po | 368 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/it.po | 368 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/ja.po | 379 ++++++++++ .../onlyoffice_odoo/i18n/pt_BR.po | 367 ++++++++++ addons_extensions/onlyoffice_odoo/i18n/ru.po | 375 ++++++++++ .../onlyoffice_odoo/i18n/zh_CN.po | 367 ++++++++++ .../onlyoffice_odoo/models/__init__.py | 2 + .../onlyoffice_odoo/models/onlyoffice_odoo.py | 21 + .../models/res_config_settings.py | 97 +++ .../onlyoffice_odoo/pyproject.toml | 3 + .../static/assets/document_formats/AUTHORS.md | 4 + .../assets/document_formats/CHANGELOG.md | 35 + .../static/assets/document_formats/LICENSE | 201 ++++++ .../static/assets/document_formats/README.md | 86 +++ .../onlyoffice-docs-formats.json | 597 ++++++++++++++++ .../assets/document_templates/AUTHORS.md | 3 + .../static/assets/document_templates/LICENSE | 201 ++++++ .../assets/document_templates/README.md | 12 + .../assets/document_templates/ar-SA/new.docx | Bin 0 -> 9271 bytes .../assets/document_templates/ar-SA/new.pdf | Bin 0 -> 10637 bytes .../assets/document_templates/ar-SA/new.pptx | Bin 0 -> 27808 bytes .../assets/document_templates/ar-SA/new.xlsx | Bin 0 -> 5661 bytes .../document_templates/az-Latn-AZ/new.docx | Bin 0 -> 6950 bytes .../document_templates/az-Latn-AZ/new.pdf | Bin 0 -> 10437 bytes .../document_templates/az-Latn-AZ/new.pptx | Bin 0 -> 35268 bytes .../document_templates/az-Latn-AZ/new.xlsx | Bin 0 -> 6310 bytes .../assets/document_templates/bg-BG/new.docx | Bin 0 -> 6688 bytes .../assets/document_templates/bg-BG/new.pdf | Bin 0 -> 10283 bytes .../assets/document_templates/bg-BG/new.pptx | Bin 0 -> 30614 bytes .../assets/document_templates/bg-BG/new.xlsx | Bin 0 -> 6337 bytes .../assets/document_templates/ca-ES/new.docx | Bin 0 -> 6995 bytes .../assets/document_templates/ca-ES/new.pdf | Bin 0 -> 10556 bytes .../assets/document_templates/ca-ES/new.pptx | Bin 0 -> 27128 bytes .../assets/document_templates/ca-ES/new.xlsx | Bin 0 -> 5568 bytes .../assets/document_templates/cs-CZ/new.docx | Bin 0 -> 6946 bytes .../assets/document_templates/cs-CZ/new.pdf | Bin 0 -> 10433 bytes .../assets/document_templates/cs-CZ/new.pptx | Bin 0 -> 33098 bytes .../assets/document_templates/cs-CZ/new.xlsx | Bin 0 -> 5613 bytes .../assets/document_templates/da-DK/new.docx | Bin 0 -> 6995 bytes .../assets/document_templates/da-DK/new.pdf | Bin 0 -> 10557 bytes .../assets/document_templates/da-DK/new.pptx | Bin 0 -> 26691 bytes .../assets/document_templates/da-DK/new.xlsx | Bin 0 -> 5568 bytes .../assets/document_templates/de-DE/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/de-DE/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/de-DE/new.pptx | Bin 0 -> 32875 bytes .../assets/document_templates/de-DE/new.xlsx | Bin 0 -> 6345 bytes .../document_templates/default/new.docx | Bin 0 -> 6940 bytes .../assets/document_templates/default/new.pdf | Bin 0 -> 10427 bytes .../document_templates/default/new.pptx | Bin 0 -> 34699 bytes .../document_templates/default/new.xlsx | Bin 0 -> 6352 bytes .../assets/document_templates/el-GR/new.docx | Bin 0 -> 6943 bytes .../assets/document_templates/el-GR/new.pdf | Bin 0 -> 10430 bytes .../assets/document_templates/el-GR/new.pptx | Bin 0 -> 34290 bytes .../assets/document_templates/el-GR/new.xlsx | Bin 0 -> 6319 bytes .../assets/document_templates/en-GB/new.docx | Bin 0 -> 6942 bytes .../assets/document_templates/en-GB/new.pdf | Bin 0 -> 10429 bytes .../assets/document_templates/en-GB/new.pptx | Bin 0 -> 34696 bytes .../assets/document_templates/en-GB/new.xlsx | Bin 0 -> 6345 bytes .../assets/document_templates/en-US/new.docx | Bin 0 -> 7726 bytes .../assets/document_templates/en-US/new.pdf | Bin 0 -> 10266 bytes .../assets/document_templates/en-US/new.pptx | Bin 0 -> 34699 bytes .../assets/document_templates/en-US/new.xlsx | Bin 0 -> 5731 bytes .../assets/document_templates/es-ES/new.docx | Bin 0 -> 6943 bytes .../assets/document_templates/es-ES/new.pdf | Bin 0 -> 10430 bytes .../assets/document_templates/es-ES/new.pptx | Bin 0 -> 33000 bytes .../assets/document_templates/es-ES/new.xlsx | Bin 0 -> 6303 bytes .../assets/document_templates/eu-ES/new.docx | Bin 0 -> 7748 bytes .../assets/document_templates/eu-ES/new.pdf | Bin 0 -> 10430 bytes .../assets/document_templates/eu-ES/new.pptx | Bin 0 -> 34917 bytes .../assets/document_templates/eu-ES/new.xlsx | Bin 0 -> 6341 bytes .../assets/document_templates/fi-FI/new.docx | Bin 0 -> 7699 bytes .../assets/document_templates/fi-FI/new.pdf | Bin 0 -> 10320 bytes .../assets/document_templates/fi-FI/new.pptx | Bin 0 -> 27407 bytes .../assets/document_templates/fi-FI/new.xlsx | Bin 0 -> 6372 bytes .../assets/document_templates/fr-FR/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/fr-FR/new.pdf | Bin 0 -> 10429 bytes .../assets/document_templates/fr-FR/new.pptx | Bin 0 -> 33058 bytes .../assets/document_templates/fr-FR/new.xlsx | Bin 0 -> 6304 bytes .../assets/document_templates/gl-ES/new.docx | Bin 0 -> 7925 bytes .../assets/document_templates/gl-ES/new.pdf | Bin 0 -> 10430 bytes .../assets/document_templates/gl-ES/new.pptx | Bin 0 -> 33034 bytes .../assets/document_templates/gl-ES/new.xlsx | Bin 0 -> 6340 bytes .../assets/document_templates/he-IL/new.docx | Bin 0 -> 7029 bytes .../assets/document_templates/he-IL/new.pdf | Bin 0 -> 10434 bytes .../assets/document_templates/he-IL/new.pptx | Bin 0 -> 32775 bytes .../assets/document_templates/he-IL/new.xlsx | Bin 0 -> 5677 bytes .../assets/document_templates/hu-HU/new.docx | Bin 0 -> 6996 bytes .../assets/document_templates/hu-HU/new.pdf | Bin 0 -> 10398 bytes .../assets/document_templates/hu-HU/new.pptx | Bin 0 -> 27074 bytes .../assets/document_templates/hu-HU/new.xlsx | Bin 0 -> 5571 bytes .../assets/document_templates/hy-AM/new.docx | Bin 0 -> 7763 bytes .../assets/document_templates/hy-AM/new.pdf | Bin 0 -> 10444 bytes .../assets/document_templates/hy-AM/new.pptx | Bin 0 -> 35958 bytes .../assets/document_templates/hy-AM/new.xlsx | Bin 0 -> 6354 bytes .../assets/document_templates/id-ID/new.docx | Bin 0 -> 6995 bytes .../assets/document_templates/id-ID/new.pdf | Bin 0 -> 10557 bytes .../assets/document_templates/id-ID/new.pptx | Bin 0 -> 26835 bytes .../assets/document_templates/id-ID/new.xlsx | Bin 0 -> 5567 bytes .../assets/document_templates/it-IT/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/it-IT/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/it-IT/new.pptx | Bin 0 -> 32950 bytes .../assets/document_templates/it-IT/new.xlsx | Bin 0 -> 6303 bytes .../assets/document_templates/ja-JP/new.docx | Bin 0 -> 8375 bytes .../assets/document_templates/ja-JP/new.pdf | Bin 0 -> 11251 bytes .../assets/document_templates/ja-JP/new.pptx | Bin 0 -> 33025 bytes .../assets/document_templates/ja-JP/new.xlsx | Bin 0 -> 7840 bytes .../assets/document_templates/ko-KR/new.docx | Bin 0 -> 6937 bytes .../assets/document_templates/ko-KR/new.pdf | Bin 0 -> 10424 bytes .../assets/document_templates/ko-KR/new.pptx | Bin 0 -> 33819 bytes .../assets/document_templates/ko-KR/new.xlsx | Bin 0 -> 6314 bytes .../assets/document_templates/lv-LV/new.docx | Bin 0 -> 6945 bytes .../assets/document_templates/lv-LV/new.pdf | Bin 0 -> 10432 bytes .../assets/document_templates/lv-LV/new.pptx | Bin 0 -> 32892 bytes .../assets/document_templates/lv-LV/new.xlsx | Bin 0 -> 6302 bytes .../assets/document_templates/ms-MY/new.docx | Bin 0 -> 6946 bytes .../assets/document_templates/ms-MY/new.pdf | Bin 0 -> 10433 bytes .../assets/document_templates/ms-MY/new.pptx | Bin 0 -> 34744 bytes .../assets/document_templates/ms-MY/new.xlsx | Bin 0 -> 6341 bytes .../assets/document_templates/nb-NO/new.docx | Bin 0 -> 7698 bytes .../assets/document_templates/nb-NO/new.pdf | Bin 0 -> 10320 bytes .../assets/document_templates/nb-NO/new.pptx | Bin 0 -> 27115 bytes .../assets/document_templates/nb-NO/new.xlsx | Bin 0 -> 5640 bytes .../assets/document_templates/nl-NL/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/nl-NL/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/nl-NL/new.pptx | Bin 0 -> 32635 bytes .../assets/document_templates/nl-NL/new.xlsx | Bin 0 -> 6339 bytes .../assets/document_templates/pl-PL/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/pl-PL/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/pl-PL/new.pptx | Bin 0 -> 33016 bytes .../assets/document_templates/pl-PL/new.xlsx | Bin 0 -> 6303 bytes .../assets/document_templates/pt-BR/new.docx | Bin 0 -> 8504 bytes .../assets/document_templates/pt-BR/new.pdf | Bin 0 -> 11380 bytes .../assets/document_templates/pt-BR/new.pptx | Bin 0 -> 33062 bytes .../assets/document_templates/pt-BR/new.xlsx | Bin 0 -> 6477 bytes .../assets/document_templates/pt-PT/new.docx | Bin 0 -> 8504 bytes .../assets/document_templates/pt-PT/new.pdf | Bin 0 -> 11380 bytes .../assets/document_templates/pt-PT/new.pptx | Bin 0 -> 32980 bytes .../assets/document_templates/pt-PT/new.xlsx | Bin 0 -> 6517 bytes .../assets/document_templates/ro-RO/new.docx | Bin 0 -> 6996 bytes .../assets/document_templates/ro-RO/new.pdf | Bin 0 -> 10557 bytes .../assets/document_templates/ro-RO/new.pptx | Bin 0 -> 26984 bytes .../assets/document_templates/ro-RO/new.xlsx | Bin 0 -> 5568 bytes .../assets/document_templates/ru-RU/new.docx | Bin 0 -> 6944 bytes .../assets/document_templates/ru-RU/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/ru-RU/new.pptx | Bin 0 -> 33670 bytes .../assets/document_templates/ru-RU/new.xlsx | Bin 0 -> 6360 bytes .../assets/document_templates/si-LK/new.docx | Bin 0 -> 8497 bytes .../assets/document_templates/si-LK/new.pdf | Bin 0 -> 11373 bytes .../assets/document_templates/si-LK/new.pptx | Bin 0 -> 34458 bytes .../assets/document_templates/si-LK/new.xlsx | Bin 0 -> 6548 bytes .../assets/document_templates/sk-SK/new.docx | Bin 0 -> 8373 bytes .../assets/document_templates/sk-SK/new.pdf | Bin 0 -> 11249 bytes .../assets/document_templates/sk-SK/new.pptx | Bin 0 -> 34947 bytes .../assets/document_templates/sk-SK/new.xlsx | Bin 0 -> 6302 bytes .../assets/document_templates/sl-SI/new.docx | Bin 0 -> 7698 bytes .../assets/document_templates/sl-SI/new.pdf | Bin 0 -> 10320 bytes .../assets/document_templates/sl-SI/new.pptx | Bin 0 -> 27177 bytes .../assets/document_templates/sl-SI/new.xlsx | Bin 0 -> 6371 bytes .../assets/document_templates/sq-AL/new.docx | Bin 0 -> 6659 bytes .../assets/document_templates/sq-AL/new.pdf | Bin 0 -> 10405 bytes .../assets/document_templates/sq-AL/new.pptx | Bin 0 -> 31494 bytes .../assets/document_templates/sq-AL/new.xlsx | Bin 0 -> 5608 bytes .../document_templates/sr-Cyrl-RS/new.docx | Bin 0 -> 7954 bytes .../document_templates/sr-Cyrl-RS/new.pdf | Bin 0 -> 10324 bytes .../document_templates/sr-Cyrl-RS/new.pptx | Bin 0 -> 30027 bytes .../document_templates/sr-Cyrl-RS/new.xlsx | Bin 0 -> 6424 bytes .../document_templates/sr-Latn-RS/new.docx | Bin 0 -> 7702 bytes .../document_templates/sr-Latn-RS/new.pdf | Bin 0 -> 10782 bytes .../document_templates/sr-Latn-RS/new.pptx | Bin 0 -> 28767 bytes .../document_templates/sr-Latn-RS/new.xlsx | Bin 0 -> 6370 bytes .../assets/document_templates/sv-SE/new.docx | Bin 0 -> 7899 bytes .../assets/document_templates/sv-SE/new.pdf | Bin 0 -> 10775 bytes .../assets/document_templates/sv-SE/new.pptx | Bin 0 -> 29047 bytes .../assets/document_templates/sv-SE/new.xlsx | Bin 0 -> 6370 bytes .../assets/document_templates/tr-TR/new.docx | Bin 0 -> 6956 bytes .../assets/document_templates/tr-TR/new.pdf | Bin 0 -> 10443 bytes .../assets/document_templates/tr-TR/new.pptx | Bin 0 -> 33275 bytes .../assets/document_templates/tr-TR/new.xlsx | Bin 0 -> 6341 bytes .../assets/document_templates/uk-UA/new.docx | Bin 0 -> 6945 bytes .../assets/document_templates/uk-UA/new.pdf | Bin 0 -> 10431 bytes .../assets/document_templates/uk-UA/new.pptx | Bin 0 -> 34725 bytes .../assets/document_templates/uk-UA/new.xlsx | Bin 0 -> 6320 bytes .../assets/document_templates/ur-PK/new.docx | Bin 0 -> 9137 bytes .../assets/document_templates/ur-PK/new.pdf | Bin 0 -> 10784 bytes .../assets/document_templates/ur-PK/new.pptx | Bin 0 -> 28318 bytes .../assets/document_templates/ur-PK/new.xlsx | Bin 0 -> 5294 bytes .../assets/document_templates/vi-VN/new.docx | Bin 0 -> 7839 bytes .../assets/document_templates/vi-VN/new.pdf | Bin 0 -> 10526 bytes .../assets/document_templates/vi-VN/new.pptx | Bin 0 -> 33595 bytes .../assets/document_templates/vi-VN/new.xlsx | Bin 0 -> 6311 bytes .../assets/document_templates/zh-CN/new.docx | Bin 0 -> 7839 bytes .../assets/document_templates/zh-CN/new.pdf | Bin 0 -> 10526 bytes .../assets/document_templates/zh-CN/new.pptx | Bin 0 -> 34707 bytes .../assets/document_templates/zh-CN/new.xlsx | Bin 0 -> 6322 bytes .../assets/document_templates/zh-TW/new.docx | Bin 0 -> 7839 bytes .../assets/document_templates/zh-TW/new.pdf | Bin 0 -> 10526 bytes .../assets/document_templates/zh-TW/new.pptx | Bin 0 -> 35545 bytes .../assets/document_templates/zh-TW/new.xlsx | Bin 0 -> 6352 bytes .../static/description/discuss_section.png | Bin 0 -> 377068 bytes .../static/description/document.png | Bin 0 -> 425495 bytes .../static/description/editor_icons/cell.ico | Bin 0 -> 4286 bytes .../description/editor_icons/diagram.ico | Bin 0 -> 4286 bytes .../static/description/editor_icons/pdf.ico | Bin 0 -> 4286 bytes .../static/description/editor_icons/slide.ico | Bin 0 -> 4286 bytes .../static/description/editor_icons/word.ico | Bin 0 -> 4286 bytes .../static/description/icon.png | Bin 0 -> 2175 bytes .../static/description/index.html | 67 ++ .../static/description/main_screenshot.png | Bin 0 -> 14690 bytes .../static/description/sales_section.png | Bin 0 -> 77820 bytes .../static/description/settings.png | Bin 0 -> 447295 bytes .../static/src/actions/documents_action.js | 70 ++ .../static/src/actions/documents_action.xml | 25 + .../attachment_card_onlyoffice.xml | 24 + .../static/src/css/form_gallery.scss | 57 ++ .../src/css/onlyoffice_link_container.png | Bin 0 -> 27329 bytes .../css/onlyoffice_link_container_mobile.png | Bin 0 -> 22957 bytes .../static/src/css/onlyoffice_preview.scss | 47 ++ .../src/css/res_config_settings_views.scss | 44 ++ .../src/models/attachment_card_onlyoffice.js | 71 ++ .../src/views/form_gallery/form_gallery.js | 274 ++++++++ .../src/views/form_gallery/form_gallery.xml | 174 +++++ .../src/views/preview/onlyoffice_preview.js | 51 ++ .../src/views/preview/onlyoffice_preview.xml | 19 + .../onlyoffice_odoo/static/svg/edit.svg | 5 + .../onlyoffice_odoo/static/svg/logo.svg | 15 + .../static/svg/onlyoffice_logo.svg | 15 + .../onlyoffice_odoo/utils/config_constants.py | 15 + .../onlyoffice_odoo/utils/config_utils.py | 130 ++++ .../onlyoffice_odoo/utils/file_utils.py | 138 ++++ .../onlyoffice_odoo/utils/format_utils.py | 42 ++ .../onlyoffice_odoo/utils/jwt_utils.py | 29 + .../onlyoffice_odoo/utils/url_utils.py | 14 + .../onlyoffice_odoo/utils/validation_utils.py | 183 +++++ .../views/res_config_settings_views.xml | 120 ++++ .../onlyoffice_odoo/views/templates.xml | 78 +++ .../view/project_stages.xml | 12 +- 257 files changed, 7418 insertions(+), 51 deletions(-) create mode 100644 addons_extensions/menu_control_center/controllers/__init__.py create mode 100644 addons_extensions/menu_control_center/controllers/main.py create mode 100644 addons_extensions/menu_control_center/models/masters.py create mode 100644 addons_extensions/menu_control_center/views/login.xml create mode 100644 addons_extensions/menu_control_center/views/masters.xml create mode 100644 addons_extensions/onlyoffice_odoo/__init__.py create mode 100644 addons_extensions/onlyoffice_odoo/__manifest__.py create mode 100644 addons_extensions/onlyoffice_odoo/controllers/__init__.py create mode 100644 addons_extensions/onlyoffice_odoo/controllers/controllers.py create mode 100644 addons_extensions/onlyoffice_odoo/doc/index.rst create mode 100644 addons_extensions/onlyoffice_odoo/doc/settings.png create mode 100644 addons_extensions/onlyoffice_odoo/i18n/de.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/en.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/es.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/fr.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/it.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/ja.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/pt_BR.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/ru.po create mode 100644 addons_extensions/onlyoffice_odoo/i18n/zh_CN.po create mode 100644 addons_extensions/onlyoffice_odoo/models/__init__.py create mode 100644 addons_extensions/onlyoffice_odoo/models/onlyoffice_odoo.py create mode 100644 addons_extensions/onlyoffice_odoo/models/res_config_settings.py create mode 100644 addons_extensions/onlyoffice_odoo/pyproject.toml create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_formats/AUTHORS.md create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_formats/CHANGELOG.md create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_formats/LICENSE create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_formats/README.md create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_formats/onlyoffice-docs-formats.json create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/AUTHORS.md create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/LICENSE create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/README.md create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ar-SA/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ar-SA/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ar-SA/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ar-SA/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/az-Latn-AZ/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/az-Latn-AZ/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/az-Latn-AZ/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/az-Latn-AZ/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/bg-BG/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/bg-BG/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/bg-BG/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/bg-BG/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ca-ES/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ca-ES/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ca-ES/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ca-ES/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/cs-CZ/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/cs-CZ/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/cs-CZ/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/cs-CZ/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/da-DK/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/da-DK/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/da-DK/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/da-DK/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/de-DE/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/de-DE/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/de-DE/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/de-DE/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/default/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/default/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/default/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/default/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/el-GR/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/el-GR/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/el-GR/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/el-GR/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-GB/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-GB/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-GB/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-GB/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-US/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-US/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-US/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/en-US/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/es-ES/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/es-ES/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/es-ES/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/es-ES/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/eu-ES/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/eu-ES/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/eu-ES/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/eu-ES/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fi-FI/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fi-FI/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fi-FI/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fi-FI/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fr-FR/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fr-FR/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fr-FR/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/fr-FR/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/gl-ES/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/gl-ES/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/gl-ES/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/gl-ES/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/he-IL/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/he-IL/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/he-IL/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/he-IL/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hu-HU/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hu-HU/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hu-HU/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hu-HU/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hy-AM/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hy-AM/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hy-AM/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/hy-AM/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/id-ID/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/id-ID/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/id-ID/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/id-ID/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/it-IT/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/it-IT/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/it-IT/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/it-IT/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ja-JP/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ja-JP/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ja-JP/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ja-JP/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ko-KR/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ko-KR/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ko-KR/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ko-KR/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/lv-LV/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/lv-LV/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/lv-LV/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/lv-LV/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ms-MY/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ms-MY/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ms-MY/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ms-MY/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nb-NO/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nb-NO/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nb-NO/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nb-NO/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nl-NL/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nl-NL/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nl-NL/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/nl-NL/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pl-PL/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pl-PL/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pl-PL/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pl-PL/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-BR/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-BR/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-BR/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-BR/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-PT/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-PT/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-PT/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/pt-PT/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ro-RO/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ro-RO/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ro-RO/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ro-RO/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ru-RU/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ru-RU/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ru-RU/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ru-RU/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/si-LK/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/si-LK/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/si-LK/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/si-LK/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sk-SK/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sk-SK/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sk-SK/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sk-SK/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sl-SI/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sl-SI/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sl-SI/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sl-SI/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sq-AL/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sq-AL/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sq-AL/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sq-AL/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Cyrl-RS/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Cyrl-RS/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Cyrl-RS/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Cyrl-RS/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Latn-RS/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Latn-RS/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Latn-RS/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sr-Latn-RS/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sv-SE/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sv-SE/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sv-SE/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/sv-SE/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/tr-TR/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/tr-TR/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/tr-TR/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/tr-TR/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/uk-UA/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/uk-UA/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/uk-UA/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/uk-UA/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ur-PK/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ur-PK/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ur-PK/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/ur-PK/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/vi-VN/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/vi-VN/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/vi-VN/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/vi-VN/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-CN/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-CN/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-CN/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-CN/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-TW/new.docx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-TW/new.pdf create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-TW/new.pptx create mode 100644 addons_extensions/onlyoffice_odoo/static/assets/document_templates/zh-TW/new.xlsx create mode 100644 addons_extensions/onlyoffice_odoo/static/description/discuss_section.png create mode 100644 addons_extensions/onlyoffice_odoo/static/description/document.png create mode 100644 addons_extensions/onlyoffice_odoo/static/description/editor_icons/cell.ico create mode 100644 addons_extensions/onlyoffice_odoo/static/description/editor_icons/diagram.ico create mode 100644 addons_extensions/onlyoffice_odoo/static/description/editor_icons/pdf.ico create mode 100644 addons_extensions/onlyoffice_odoo/static/description/editor_icons/slide.ico create mode 100644 addons_extensions/onlyoffice_odoo/static/description/editor_icons/word.ico create mode 100644 addons_extensions/onlyoffice_odoo/static/description/icon.png create mode 100644 addons_extensions/onlyoffice_odoo/static/description/index.html create mode 100644 addons_extensions/onlyoffice_odoo/static/description/main_screenshot.png create mode 100644 addons_extensions/onlyoffice_odoo/static/description/sales_section.png create mode 100644 addons_extensions/onlyoffice_odoo/static/description/settings.png create mode 100644 addons_extensions/onlyoffice_odoo/static/src/actions/documents_action.js create mode 100644 addons_extensions/onlyoffice_odoo/static/src/actions/documents_action.xml create mode 100644 addons_extensions/onlyoffice_odoo/static/src/components/attachment_card_onlyoffice/attachment_card_onlyoffice.xml create mode 100644 addons_extensions/onlyoffice_odoo/static/src/css/form_gallery.scss create mode 100644 addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container.png create mode 100644 addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container_mobile.png create mode 100644 addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_preview.scss create mode 100644 addons_extensions/onlyoffice_odoo/static/src/css/res_config_settings_views.scss create mode 100644 addons_extensions/onlyoffice_odoo/static/src/models/attachment_card_onlyoffice.js create mode 100644 addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.js create mode 100644 addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.xml create mode 100644 addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.js create mode 100644 addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.xml create mode 100644 addons_extensions/onlyoffice_odoo/static/svg/edit.svg create mode 100644 addons_extensions/onlyoffice_odoo/static/svg/logo.svg create mode 100644 addons_extensions/onlyoffice_odoo/static/svg/onlyoffice_logo.svg create mode 100644 addons_extensions/onlyoffice_odoo/utils/config_constants.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/config_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/file_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/format_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/jwt_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/url_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/utils/validation_utils.py create mode 100644 addons_extensions/onlyoffice_odoo/views/res_config_settings_views.xml create mode 100644 addons_extensions/onlyoffice_odoo/views/templates.xml diff --git a/addons_extensions/menu_control_center/__init__.py b/addons_extensions/menu_control_center/__init__.py index 9a7e03ede..a66486a18 100644 --- a/addons_extensions/menu_control_center/__init__.py +++ b/addons_extensions/menu_control_center/__init__.py @@ -1 +1 @@ -from . import models \ No newline at end of file +from . import controllers, models \ No newline at end of file diff --git a/addons_extensions/menu_control_center/__manifest__.py b/addons_extensions/menu_control_center/__manifest__.py index 385729848..25a53fdeb 100644 --- a/addons_extensions/menu_control_center/__manifest__.py +++ b/addons_extensions/menu_control_center/__manifest__.py @@ -10,10 +10,12 @@ 'category': 'Tools', 'author': 'PRANAY', 'website': 'https://ftprotech.in', - 'depends': ['base','hr'], + 'depends': ['base','hr','web','one2many_search_widget'], 'data': [ 'security/ir.model.access.csv', 'data/data.xml', + 'views/masters.xml', + 'views/login.xml', 'views/menu_access_control_views.xml', ], # 'assets': { diff --git a/addons_extensions/menu_control_center/controllers/__init__.py b/addons_extensions/menu_control_center/controllers/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/addons_extensions/menu_control_center/controllers/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/addons_extensions/menu_control_center/controllers/main.py b/addons_extensions/menu_control_center/controllers/main.py new file mode 100644 index 000000000..cb59c6a73 --- /dev/null +++ b/addons_extensions/menu_control_center/controllers/main.py @@ -0,0 +1,26 @@ +from odoo import http, _ +from odoo.http import request +from odoo.addons.web.controllers.home import Home +import werkzeug + + +class CustomMasterLogin(Home): + + @http.route() + def web_login(self, *args, **kw): + # Call the original Odoo login + master_selected = kw.get('master_select') + + response = super(CustomMasterLogin, self).web_login(*args, **kw) + + # We only modify the QWeb response (GET request) + if response.is_qweb: + # load your masters + masters = request.env['master.control'].sudo().search([]) + response.qcontext['masters'] = masters + + # After successful login + if request.session.uid and master_selected: + request.session['active_master'] = master_selected + + return response diff --git a/addons_extensions/menu_control_center/models/__init__.py b/addons_extensions/menu_control_center/models/__init__.py index 52e35f001..3e41a1d7b 100644 --- a/addons_extensions/menu_control_center/models/__init__.py +++ b/addons_extensions/menu_control_center/models/__init__.py @@ -1,2 +1,3 @@ +from . import masters from . import models from . import menu \ No newline at end of file diff --git a/addons_extensions/menu_control_center/models/masters.py b/addons_extensions/menu_control_center/models/masters.py new file mode 100644 index 000000000..93b4f4f5d --- /dev/null +++ b/addons_extensions/menu_control_center/models/masters.py @@ -0,0 +1,95 @@ +from odoo import models, fields, _ + +class MasterControl(models.Model): + _name = 'master.control' + _description = 'Master Control' + + sequence = fields.Integer() + name = fields.Char(string='Master Name', required=True) + code = fields.Char(string='Code', required=True) + default_show = fields.Boolean(default=True) + access_group_ids = fields.One2many('group.access.line','master_control_id',string='Roles') + + + def action_generate_groups(self): + """Generate category → groups list""" + for rec in self: + + # Clear old groups + rec.access_group_ids.unlink() + + groups = self.env['res.groups'].sudo().search([],order='category_id') + show_group = True if rec.default_show else False + print(show_group) + for grp in groups: + self.env['group.access.line'].create({ + 'master_control_id': rec.id, + 'group_id': grp.id, + 'show_group': show_group, + }) + + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': _('Success'), + 'message': _('Groups generated successfully!'), + 'type': 'success', + } + } + + # ----------------------------------------- + # UPDATE GROUPS (Detect new groups) + # ----------------------------------------- + def action_update_groups(self): + for rec in self: + created_count = 0 + + existing_ids = set(rec.access_group_ids.mapped('group_id.id')) + + categories = self.env['ir.module.category'].search([]) + + for category in categories: + groups = self.env['res.groups'].search([ + ('category_id', '=', category.id) + ]) + + for grp in groups: + # create only missing group + if grp.id not in existing_ids: + rec.access_group_ids.create({ + 'master_control_id': rec.id, + 'category_id': category.id, + 'group_id': grp.id, + 'show_group': True if rec.default_show else False, + }) + created_count += 1 + existing_ids.add(grp.id) + + if created_count: + message = f"Added {created_count} new groups." + msg_type = "success" + else: + message = "No new groups found." + msg_type = "info" + + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': _('Group Update'), + 'message': _(message), + 'type': msg_type, + } + } + + +class GroupsAccessLine(models.Model): + _name = 'group.access.line' + _description = 'Group Access Line' + _rec_name = 'group_id' + + category_id = fields.Many2one('ir.module.category', related='group_id.category_id') + group_id = fields.Many2one('res.groups', string="Role") + show_group = fields.Boolean(string="Show", default=True) + master_control_id = fields.Many2one('master.control') \ No newline at end of file diff --git a/addons_extensions/menu_control_center/models/menu.py b/addons_extensions/menu_control_center/models/menu.py index c82f101c0..8a0e1f736 100644 --- a/addons_extensions/menu_control_center/models/menu.py +++ b/addons_extensions/menu_control_center/models/menu.py @@ -17,7 +17,10 @@ class IrUiMenu(models.Model): group_ids = set(self.env.user._get_group_ids()) if not debug: - hide_menus_list = self.env['menu.access.control'].sudo().search([('user_ids','ilike',self.env.user.id)]).access_menu_line_ids.filtered(lambda menu: not(menu.is_main_menu)).menu_id.ids + parent_menus = self.env['menu.access.control'].sudo().search([('user_ids','ilike',self.env.user.id)]).access_menu_line_ids.filtered(lambda menu: not(menu.is_main_menu)).menu_id.ids + sub_menus = self.env['menu.access.control'].sudo().search([('user_ids','ilike',self.env.user.id)]).access_sub_menu_line_ids.filtered(lambda menu: not(menu.is_main_menu)).menu_id.ids + + hide_menus_list = list(set(parent_menus + sub_menus)) menus = menus.filtered(lambda menu: (menu.id not in hide_menus_list)) group_ids = group_ids - { diff --git a/addons_extensions/menu_control_center/models/models.py b/addons_extensions/menu_control_center/models/models.py index fbd4813e9..4d21b244b 100644 --- a/addons_extensions/menu_control_center/models/models.py +++ b/addons_extensions/menu_control_center/models/models.py @@ -37,61 +37,124 @@ class MenuAccessControl(models.Model): access_menu_line_ids = fields.One2many( 'menu.access.line', 'access_control_id', - string="Accessible Menus" + string="Accessible Menus", domain=[('menu_id.parent_id','=',False)] ) + access_sub_menu_line_ids = fields.One2many('menu.access.line', 'access_control_id', + string="Accessible Menus", domain=[('menu_id.parent_id','!=',False)] + ) + + def _get_all_submenus(self, menu): + """Returns all submenus recursively for a given menu.""" + submenus = self.env['ir.ui.menu'].search([('parent_id', '=', menu.id), ('active', '=', True)]) + all_subs = submenus + for sm in submenus: + all_subs |= self._get_all_submenus(sm) + return all_subs + def action_generate_menus(self): - """Button to fetch active top-level menus and populate access lines.""" - menu_lines = [] - active_menus = self.env['ir.ui.menu'].search([ - ('parent_id', '=', False), # top-level menus - ('active', '=', True) - ]) - for menu in active_menus: - menu_lines.append((0, 0, { - 'menu_id': menu.id, - 'is_main_menu': True - })) - self.access_menu_line_ids = menu_lines + """ + Generate main menus and all submenus (recursive), + and set access_line_id for every submenu. + """ + for rec in self: - def action_update_menus(self): - """Button to add new top-level menus that are not already in the list.""" - for record in self: - # Get existing menu IDs in the current record - existing_menu_ids = record.access_menu_line_ids.mapped('menu_id').ids + # clear old menus + rec.access_menu_line_ids.unlink() + rec.access_sub_menu_line_ids.unlink() - # Find new top-level menus that are not in existing_menu_ids - new_menus = self.env['ir.ui.menu'].search([ + active_menus = self.env['ir.ui.menu'].search([ ('parent_id', '=', False), - ('active', '=', True), - ('id', 'not in', existing_menu_ids) + ('active', '=', True) ]) - # Create new lines for the new menus - new_lines = [] - for menu in new_menus: - new_lines.append((0, 0, { - 'menu_id': menu.id, - 'is_main_menu': True # Default to True as requested - })) + for menu in active_menus: - if new_lines: - record.write({ - 'access_menu_line_ids': new_lines + # 1️⃣ Create main menu line + main_line = self.env['menu.access.line'].create({ + 'access_control_id': rec.id, + 'menu_id': menu.id, + 'is_main_menu': True, }) - # Show success message + + # 2️⃣ Fetch all recursive submenus + submenus = self._get_all_submenus(menu) + + # 3️⃣ Create submenu lines with correct parent + for sm in submenus: + self.env['menu.access.line'].create({ + 'access_control_id': rec.id, + 'menu_id': sm.id, + 'is_main_menu': True, + 'access_line_id': main_line.id, # important + }) + + def action_update_menus(self): + line = self.env['menu.access.line'] + menu = self.env['ir.ui.menu'] + + for rec in self: + created_count = 0 + + # All existing menu IDs across BOTH One2manys + existing_menu_ids = set( + rec.access_menu_line_ids.mapped('menu_id.id') + + rec.access_sub_menu_line_ids.mapped('menu_id.id') + ) + + # ---------- Step 1: Ensure all top-level menus exist ---------- + top_menus = menu.search([ + ('parent_id', '=', False), + ('active', '=', True), + ]) + + for menu in top_menus: + + # Create missing MAIN MENU + main_line = line.search([ + ('access_control_id', '=', rec.id), + ('menu_id', '=', menu.id), + ('access_line_id', '=', False) + ], limit=1) + + if not main_line: + main_line = line.create({ + 'access_control_id': rec.id, + 'menu_id': menu.id, + 'is_main_menu': True, + }) + created_count += 1 + existing_menu_ids.add(menu.id) + + # ---------- Step 2: Ensure all SUBMENUS exist ---------- + submenus = rec._get_all_submenus(menu) + + for sm in submenus: + + # If submenu is missing → create it + if sm.id not in existing_menu_ids: + line.create({ + 'access_control_id': rec.id, + 'menu_id': sm.id, + 'is_main_menu': True, + 'access_line_id': main_line.id, + }) + created_count += 1 + existing_menu_ids.add(sm.id) + + # ---------- Notification ---------- + if created_count: return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': _('Success'), - 'message': _('Added %s new menu(s)') % len(new_menus), + 'message': _('Added %s new menu(s) (including submenus)') % created_count, 'type': 'success', 'sticky': False, } } else: - # Show info message if no new menus found return { 'type': 'ir.actions.client', 'tag': 'display_notification', @@ -103,6 +166,7 @@ class MenuAccessControl(models.Model): } } + class MenuAccessLine(models.Model): _name = 'menu.access.line' _description = 'Menu Access Line' @@ -111,3 +175,29 @@ class MenuAccessLine(models.Model): access_control_id = fields.Many2one('menu.access.control', ondelete='cascade') menu_id = fields.Many2one('ir.ui.menu', string="Menu") is_main_menu = fields.Boolean(string="Is Main Menu", default=True) + parent_menu = fields.Many2one('ir.ui.menu',related='menu_id.parent_id') + access_line_id = fields.Many2one('menu.access.line') + control_unit = fields.Many2one( + 'menu.control.units', + related='access_control_id.control_unit', + store=True + ) + + def open_submenus_popup_view(self): + self.ensure_one() + + return { + "name": _("Sub Menus"), + "type": "ir.actions.act_window", + "res_model": "menu.access.line", + "view_mode": "list,form", + "views": [ + (self.env.ref("menu_control_center.view_submenu_line_list").id, "list"), + ], + "target": "new", + "domain": [("access_line_id", "=", self.id)], + "context": {"default_access_line_id": self.id}, + } + + + diff --git a/addons_extensions/menu_control_center/security/ir.model.access.csv b/addons_extensions/menu_control_center/security/ir.model.access.csv index d7edab9d1..f6e0f1e02 100644 --- a/addons_extensions/menu_control_center/security/ir.model.access.csv +++ b/addons_extensions/menu_control_center/security/ir.model.access.csv @@ -1,4 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_menu_access_control,access.menu.access.control,model_menu_access_control,hr.group_hr_manager,1,1,1,1 access_menu_access_line,access.menu.access.line,model_menu_access_line,hr.group_hr_manager,1,1,1,1 -access_menu_control_units,access.menu.control.units,model_menu_control_units,hr.group_hr_manager,1,1,1,1 \ No newline at end of file +access_menu_control_units,access.menu.control.units,model_menu_control_units,hr.group_hr_manager,1,1,1,1 +access_master_control_public,master.control.public,model_master_control,base.group_public,1,0,0,0 +access_master_control_hr,master.control.hr,model_master_control,hr.group_hr_manager,1,1,1,1 +group_access_line_access,group_access_line_access,model_group_access_line,,1,1,1,1 diff --git a/addons_extensions/menu_control_center/views/login.xml b/addons_extensions/menu_control_center/views/login.xml new file mode 100644 index 000000000..dc5e0d5a5 --- /dev/null +++ b/addons_extensions/menu_control_center/views/login.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/addons_extensions/menu_control_center/views/masters.xml b/addons_extensions/menu_control_center/views/masters.xml new file mode 100644 index 000000000..b15db1e26 --- /dev/null +++ b/addons_extensions/menu_control_center/views/masters.xml @@ -0,0 +1,76 @@ + + + + + master.control.list + master.control + + + + + + + + + + + master.control.form + master.control + +
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + Master Control + master.control + list,form + + + + + + + + +
\ No newline at end of file diff --git a/addons_extensions/menu_control_center/views/menu_access_control_views.xml b/addons_extensions/menu_control_center/views/menu_access_control_views.xml index d4ea37745..63bc7381c 100644 --- a/addons_extensions/menu_control_center/views/menu_access_control_views.xml +++ b/addons_extensions/menu_control_center/views/menu_access_control_views.xml @@ -1,5 +1,26 @@ + + menu.access.line.submenu.list + menu.access.line + + + + + + + + + + + + + Sub Menus + menu.access.line + list + new + + menu.control.units.list menu.control.units @@ -71,12 +92,29 @@ - - - - - - + + + + + + + + + + + diff --git a/addons_extensions/onlyoffice_odoo/static/src/css/form_gallery.scss b/addons_extensions/onlyoffice_odoo/static/src/css/form_gallery.scss new file mode 100644 index 000000000..67b5f5cd7 --- /dev/null +++ b/addons_extensions/onlyoffice_odoo/static/src/css/form_gallery.scss @@ -0,0 +1,57 @@ +.o_onlyoffice_kanban_renderer { + row-gap: 30px; + column-gap: 30px; + background: none; + + .o_onlyoffice_kanban_record { + width: 200px; + border: 1px solid; + border-color: var(--black-25); + + .o_onlyoffice_record_selector { + color: var(--black-25); + position: absolute; + top: 8px; + right: 8px; + font-size: 16px; + z-index: 9; + cursor: pointer; + + background: rgba(255, 255, 255, 0.66); + border-radius: 50%; + width: 13px; + height: 13px; + display: flex; + align-items: center; + justify-content: center; + } + + .o_onlyoffice_record_selected { + opacity: 1; + border: 1px solid var(--primary); + box-shadow: 0 0 0 1px var(--primary); + background-color: var(--body-bg); + + .o_onlyoffice_record_selector::before { + color: var(--primary); + content: "\f058"; + } + } + } + + .o_onlyoffice_kanban_previewer { + cursor: zoom-in; + + .o_onlyoffice_kanban_image { + width: 100%; + height: 100%; + } + } + + .o_onlyoffice_kanban_details_wrapper { + flex-direction: row; + min-height: auto; + column-gap: 10px; + align-items: baseline; + } +} diff --git a/addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container.png b/addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container.png new file mode 100644 index 0000000000000000000000000000000000000000..372532c986b54af552793acfe27b797ad72e5e05 GIT binary patch literal 27329 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 literal 0 HcmV?d00001 diff --git a/addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container_mobile.png b/addons_extensions/onlyoffice_odoo/static/src/css/onlyoffice_link_container_mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..889098137d8897fa7e44c5ea6712d8d82f13c2f2 GIT binary patch literal 22957 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 { + try { + const data = await fetch("/onlyoffice_odoo/static/assets/document_formats/onlyoffice-docs-formats.json") + formats = await data.json() + } catch (error) { + console.error("Error loading formats data:", error) + } +} + +loadFormats() + +patch(AttachmentList.prototype, { + setup() { + super.setup(...arguments) + this.orm = useService("orm") + this.notification = useService("notification") + this.actionService = useService("action") + }, + // eslint-disable-next-line sort-keys + onlyofficeCanOpen(attachment) { + const format = formats.find((f) => f.name === attachment.extension.toLowerCase()) + return format && format.actions && (format.actions.includes("view") || format.actions.includes("edit")) + }, + async openOnlyoffice(attachment) { + const demo = JSON.parse(await this.orm.call("onlyoffice.odoo", "get_demo")) + if (demo && demo.mode && demo.date) { + const isValidDate = (d) => d instanceof Date && !isNaN(d) + demo.date = new Date(Date.parse(demo.date)) + if (isValidDate(demo.date)) { + const today = new Date() + const difference = Math.floor((today - demo.date) / (1000 * 60 * 60 * 24)) + if (difference > 30) { + this.notification.add( + _t("The 30-day test period is over, you can no longer connect to demo ONLYOFFICE Docs server"), + { + title: _t("ONLYOFFICE Docs server"), + type: "warning", + }, + ) + return + } + } + } + const { same_tab } = JSON.parse(await this.orm.call("onlyoffice.odoo", "get_same_tab")) + if (same_tab) { + const action = { + params: { attachment_id: attachment.id }, + tag: "onlyoffice_editor", + target: "current", + type: "ir.actions.client", + } + return this.actionService.doAction(action) + } + const accessTokenQuery = attachment.accessToken ? `?access_token=${attachment.accessToken}` : "" + window.open(`/onlyoffice/editor/${attachment.id}${accessTokenQuery}`, "_blank") + }, +}) diff --git a/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.js b/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.js new file mode 100644 index 000000000..4a7fc5452 --- /dev/null +++ b/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.js @@ -0,0 +1,274 @@ +/** @odoo-module **/ +import { OnlyofficePreview } from "@onlyoffice_odoo/views/preview/onlyoffice_preview" +import { Dialog } from "@web/core/dialog/dialog" +import { Dropdown } from "@web/core/dropdown/dropdown" +import { DropdownItem } from "@web/core/dropdown/dropdown_item" +import { _t } from "@web/core/l10n/translation" +import { rpc } from "@web/core/network/rpc" +import { Pager } from "@web/core/pager/pager" +import { useService } from "@web/core/utils/hooks" + +const { Component, useState, onWillStart, onWillUnmount } = owl + +export class FormGallery extends Component { + static template = "onlyoffice_odoo.FormGallery" + + static components = { + Dialog, + Dropdown, + DropdownItem, + Pager, + } + + setup() { + this.title = _t("Document templates") + this.action = useService("action") + this.notification = useService("notification") + this.rpc = rpc + this.orm = useService("orm") + + this.searchTimeout = null + + this.state = useState({ + categories: [], + error: null, + form: null, + forms: [], + ghost: 0, + limit: 12, + loading: false, + locale: { + code: "en", + name: "English", + }, + locales: [ + { + code: "en", + name: "English", + }, + ], + offset: 0, + search: "", + subcategories: {}, + subcategory: { + category_type: "category", + id: "all", + }, + total: 0, + type: "pdf", + }) + + onWillStart(async () => { + this.state.loading = true + await this.fetchLocales() + await this.fetchCategoryTypes() + await this.fetchOforms() + this.state.loading = false + }) + + onWillUnmount(() => { + if (this.searchTimeout) { + clearTimeout(this.searchTimeout) + } + }) + } + + async fetchLocales() { + try { + const url = "/onlyoffice/oforms/locales" + const response = await this.rpc(url) + + let localesData = [] + if (Array.isArray(response)) { + localesData = response.map((item) => ({ + code: item.code, + name: item.name || item.code, + })) + } else if (response && response.data) { + localesData = response.data + } + + this.state.locales = localesData + } catch (_error) { + this.state.locales = [ + { + code: "en", + name: "English", + }, + ] + } + } + + async fetchCategoryTypes() { + try { + const response = await this.rpc("/onlyoffice/oforms/category-types", { locale: this.state.locale.code }) + this.state.categories = response.data || [] + for (const categoryTypes of response.data) { + await this.fetchSubcategories(categoryTypes.categoryId) + } + } catch (_error) { + this.notification.add(_t("Failed to load categories"), { type: "danger" }) + } + } + + async fetchSubcategories(categoryId) { + try { + const category = this.state.categories.find((c) => c.categoryId === categoryId) + const response = await this.rpc("/onlyoffice/oforms/subcategories", { + category_type: category.type, + locale: this.state.locale.code, + }) + + this.state.subcategories[categoryId] = response.data || [] + } catch (_error) { + this.state.subcategories[categoryId] = [] + } + } + + async fetchOforms() { + this.state.loading = true + this.state.form = null + this.state.error = null + + try { + const params = { + ["filters[" + this.state.subcategory.category_type + "][$eq]"]: this.state.subcategory.id, + locale: this.state.locale.code, + "pagination[pageSize]": this.state.limit, + "pagination[page]": Math.floor(this.state.offset / this.state.limit) + 1, + type: this.state.type, + } + + if (this.state.search) { + params["filters[name_form][$containsi]"] = this.state.search + } + + const response = await this.rpc("/onlyoffice/oforms", { params: params }) + + this.state.forms = response.data || [] + + const oKanbanGhost = 4 - (this.state.forms.length % 4) + if (oKanbanGhost === 4) { + this.state.ghost = new Array(0).fill() + } else { + this.state.ghost = new Array(oKanbanGhost).fill() + } + + this.state.total = response.meta?.pagination?.total || 0 + } catch (_error) { + this.state.error = _t("Failed to load forms") + this.notification.add(_t("Error loading forms"), { type: "danger" }) + } + this.state.loading = false + } + + async onChangeType(type) { + this.state.type = type + this.state.subcategory = { + category_type: "category", + id: "all", + } + this.state.offset = 0 + await this.fetchOforms() + } + + async onSubcategorySelect(subcategory) { + this.state.subcategory = subcategory + this.state.type = "pdf" + this.state.offset = 0 + await this.fetchOforms() + } + + async onAllSubcategorySelect() { + this.state.subcategory = { + category_type: "category", + id: "all", + } + this.state.offset = 0 + await this.fetchOforms() + } + + async onSearch(search) { + if (this.searchTimeout) { + clearTimeout(this.searchTimeout) + } + + this.state.search = search + + this.searchTimeout = setTimeout(async () => { + this.state.offset = 0 + await this.fetchOforms() + }, 1000) + } + + async onLocaleChange(locale) { + this.state.loading = true + + this.state.locale = locale + this.state.subcategory = { + category_type: "category", + id: "all", + } + this.state.offset = 0 + await this.fetchCategoryTypes() + await this.fetchOforms() + + this.state.loading = false + } + + async onPageChange({ offset }) { + this.state.offset = offset + await this.fetchOforms() + } + + getImageUrl(form) { + const imageData = form.attributes?.template_image?.data + if (!imageData) { + return null + } + return ( + imageData.attributes.formats.medium?.url || + imageData.attributes.formats.small?.url || + imageData.attributes.formats.thumbnail?.url + ) + } + + getPreviewUrl(form) { + return form.attributes?.card_prewiew?.data?.attributes?.url + } + + previewForm(url, title, ext) { + this.env.services.dialog.add( + OnlyofficePreview, + { + close: () => { + this.env.services.dialog.close() + }, + title: title + "." + ext.split(".").pop(), + url: url, + }, + { + onClose: () => { + return + }, + }, + ) + } + + selectForm(form) { + if (this.state.form && this.state.form.id === form.id) { + this.state.form = null + } else { + this.state.form = form + } + } + + async download() { + if (this.props.onDownload && this.state.form) { + await this.props.onDownload(this.state.form) + if (this.props.close) { + this.props.close() + } + } + } +} diff --git a/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.xml b/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.xml new file mode 100644 index 000000000..74c9d4de1 --- /dev/null +++ b/addons_extensions/onlyoffice_odoo/static/src/views/form_gallery/form_gallery.xml @@ -0,0 +1,174 @@ + + + + +
+
+
+ +
+
+
+
+ + + + + View all templates + + + +
+ + + + + Form + + + Document + + + Spreadsheet + + + Presentation + + + +
+
+
+ + + + + + + + + + +
+
+ +
+
+ + +
+ +

Loading forms...

+
+
+ + +
+ + +
+ +
+
+ +
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+ +
+ + +
+ +

No forms found

+

Try changing your search or filters

+
+
+
+ + + + + +
+
+
diff --git a/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.js b/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.js new file mode 100644 index 000000000..aa5602376 --- /dev/null +++ b/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.js @@ -0,0 +1,51 @@ +/** @odoo-module **/ + +import { Component, onMounted, onWillUnmount } from "@odoo/owl" + +export class OnlyofficePreview extends Component { + static template = "onlyoffice_odoo.OnlyofficePreview" + + static props = { + close: Function, + title: String, + url: String, + } + + setup() { + this.title = "Preview - " + this.props.title + this.url = + "/onlyoffice/preview" + + `?url=${encodeURIComponent(this.props.url)}&` + + `title=${encodeURIComponent(this.props.title)}` + + const handleKeyDown = (ev) => { + if (ev.key === "Escape") { + ev.stopPropagation() + ev.preventDefault() + this.props.close() + } + } + + onMounted(() => { + document.addEventListener("keydown", handleKeyDown, { capture: true }) + document.querySelectorAll(".o-overlay-item").forEach((item) => { + if (item.querySelector(".o-onlyoffice-preview")) { + item.classList.add("o-onlyoffice-overlay-item") + } + }) + }) + + onWillUnmount(() => { + document.removeEventListener("keydown", handleKeyDown, { capture: true }) + }) + } + + onClickOutside(ev) { + const isHeader = ev.target.closest(".o-onlyoffice-preview-header") + const isBody = ev.target.closest(".o-onlyoffice-preview-body") + + if (!isHeader && !isBody) { + this.props.close() + } + } +} diff --git a/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.xml b/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.xml new file mode 100644 index 000000000..a76374966 --- /dev/null +++ b/addons_extensions/onlyoffice_odoo/static/src/views/preview/onlyoffice_preview.xml @@ -0,0 +1,19 @@ + + + +
+
+
+ +
+
+
+ +
+
+
+