vanilla 17.0

This commit is contained in:
Ernad Husremovic 2025-10-08 10:47:08 +02:00
parent d72e748793
commit a9bcec8e91
1986 changed files with 1613876 additions and 568976 deletions

View file

@ -15,40 +15,14 @@ pip install odoo-bringout-oca-ocb-web
## Dependencies ## Dependencies
This addon depends on:
- base - base
## Manifest Information
- **Name**: Web
- **Version**: 1.0
- **Category**: Hidden
- **License**: LGPL-3
- **Installable**: False
## Modifications
This package has been modified from the original OCA/OCB source:
- Removed proprietary mobile app download buttons (Google Play Store, Apple App Store) from base_setup configuration views
## Source ## Source
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `web`. - Repository: https://github.com/OCA/OCB
- Branch: 17.0
- Path: addons/web
## License ## License
This package maintains the original LGPL-3 license from the upstream Odoo project. This package preserves the original LGPL-3 license.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -1,12 +1,14 @@
[project] [project]
name = "odoo-bringout-oca-ocb-web" name = "odoo-bringout-oca-ocb-web"
version = "16.0.0" version = "16.0.0"
description = "Web - Odoo addon" description = "Web -
Odoo addon
"
authors = [ authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" } { name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
] ]
dependencies = [ dependencies = [
"odoo-bringout-oca-ocb-base>=16.0.0", "odoo-bringout-oca-ocb-base>=17.0.0",
"requests>=2.25.1" "requests>=2.25.1"
] ]
readme = "README.md" readme = "README.md"
@ -16,14 +18,14 @@ classifiers = [
"Intended Audience :: Developers", "Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Topic :: Office/Business", "Topic :: Office/Business",
] ]
[project.urls] [project.urls]
homepage = "https://github.com/bringout/odoo-bringout-oca-ocb-web" homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/odoo-bringout-oca-ocb-web" repository = "https://github.com/bringout/0"
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]

View file

@ -18,8 +18,8 @@ This module provides the core of the Odoo Web Client.
'views/webclient_templates.xml', 'views/webclient_templates.xml',
'views/report_templates.xml', 'views/report_templates.xml',
'views/base_document_layout_views.xml', 'views/base_document_layout_views.xml',
'views/partner_view.xml',
'views/speedscope_template.xml', 'views/speedscope_template.xml',
'views/lazy_assets.xml',
'views/neutralize_views.xml', 'views/neutralize_views.xml',
'data/ir_attachment.xml', 'data/ir_attachment.xml',
'data/report_layout.xml', 'data/report_layout.xml',
@ -37,69 +37,33 @@ This module provides the core of the Odoo Web Client.
# 3) an arbitrary name, relevant to the content of the bundle. # 3) an arbitrary name, relevant to the content of the bundle.
# #
# Examples: # Examples:
# > web.assets_common = assets common to backend clients and others # > web_editor.assets_legacy_wysiwyg = assets needed by components defined in the "web_editor" module.
# (not frontend).
# > web_editor.assets_wysiwyg = assets needed by components defined in the "web_editor" module.
# Warning: Layouts using "assets_frontend" assets do not have the 'web.assets_emoji': [
# "assets_common" assets anymore. So, if it make sense, files added in 'web/static/src/core/emoji_picker/emoji_data.js'
# "assets_common" should also be added in "assets_frontend". ],
# TODO in the future, probably remove "assets_common" definition 'web.assets_backend': [
# entirely and let all "main" bundles evolve on their own, including the
# files they need in their bundle.
'web.assets_common': [
('include', 'web._assets_helpers'), ('include', 'web._assets_helpers'),
('include', 'web._assets_backend_helpers'),
'web/static/src/scss/pre_variables.scss', 'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss', 'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap_backend'),
('include', 'web._assets_core'),
'web/static/src/legacy/scss/tempusdominus_overridden.scss',
'web/static/lib/tempusdominus/tempusdominus.scss',
'web/static/lib/jquery.ui/jquery-ui.css',
'web/static/src/libs/fontawesome/css/font-awesome.css', 'web/static/src/libs/fontawesome/css/font-awesome.css',
'web/static/lib/odoo_ui_icons/*', 'web/static/lib/odoo_ui_icons/*',
'web/static/lib/select2/select2.css',
'web/static/lib/select2-bootstrap-css/select2-bootstrap.css',
'web/static/lib/daterangepicker/daterangepicker.css',
'web/static/src/webclient/navbar/navbar.scss', 'web/static/src/webclient/navbar/navbar.scss',
'web/static/src/scss/animation.scss',
'web/static/src/scss/fontawesome_overridden.scss',
'web/static/src/scss/mimetypes.scss',
'web/static/src/scss/ui.scss',
'web/static/src/views/fields/translation_dialog.scss',
'web/static/src/legacy/scss/ui.scss', 'web/static/src/legacy/scss/ui.scss',
'web/static/src/legacy/scss/mimetypes.scss',
'web/static/src/legacy/scss/modal.scss',
'web/static/src/legacy/scss/animation.scss',
'web/static/src/legacy/scss/datepicker.scss',
'web/static/src/legacy/scss/daterangepicker.scss',
'web/static/src/legacy/scss/banner.scss',
'web/static/src/legacy/scss/colorpicker.scss',
'web/static/src/legacy/scss/popover.scss',
'web/static/src/legacy/scss/translation_dialog.scss',
'web/static/src/legacy/scss/keyboard.scss',
'web/static/src/legacy/scss/name_and_signature.scss',
'web/static/src/legacy/scss/web.zoomodoo.scss',
'web/static/src/legacy/scss/fontawesome_overridden.scss',
'web/static/src/legacy/js/promise_extension.js', 'web/static/src/polyfills/clipboard.js',
'web/static/src/boot.js',
'web/static/src/session.js',
'web/static/src/legacy/js/core/cookie_utils.js',
'web/static/lib/underscore/underscore.js',
'web/static/lib/underscore.string/lib/underscore.string.js',
'web/static/lib/moment/moment.js',
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js', 'web/static/lib/jquery/jquery.js',
'web/static/lib/jquery.ui/jquery-ui.js',
'web/static/lib/jquery/jquery.browser.js',
'web/static/lib/jquery.blockUI/jquery.blockUI.js',
'web/static/lib/jquery.hotkeys/jquery.hotkeys.js',
'web/static/lib/jquery.placeholder/jquery.placeholder.js',
'web/static/lib/jquery.form/jquery.form.js',
'web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js',
'web/static/lib/jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js',
'web/static/lib/popper/popper.js', 'web/static/lib/popper/popper.js',
'web/static/lib/bootstrap/js/dist/dom/data.js', 'web/static/lib/bootstrap/js/dist/dom/data.js',
'web/static/lib/bootstrap/js/dist/dom/event-handler.js', 'web/static/lib/bootstrap/js/dist/dom/event-handler.js',
@ -118,81 +82,17 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/bootstrap/js/dist/scrollspy.js', 'web/static/lib/bootstrap/js/dist/scrollspy.js',
'web/static/lib/bootstrap/js/dist/tab.js', 'web/static/lib/bootstrap/js/dist/tab.js',
'web/static/lib/bootstrap/js/dist/toast.js', 'web/static/lib/bootstrap/js/dist/toast.js',
'web/static/lib/tempusdominus/tempusdominus.js',
'web/static/lib/select2/select2.js',
'web/static/lib/clipboard/clipboard.js',
'web/static/lib/jSignature/jSignatureCustom.js',
'web/static/lib/qweb/qweb2.js',
'web/static/src/legacy/js/assets.js',
'web/static/src/legacy/js/libs/autocomplete.js',
'web/static/src/legacy/js/libs/bootstrap.js', 'web/static/src/legacy/js/libs/bootstrap.js',
'web/static/src/legacy/js/libs/content-disposition.js',
'web/static/src/legacy/js/libs/download.js',
'web/static/src/legacy/js/libs/jquery.js', 'web/static/src/legacy/js/libs/jquery.js',
'web/static/src/legacy/js/libs/moment.js',
'web/static/src/legacy/js/libs/underscore.js',
'web/static/src/legacy/js/libs/pdfjs.js',
'web/static/src/legacy/js/libs/zoomodoo.js',
'web/static/src/legacy/js/libs/jSignatureCustom.js',
'web/static/src/legacy/js/core/abstract_service.js',
'web/static/src/legacy/js/core/abstract_storage_service.js',
'web/static/src/legacy/js/core/ajax.js',
'web/static/src/legacy/js/core/browser_detection.js',
'web/static/src/legacy/js/core/bus.js',
'web/static/src/legacy/js/core/class.js',
'web/static/src/legacy/js/core/collections.js',
'web/static/src/legacy/js/core/concurrency.js',
'web/static/src/legacy/js/core/dialog.js',
'web/static/src/legacy/xml/dialog.xml',
'web/static/src/legacy/js/core/owl_dialog.js',
'web/static/src/legacy/js/core/popover.js',
'web/static/src/legacy/js/core/minimal_dom.js',
'web/static/src/legacy/js/core/dom.js',
'web/static/src/legacy/js/core/local_storage.js',
'web/static/src/legacy/js/core/mixins.js',
'web/static/src/legacy/js/core/qweb.js',
'web/static/src/legacy/js/core/ram_storage.js',
'web/static/src/legacy/js/core/registry.js',
'web/static/src/legacy/js/core/rpc.js',
'web/static/src/legacy/js/core/service_mixins.js',
'web/static/src/legacy/js/core/session.js',
'web/static/src/legacy/js/core/session_storage.js',
'web/static/src/legacy/js/core/time.js',
'web/static/src/legacy/js/core/translation.js',
'web/static/src/legacy/js/core/utils.js',
'web/static/src/legacy/js/core/widget.js',
'web/static/src/legacy/js/services/ajax_service.js',
'web/static/src/legacy/js/services/config.js',
'web/static/src/legacy/js/services/core.js',
'web/static/src/legacy/js/services/local_storage_service.js',
'web/static/src/legacy/js/services/session_storage_service.js',
'web/static/src/legacy/js/common_env.js',
'web/static/src/legacy/js/widgets/name_and_signature.js',
'web/static/src/legacy/xml/name_and_signature.xml',
'web/static/src/legacy/js/core/smooth_scroll_on_drag.js',
'web/static/src/legacy/js/widgets/colorpicker.js',
'web/static/src/legacy/xml/colorpicker.xml',
'web/static/src/legacy/js/widgets/translation_dialog.js',
'web/static/src/legacy/xml/translation_dialog.xml',
],
'web.assets_backend': [
('include', 'web._assets_helpers'),
('include', 'web._assets_backend_helpers'),
'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap'),
'base/static/src/css/modules.css', 'base/static/src/css/modules.css',
'web/static/src/core/utils/transitions.scss', 'web/static/src/core/utils/transitions.scss',
'web/static/src/core/**/*', 'web/static/src/model/**/*',
'web/static/src/search/**/*', 'web/static/src/search/**/*',
'web/static/src/webclient/icons.scss', # variables required in list_controller.scss 'web/static/src/webclient/icons.scss', # variables required in list_controller.scss
'web/static/src/views/**/*', 'web/static/src/views/**/*',
'web/static/src/webclient/**/*', 'web/static/src/webclient/**/*',
('remove', 'web/static/src/webclient/navbar/navbar.scss'), # already in assets_common
('remove', 'web/static/src/webclient/clickbot/clickbot.js'), # lazy loaded ('remove', 'web/static/src/webclient/clickbot/clickbot.js'), # lazy loaded
('remove', 'web/static/src/views/form/button_box/*.scss'), ('remove', 'web/static/src/views/form/button_box/*.scss'),
@ -201,108 +101,33 @@ This module provides the core of the Odoo Web Client.
'web/static/src/webclient/actions/reports/*.js', 'web/static/src/webclient/actions/reports/*.js',
'web/static/src/webclient/actions/reports/*.xml', 'web/static/src/webclient/actions/reports/*.xml',
'web/static/src/env.js', 'web/static/src/libs/pdfjs.js',
'web/static/lib/jquery.scrollTo/jquery.scrollTo.js', 'web/static/src/scss/ace.scss',
'web/static/lib/py.js/lib/py.js', 'web/static/src/scss/base_document_layout.scss',
'web/static/lib/py.js/lib/py_extras.js',
'web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js',
'web/static/src/legacy/scss/domain_selector.scss',
'web/static/src/legacy/scss/model_field_selector.scss',
'web/static/src/legacy/scss/dropdown.scss', 'web/static/src/legacy/scss/dropdown.scss',
'web/static/src/legacy/scss/tooltip.scss',
'web/static/src/legacy/scss/switch_company_menu.scss',
'web/static/src/legacy/scss/ace.scss',
'web/static/src/legacy/scss/fields.scss', 'web/static/src/legacy/scss/fields.scss',
'web/static/src/legacy/scss/views.scss',
'web/static/src/legacy/scss/form_view.scss',
'web/static/src/legacy/scss/list_view.scss',
'web/static/src/legacy/scss/kanban_dashboard.scss',
'web/static/src/legacy/scss/kanban_examples_dialog.scss',
'web/static/src/legacy/scss/kanban_column_progressbar.scss',
'web/static/src/legacy/scss/kanban_view.scss',
'web/static/src/legacy/scss/data_export.scss',
'base/static/src/scss/onboarding.scss',
'web/static/src/legacy/scss/attachment_preview.scss',
'web/static/src/legacy/scss/base_document_layout.scss',
'web/static/src/legacy/scss/special_fields.scss',
'web/static/src/legacy/scss/fields_extra.scss',
'web/static/src/legacy/scss/form_view_extra.scss',
'web/static/src/legacy/scss/list_view_extra.scss',
'web/static/src/legacy/scss/color_picker.scss',
'base/static/src/scss/res_partner.scss', 'base/static/src/scss/res_partner.scss',
# Form style should be computed before # Form style should be computed before
'web/static/src/views/form/button_box/*.scss', 'web/static/src/views/form/button_box/*.scss',
'web/static/src/legacy/action_adapters.js',
'web/static/src/legacy/debug_manager.js',
'web/static/src/legacy/legacy_service_provider.js',
'web/static/src/legacy/legacy_client_actions.js',
'web/static/src/legacy/legacy_dialog.js',
'web/static/src/legacy/legacy_load_views.js',
'web/static/src/legacy/legacy_views.js',
'web/static/src/legacy/legacy_promise_error_handler.js',
'web/static/src/legacy/legacy_rpc_error_handler.js',
'web/static/src/legacy/root_widget.js',
'web/static/src/legacy/systray_menu.js',
'web/static/src/legacy/systray_menu_item.js',
'web/static/src/legacy/backend_utils.js',
'web/static/src/legacy/utils.js',
'web/static/src/legacy/web_client.js',
'web/static/src/legacy/js/_deprecated/*',
'web/static/src/legacy/js/chrome/*',
'web/static/src/legacy/js/components/*',
'web/static/src/legacy/js/control_panel/*',
'web/static/src/legacy/js/core/domain.js',
'web/static/src/legacy/js/core/mvc.js',
'web/static/src/legacy/js/core/py_utils.js',
'web/static/src/legacy/js/core/context.js',
'web/static/src/legacy/js/core/misc.js',
'web/static/src/legacy/js/fields/*',
'web/static/src/legacy/js/services/data_manager.js',
'web/static/src/legacy/js/services/session.js',
'web/static/src/legacy/js/tools/tools.js',
'web/static/src/legacy/js/views/**/*',
'web/static/src/legacy/js/widgets/data_export.js',
'web/static/src/legacy/js/widgets/date_picker.js',
'web/static/src/legacy/js/widgets/domain_selector_dialog.js',
'web/static/src/legacy/js/widgets/domain_selector.js',
'web/static/src/legacy/js/widgets/iframe_widget.js',
'web/static/src/legacy/js/widgets/model_field_selector.js',
'web/static/src/legacy/js/widgets/model_field_selector_popover.js',
'web/static/src/legacy/js/widgets/ribbon.js',
'web/static/src/legacy/js/widgets/week_days.js',
'web/static/src/legacy/js/widgets/signature.js',
'web/static/src/legacy/js/widgets/attach_document.js',
'web/static/src/legacy/js/apps.js',
'web/static/src/legacy/js/env.js',
'web/static/src/legacy/js/model.js',
'web/static/src/legacy/js/owl_compatibility.js',
'web/static/src/legacy/xml/base.xml', 'web/static/src/legacy/xml/base.xml',
'web/static/src/legacy/xml/ribbon.xml',
'web/static/src/legacy/xml/control_panel.xml',
'web/static/src/legacy/xml/fields.xml',
'web/static/src/legacy/xml/kanban.xml',
'web/static/src/legacy/xml/search_panel.xml',
'web/static/src/legacy/xml/week_days.xml',
# Don't include dark mode files in light mode # Don't include dark mode files in light mode
('remove', 'web/static/src/**/*.dark.scss'), ('remove', 'web/static/src/**/*.dark.scss'),
], ],
"web.assets_backend_legacy_lazy": [ 'web.assets_web': [
("include", "web._assets_helpers"), ('include', 'web.assets_backend'),
('include', 'web._assets_backend_helpers'), 'web/static/src/main.js',
'web/static/src/scss/pre_variables.scss', 'web/static/src/start.js',
'web/static/lib/bootstrap/scss/_variables.scss',
], ],
'web.assets_frontend_minimal': [ 'web.assets_frontend_minimal': [
'web/static/src/legacy/js/promise_extension.js', 'web/static/src/polyfills/object.js',
'web/static/src/boot.js', 'web/static/src/polyfills/array.js',
'web/static/src/module_loader.js',
'web/static/src/session.js', 'web/static/src/session.js',
'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/src/core/browser/cookie.js',
'web/static/src/legacy/js/core/menu.js',
'web/static/src/legacy/js/core/minimal_dom.js', 'web/static/src/legacy/js/core/minimal_dom.js',
'web/static/src/legacy/js/public/lazyloader.js', 'web/static/src/legacy/js/public/lazyloader.js',
], ],
@ -320,54 +145,31 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/bootstrap/scss/_variables.scss', 'web/static/lib/bootstrap/scss/_variables.scss',
'web/static/lib/luxon/luxon.js', 'web/static/lib/luxon/luxon.js',
('include', 'web._assets_bootstrap'), ('include', 'web._assets_bootstrap_frontend'),
'web/static/src/legacy/scss/tempusdominus_overridden.scss',
'web/static/lib/tempusdominus/tempusdominus.scss',
'web/static/lib/jquery.ui/jquery-ui.css',
'web/static/src/libs/fontawesome/css/font-awesome.css', 'web/static/src/libs/fontawesome/css/font-awesome.css',
'web/static/lib/odoo_ui_icons/*', 'web/static/lib/odoo_ui_icons/*',
'web/static/lib/select2/select2.css', 'web/static/lib/select2/select2.css',
'web/static/lib/select2-bootstrap-css/select2-bootstrap.css', 'web/static/lib/select2-bootstrap-css/select2-bootstrap.css',
'web/static/lib/daterangepicker/daterangepicker.css',
'web/static/src/webclient/navbar/navbar.scss', 'web/static/src/webclient/navbar/navbar.scss',
'web/static/src/legacy/scss/ui.scss', 'web/static/src/scss/animation.scss',
'web/static/src/legacy/scss/mimetypes.scss', 'web/static/src/scss/base_frontend.scss',
'web/static/src/legacy/scss/modal.scss', 'web/static/src/scss/fontawesome_overridden.scss',
'web/static/src/legacy/scss/animation.scss', 'web/static/src/scss/mimetypes.scss',
'web/static/src/legacy/scss/datepicker.scss', 'web/static/src/scss/ui.scss',
'web/static/src/legacy/scss/daterangepicker.scss', 'web/static/src/views/fields/translation_dialog.scss',
'web/static/src/legacy/scss/banner.scss', 'web/static/src/views/fields/signature/signature_field.scss',
'web/static/src/legacy/scss/colorpicker.scss',
'web/static/src/legacy/scss/popover.scss', 'web/static/src/legacy/scss/ui.scss',
'web/static/src/legacy/scss/translation_dialog.scss', 'web/static/src/legacy/scss/modal.scss',
'web/static/src/legacy/scss/keyboard.scss',
'web/static/src/legacy/scss/name_and_signature.scss',
'web/static/src/legacy/scss/web.zoomodoo.scss',
'web/static/src/legacy/scss/fontawesome_overridden.scss',
'web/static/src/legacy/scss/base_frontend.scss',
'web/static/src/legacy/scss/lazyloader.scss', 'web/static/src/legacy/scss/lazyloader.scss',
('include', 'web.assets_frontend_minimal'), ('include', 'web.assets_frontend_minimal'),
'web/static/lib/underscore/underscore.js',
'web/static/lib/underscore.string/lib/underscore.string.js',
'web/static/lib/moment/moment.js',
'web/static/lib/owl/owl.js', 'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js', 'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js', 'web/static/lib/jquery/jquery.js',
'web/static/lib/jquery.ui/jquery-ui.js',
'web/static/lib/jquery/jquery.browser.js',
'web/static/lib/jquery.blockUI/jquery.blockUI.js',
'web/static/lib/jquery.hotkeys/jquery.hotkeys.js',
'web/static/lib/jquery.placeholder/jquery.placeholder.js',
'web/static/lib/jquery.form/jquery.form.js',
'web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js',
'web/static/lib/jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js',
'web/static/lib/popper/popper.js', 'web/static/lib/popper/popper.js',
'web/static/lib/bootstrap/js/dist/dom/data.js', 'web/static/lib/bootstrap/js/dist/dom/data.js',
'web/static/lib/bootstrap/js/dist/dom/event-handler.js', 'web/static/lib/bootstrap/js/dist/dom/event-handler.js',
@ -386,100 +188,46 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/bootstrap/js/dist/scrollspy.js', 'web/static/lib/bootstrap/js/dist/scrollspy.js',
'web/static/lib/bootstrap/js/dist/tab.js', 'web/static/lib/bootstrap/js/dist/tab.js',
'web/static/lib/bootstrap/js/dist/toast.js', 'web/static/lib/bootstrap/js/dist/toast.js',
'web/static/lib/tempusdominus/tempusdominus.js',
'web/static/lib/select2/select2.js', 'web/static/lib/select2/select2.js',
'web/static/lib/clipboard/clipboard.js',
'web/static/lib/jSignature/jSignatureCustom.js',
'web/static/lib/qweb/qweb2.js',
'web/static/src/legacy/js/assets.js',
'web/static/src/legacy/js/libs/autocomplete.js',
'web/static/src/legacy/js/libs/bootstrap.js', 'web/static/src/legacy/js/libs/bootstrap.js',
'web/static/src/legacy/js/libs/content-disposition.js',
'web/static/src/legacy/js/libs/download.js',
'web/static/src/legacy/js/libs/jquery.js', 'web/static/src/legacy/js/libs/jquery.js',
'web/static/src/legacy/js/libs/moment.js',
'web/static/src/legacy/js/libs/underscore.js',
'web/static/src/legacy/js/libs/pdfjs.js',
'web/static/src/legacy/js/libs/zoomodoo.js',
'web/static/src/legacy/js/libs/jSignatureCustom.js',
'web/static/src/legacy/js/core/abstract_service.js',
'web/static/src/legacy/js/core/abstract_storage_service.js',
'web/static/src/legacy/js/core/ajax.js',
'web/static/src/legacy/js/core/browser_detection.js',
'web/static/src/legacy/js/core/bus.js',
'web/static/src/legacy/js/core/class.js', 'web/static/src/legacy/js/core/class.js',
'web/static/src/legacy/js/core/collections.js',
'web/static/src/legacy/js/core/concurrency.js',
'web/static/src/legacy/js/core/dialog.js', 'web/static/src/legacy/js/core/dialog.js',
'web/static/src/legacy/xml/dialog.xml', 'web/static/src/legacy/xml/dialog.xml',
'web/static/src/legacy/js/core/owl_dialog.js',
'web/static/src/legacy/js/core/popover.js',
'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/dom.js',
'web/static/src/legacy/js/core/local_storage.js',
'web/static/src/legacy/js/core/menu.js',
'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/mixins.js',
'web/static/src/legacy/js/core/qweb.js',
'web/static/src/legacy/js/core/ram_storage.js',
'web/static/src/legacy/js/core/registry.js',
'web/static/src/legacy/js/core/rpc.js',
'web/static/src/legacy/js/core/service_mixins.js', 'web/static/src/legacy/js/core/service_mixins.js',
'web/static/src/legacy/js/core/session.js',
'web/static/src/legacy/js/core/session_storage.js',
'web/static/src/legacy/js/core/time.js',
'web/static/src/legacy/js/core/translation.js',
'web/static/src/legacy/js/core/utils.js',
'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/core/widget.js',
'web/static/src/legacy/js/services/ajax_service.js',
'web/static/src/legacy/js/services/config.js',
'web/static/src/legacy/js/services/core.js',
'web/static/src/legacy/js/services/local_storage_service.js',
'web/static/src/legacy/js/services/session_storage_service.js',
'web/static/src/legacy/js/common_env.js',
'web/static/src/legacy/js/widgets/name_and_signature.js',
'web/static/src/legacy/xml/name_and_signature.xml',
'web/static/src/legacy/js/core/smooth_scroll_on_drag.js',
'web/static/src/legacy/js/widgets/colorpicker.js',
'web/static/src/legacy/xml/colorpicker.xml',
'web/static/src/legacy/js/widgets/translation_dialog.js',
'web/static/src/legacy/xml/translation_dialog.xml',
'web/static/src/env.js', 'web/static/src/env.js',
'web/static/src/core/utils/transitions.scss', # included early because used by other files 'web/static/src/core/utils/transitions.scss', # included early because used by other files
'web/static/src/core/**/*', 'web/static/src/core/**/*',
('remove', 'web/static/src/core/commands/**/*'), ('remove', 'web/static/src/core/commands/**/*'),
('remove', 'web/static/src/core/debug/debug_menu.js'), ('remove', 'web/static/src/core/debug/debug_menu.js'),
('remove', 'web/static/src/core/file_viewer/file_viewer.dark.scss'),
('remove', 'web/static/src/core/emoji_picker/emoji_data.js'),
'web/static/src/core/commands/default_providers.js',
'web/static/src/core/commands/command_palette.js',
'web/static/src/public/error_notifications.js', 'web/static/src/public/error_notifications.js',
'web/static/src/public/public_component_service.js',
'web/static/src/public/datetime_picker_widget.js',
'web/static/src/libs/pdfjs.js',
'web/static/src/legacy/utils.js',
'web/static/src/legacy/js/core/misc.js',
'web/static/src/legacy/js/owl_compatibility.js',
'web/static/src/legacy/js/services/session.js',
'web/static/src/legacy/js/public/public_env.js',
'web/static/src/legacy/js/public/public_root.js', 'web/static/src/legacy/js/public/public_root.js',
'web/static/src/legacy/js/public/public_root_instance.js', 'web/static/src/legacy/js/public/public_root_instance.js',
'web/static/src/legacy/js/public/public_widget.js', 'web/static/src/legacy/js/public/public_widget.js',
'web/static/src/legacy/legacy_promise_error_handler.js', 'web/static/src/legacy/js/public/signin.js',
'web/static/src/legacy/legacy_rpc_error_handler.js',
'web/static/src/legacy/js/fields/field_utils.js',
('include', 'web.frontend_legacy'),
], ],
'web.assets_frontend_lazy': [ 'web.assets_frontend_lazy': [
('include', 'web.assets_frontend'), ('include', 'web.assets_frontend'),
# Remove assets_frontend_minimal # Remove assets_frontend_minimal
('remove', 'web/static/src/legacy/js/promise_extension.js'), ('remove', 'web/static/src/module_loader.js'),
('remove', 'web/static/src/boot.js'),
('remove', 'web/static/src/session.js'), ('remove', 'web/static/src/session.js'),
('remove', 'web/static/src/legacy/js/core/cookie_utils.js'), ('remove', 'web/static/src/core/browser/cookie.js'),
('remove', 'web/static/src/legacy/js/core/menu.js'),
('remove', 'web/static/src/legacy/js/core/minimal_dom.js'), ('remove', 'web/static/src/legacy/js/core/minimal_dom.js'),
('remove', 'web/static/src/legacy/js/public/lazyloader.js'), ('remove', 'web/static/src/legacy/js/public/lazyloader.js'),
], ],
'web.assets_backend_prod_only': [
'web/static/src/main.js',
'web/static/src/start.js',
'web/static/src/legacy/legacy_setup.js',
],
# Optional Bundle for PDFJS lib # Optional Bundle for PDFJS lib
# Since PDFJS is quite huge (80000≈ lines), please only load it when it is necessary. # Since PDFJS is quite huge (80000≈ lines), please only load it when it is necessary.
# For now, it is only use to display the PDF slide Viewer during an embed. # For now, it is only use to display the PDF slide Viewer during an embed.
@ -495,10 +243,29 @@ This module provides the core of the Odoo Web Client.
'web/static/src/scss/pre_variables.scss', 'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss', 'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap'), ('include', 'web._assets_bootstrap_backend'),
'web/static/lib/bootstrap/js/dist/dom/data.js',
'web/static/lib/bootstrap/js/dist/dom/event-handler.js',
'web/static/lib/bootstrap/js/dist/dom/manipulator.js',
'web/static/lib/bootstrap/js/dist/dom/selector-engine.js',
'web/static/lib/bootstrap/js/dist/base-component.js',
'web/static/lib/bootstrap/js/dist/alert.js',
'web/static/lib/bootstrap/js/dist/button.js',
'web/static/lib/bootstrap/js/dist/carousel.js',
'web/static/lib/bootstrap/js/dist/collapse.js',
'web/static/lib/bootstrap/js/dist/dropdown.js',
'web/static/lib/bootstrap/js/dist/modal.js',
'web/static/lib/bootstrap/js/dist/offcanvas.js',
'web/static/lib/bootstrap/js/dist/tooltip.js',
'web/static/lib/bootstrap/js/dist/popover.js',
'web/static/lib/bootstrap/js/dist/scrollspy.js',
'web/static/lib/bootstrap/js/dist/tab.js',
'web/static/lib/bootstrap/js/dist/toast.js',
'base/static/src/css/description.css', 'base/static/src/css/description.css',
'web/static/src/libs/fontawesome/css/font-awesome.css', 'web/static/src/libs/fontawesome/css/font-awesome.css',
'web/static/src/scss/fontawesome_overridden.scss',
'web/static/lib/odoo_ui_icons/*', 'web/static/lib/odoo_ui_icons/*',
'web/static/fonts/fonts.scss', 'web/static/fonts/fonts.scss',
@ -508,30 +275,29 @@ This module provides the core of the Odoo Web Client.
'web/static/src/webclient/actions/reports/layout_assets/layout_boxed.scss', 'web/static/src/webclient/actions/reports/layout_assets/layout_boxed.scss',
'web/static/src/webclient/actions/reports/layout_assets/layout_clean.scss', 'web/static/src/webclient/actions/reports/layout_assets/layout_clean.scss',
'web/static/asset_styles_company_report.scss', 'web/static/asset_styles_company_report.scss',
'web/static/src/legacy/js/services/session.js',
'web/static/src/legacy/js/public/public_root.js',
'web/static/src/legacy/js/public/public_root_instance.js',
'web/static/src/legacy/js/public/public_widget.js',
'web/static/src/legacy/js/report/report.js',
], ],
'web.report_assets_pdf': [ 'web.report_assets_pdf': [
'web/static/src/webclient/actions/reports/reset.min.css', 'web/static/src/webclient/actions/reports/reset.min.css',
], ],
'web.ace_lib': [
"web/static/lib/ace/ace.js",
"web/static/lib/ace/mode-js.js",
"web/static/lib/ace/javascript_highlight_rules.js",
"web/static/lib/ace/mode-xml.js",
"web/static/lib/ace/mode-qweb.js",
"web/static/lib/ace/mode-python.js",
"web/static/lib/ace/mode-scss.js",
"web/static/lib/ace/theme-monokai.js",
],
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# COLOR SCHEME BUNDLES # COLOR SCHEME BUNDLES
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
"web.dark_mode_assets_common": [ "web.assets_web_dark": [
('include', 'web.assets_common'), ('include', 'web.assets_web'),
],
"web.dark_mode_assets_backend": [
('include', 'web.assets_backend'),
'web/static/src/**/*.dark.scss', 'web/static/src/**/*.dark.scss',
], ],
"web.dark_mode_variables": [
('before', 'base/static/src/scss/onboarding.variables.scss', 'base/static/src/scss/onboarding.variables.dark.scss'),
],
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# SUB BUNDLES # SUB BUNDLES
@ -542,14 +308,25 @@ This module provides the core of the Odoo Web Client.
# Their naming conventions are similar to those of the main bundles, # Their naming conventions are similar to those of the main bundles,
# with the addition of a prefixed underscore to reflect the "private" # with the addition of a prefixed underscore to reflect the "private"
# aspect. # aspect.
#
# Examples:
# > web._assets_helpers = define assets needed in most main bundles
# Bare javascript essentials: module loader, core folder and core libs
'web._assets_core': [
# module loader
'web/static/src/module_loader.js',
# libs
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
# core
'web/static/src/env.js',
'web/static/src/session.js',
'web/static/src/core/utils/transitions.scss',
'web/static/src/core/**/*',
('remove', 'web/static/src/core/emoji_picker/emoji_data.js'), # always lazy-loaded
],
'web._assets_primary_variables': [ 'web._assets_primary_variables': [
'web/static/src/scss/primary_variables.scss', 'web/static/src/scss/primary_variables.scss',
'web/static/src/**/**/*.variables.scss', 'web/static/src/**/*.variables.scss',
'base/static/src/scss/onboarding.variables.scss',
], ],
'web._assets_secondary_variables': [ 'web._assets_secondary_variables': [
'web/static/src/scss/secondary_variables.scss', 'web/static/src/scss/secondary_variables.scss',
@ -557,9 +334,10 @@ This module provides the core of the Odoo Web Client.
'web._assets_helpers': [ 'web._assets_helpers': [
'web/static/lib/bootstrap/scss/_functions.scss', 'web/static/lib/bootstrap/scss/_functions.scss',
'web/static/lib/bootstrap/scss/_mixins.scss', 'web/static/lib/bootstrap/scss/_mixins.scss',
'web/static/src/scss/functions.scss',
'web/static/src/scss/mixins_forwardport.scss', 'web/static/src/scss/mixins_forwardport.scss',
'web/static/src/scss/bs_mixins_overrides.scss', 'web/static/src/scss/bs_mixins_overrides.scss',
'web/static/src/legacy/scss/utils.scss', 'web/static/src/scss/utils.scss',
('include', 'web._assets_primary_variables'), ('include', 'web._assets_primary_variables'),
('include', 'web._assets_secondary_variables'), ('include', 'web._assets_secondary_variables'),
@ -571,6 +349,15 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/bootstrap/scss/utilities/_api.scss', 'web/static/lib/bootstrap/scss/utilities/_api.scss',
'web/static/src/scss/bootstrap_review.scss', 'web/static/src/scss/bootstrap_review.scss',
], ],
'web._assets_bootstrap_backend': [
('include', 'web._assets_bootstrap'),
('after', 'web/static/src/scss/utilities_custom.scss', 'web/static/src/scss/utilities_custom_backend.scss'),
'web/static/src/scss/bootstrap_review_backend.scss',
],
'web._assets_bootstrap_frontend': [
('include', 'web._assets_bootstrap'),
'web/static/src/scss/bootstrap_review_frontend.scss',
],
'web._assets_backend_helpers': [ 'web._assets_backend_helpers': [
'web/static/src/scss/bootstrap_overridden.scss', 'web/static/src/scss/bootstrap_overridden.scss',
'web/static/src/scss/bs_mixins_overrides_backend.scss', 'web/static/src/scss/bs_mixins_overrides_backend.scss',
@ -579,11 +366,6 @@ This module provides the core of the Odoo Web Client.
'web/static/src/scss/bootstrap_overridden_frontend.scss', 'web/static/src/scss/bootstrap_overridden_frontend.scss',
], ],
# Used during the transition of the web architecture
'web.frontend_legacy': [
'web/static/src/legacy/frontend/**/*',
],
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# TESTS BUNDLES # TESTS BUNDLES
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
@ -591,29 +373,30 @@ This module provides the core of the Odoo Web Client.
'web.assets_tests': [ 'web.assets_tests': [
# No tours are defined in web, but the bundle "assets_tests" is # No tours are defined in web, but the bundle "assets_tests" is
# first called in web. # first called in web.
'web/static/tests/legacy/helpers/test_utils_file.js',
'web/static/tests/helpers/cleanup.js', 'web/static/tests/helpers/cleanup.js',
'web/static/tests/helpers/utils.js', 'web/static/tests/helpers/utils.js',
'web/static/tests/utils.js', 'web/static/tests/utils.js',
], ],
# remove this bundle alongside the owl2 compatibility layer 'web.__assets_tests_call__': [
'web.tests_assets_common': [ 'web/static/tests/ignore_missing_deps_start.js',
('include', 'web.assets_common'), ('include', 'web.assets_tests'),
('after', 'web/static/src/owl2_compatibility/app.js', 'web/static/tests/owl2_compatibility_app.js'), 'web/static/tests/ignore_missing_deps_stop.js',
], ],
'web.tests_assets': [ 'web.tests_assets': [
('include', 'web.assets_backend'),
'web/static/src/public/public_component_service.js',
'web/static/tests/patch_translations.js',
'web/static/lib/qunit/qunit-2.9.1.css', 'web/static/lib/qunit/qunit-2.9.1.css',
'web/static/lib/qunit/qunit-2.9.1.js', 'web/static/lib/qunit/qunit-2.9.1.js',
'web/static/tests/legacy/helpers/**/*', 'web/static/tests/legacy/helpers/**/*',
('remove', 'web/static/tests/legacy/helpers/test_utils_tests.js'), ('remove', 'web/static/tests/legacy/helpers/test_utils_tests.js'),
'web/static/tests/legacy/legacy_setup.js',
'web/static/lib/fullcalendar/core/main.css', 'web/static/lib/fullcalendar/core/main.css',
'web/static/lib/fullcalendar/daygrid/main.css', 'web/static/lib/fullcalendar/daygrid/main.css',
'web/static/lib/fullcalendar/timegrid/main.css', 'web/static/lib/fullcalendar/timegrid/main.css',
'web/static/lib/fullcalendar/list/main.css', 'web/static/lib/fullcalendar/list/main.css',
'web/static/lib/fullcalendar/core/main.js', 'web/static/lib/fullcalendar/core/main.js',
'web/static/lib/fullcalendar/moment/main.js',
'web/static/lib/fullcalendar/interaction/main.js', 'web/static/lib/fullcalendar/interaction/main.js',
'web/static/lib/fullcalendar/daygrid/main.js', 'web/static/lib/fullcalendar/daygrid/main.js',
'web/static/lib/fullcalendar/timegrid/main.js', 'web/static/lib/fullcalendar/timegrid/main.js',
@ -628,17 +411,13 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/ace/mode-xml.js', 'web/static/lib/ace/mode-xml.js',
'web/static/lib/ace/mode-js.js', 'web/static/lib/ace/mode-js.js',
'web/static/lib/ace/mode-qweb.js', 'web/static/lib/ace/mode-qweb.js',
'web/static/lib/nearest/jquery.nearest.js', 'web/static/lib/ace/theme-monokai.js',
'web/static/lib/daterangepicker/daterangepicker.js',
'web/static/src/legacy/js/libs/daterangepicker.js',
'web/static/lib/stacktracejs/stacktrace.js', 'web/static/lib/stacktracejs/stacktrace.js',
'web/static/lib/Chart/Chart.js', ('include', "web.chartjs_lib"),
'web/static/lib/jSignature/jSignatureCustom.js',
'web/static/src/libs/jSignatureCustom.js',
'/web/static/lib/daterangepicker/daterangepicker.js',
# 'web/static/tests/legacy/main_tests.js',
'web/static/tests/helpers/**/*.js', 'web/static/tests/helpers/**/*.js',
'web/static/tests/utils.js',
'web/static/tests/views/helpers.js', 'web/static/tests/views/helpers.js',
'web/static/tests/search/helpers.js', 'web/static/tests/search/helpers.js',
'web/static/tests/views/calendar/helpers.js', 'web/static/tests/views/calendar/helpers.js',
@ -647,50 +426,39 @@ This module provides the core of the Odoo Web Client.
'web/static/tests/main.js', 'web/static/tests/main.js',
'web/static/tests/mock_server_tests.js', 'web/static/tests/mock_server_tests.js',
'web/static/tests/setup.js', 'web/static/tests/setup.js',
'web/static/tests/utils.js',
# These 2 lines below are taken from web.assets_frontend 'web/static/src/webclient/clickbot/clickbot.js',
# They're required for the web.frontend_legacy to work properly
# It is expected to add other lines coming from the web.assets_frontend
# if we need to add more and more legacy stuff that would require other scss or js.
('include', 'web._assets_helpers'),
'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web.frontend_legacy'),
("include", "web.assets_backend_legacy_lazy"),
], ],
'web.qunit_suite_tests': [ 'web.qunit_suite_tests': [
'web/static/tests/env_tests.js', 'web/static/tests/env_tests.js',
'web/static/tests/dependencies_tests.js',
'web/static/tests/reactivity_tests.js', 'web/static/tests/reactivity_tests.js',
'web/static/tests/core/**/*.js', 'web/static/tests/core/**/*.js',
'web/static/tests/l10n/**/*.js', 'web/static/tests/l10n/**/*.js',
'web/static/tests/search/**/*.js', 'web/static/tests/search/**/*.js',
'web/static/tests/model/**/*.js',
('remove', 'web/static/tests/search/helpers.js'), ('remove', 'web/static/tests/search/helpers.js'),
'web/static/tests/views/**/*.js', 'web/static/tests/views/**/*.js',
('remove', 'web/static/tests/views/helpers.js'), ('remove', 'web/static/tests/views/helpers.js'),
('remove', 'web/static/tests/views/calendar/helpers.js'), ('remove', 'web/static/tests/views/calendar/helpers.js'),
'web/static/tests/webclient/**/*.js', 'web/static/tests/webclient/**/*.js',
('remove', 'web/static/tests/webclient/**/helpers.js'), ('remove', 'web/static/tests/webclient/**/helpers.js'),
'web/static/tests/legacy/**/*.js', 'web/static/tests/public/**/*.js',
('remove', 'web/static/tests/legacy/**/*_mobile_tests.js'),
('remove', 'web/static/tests/legacy/**/*_benchmarks.js'),
('remove', 'web/static/tests/legacy/helpers/**/*.js'),
('remove', 'web/static/tests/legacy/legacy_setup.js'),
('include', 'web.frontend_legacy_tests'), # Legacy
'web/static/tests/legacy/**/*.js',
('remove', 'web/static/tests/legacy/helpers/**/*.js'),
], ],
'web.qunit_mobile_suite_tests': [ 'web.qunit_mobile_suite_tests': [
'web/static/tests/mobile/**/*.js', 'web/static/tests/mobile/**/*.js',
'web/static/tests/legacy/fields/basic_fields_mobile_tests.js',
'web/static/tests/legacy/fields/relational_fields_mobile_tests.js',
'web/static/tests/legacy/components/dropdown_menu_mobile_tests.js',
], ],
'web.assets_clickbot': [
# Used during the transition of the web architecture 'web/static/src/webclient/clickbot/clickbot.js',
'web.frontend_legacy_tests': [
'web/static/tests/legacy/frontend/*.js',
], ],
"web.chartjs_lib" : [
'/web/static/lib/Chart/Chart.js',
'/web/static/lib/chartjs-adapter-luxon/chartjs-adapter-luxon.js',
]
}, },
'bootstrap': True, # load translations for login screen, 'bootstrap': True, # load translations for login screen,
'license': 'LGPL-3', 'license': 'LGPL-3',

View file

@ -11,7 +11,9 @@ from . import pivot
from . import profiling from . import profiling
from . import report from . import report
from . import session from . import session
from . import vcard
from . import view from . import view
from . import webclient from . import webclient
from . import webmanifest
from . import main # deprecated from . import main # deprecated

View file

@ -1,6 +1,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging import logging
from odoo import _
from odoo.exceptions import MissingError
from odoo.http import Controller, request, route from odoo.http import Controller, request, route
from .utils import clean_action from .utils import clean_action
@ -21,8 +23,8 @@ class Action(Controller):
action = request.env.ref(action_id) action = request.env.ref(action_id)
assert action._name.startswith('ir.actions.') assert action._name.startswith('ir.actions.')
action_id = action.id action_id = action.id
except Exception: except Exception as exc:
action_id = 0 # force failed read raise MissingError(_("The action %r does not exist.", action_id)) from exc
base_action = Actions.browse([action_id]).sudo().read(['type']) base_action = Actions.browse([action_id]).sudo().read(['type'])
if base_action: if base_action:
@ -37,7 +39,9 @@ class Action(Controller):
return value return value
@route('/web/action/run', type='json', auth="user") @route('/web/action/run', type='json', auth="user")
def run(self, action_id): def run(self, action_id, context=None):
if context:
request.update_context(**context)
action = request.env['ir.actions.server'].browse([action_id]) action = request.env['ir.actions.server'].browse([action_id])
result = action.run() result = action.run()
return clean_action(result, env=action.env) if result else False return clean_action(result, env=action.env) if result else False

View file

@ -15,14 +15,13 @@ except ImportError:
import odoo import odoo
import odoo.modules.registry import odoo.modules.registry
from odoo import http, _ from odoo import SUPERUSER_ID, _, http
from odoo.addons.base.models.assetsbundle import ANY_UNIQUE
from odoo.exceptions import AccessError, UserError from odoo.exceptions import AccessError, UserError
from odoo.http import request, Response from odoo.http import request, Response
from odoo.modules import get_resource_path
from odoo.tools import file_open, file_path, replace_exceptions, str2bool from odoo.tools import file_open, file_path, replace_exceptions, str2bool
from odoo.tools.mimetypes import guess_mimetype
from odoo.tools.image import image_guess_size_from_field_name from odoo.tools.image import image_guess_size_from_field_name
from odoo.tools.mimetypes import guess_mimetype
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -85,33 +84,59 @@ class Binary(http.Controller):
return stream.get_response(**send_file_kwargs) return stream.get_response(**send_file_kwargs)
@http.route(['/web/assets/debug/<string:filename>', @http.route([
'/web/assets/debug/<path:extra>/<string:filename>', '/web/assets/<string:unique>/<string:filename>'], type='http', auth="public")
'/web/assets/<int:id>/<string:filename>', def content_assets(self, filename=None, unique=ANY_UNIQUE, nocache=False, assets_params=None):
'/web/assets/<int:id>-<string:unique>/<string:filename>', assets_params = assets_params or {}
'/web/assets/<int:id>-<string:unique>/<path:extra>/<string:filename>'], type='http', auth="public") assert isinstance(assets_params, dict)
# pylint: disable=redefined-builtin,invalid-name debug_assets = unique == 'debug'
def content_assets(self, id=None, filename=None, unique=False, extra=None, nocache=False): if unique in ('any', '%'):
if not id: unique = ANY_UNIQUE
domain = [('url', '!=', False), ('res_model', '=', 'ir.ui.view'), attachment = None
('res_id', '=', 0), ('create_uid', '=', odoo.SUPERUSER_ID)] if unique != 'debug':
if extra: url = request.env['ir.asset']._get_asset_bundle_url(filename, unique, assets_params)
domain += [('url', '=like', f'/web/assets/%/{extra}/{filename}')] assert not '%' in url
else: domain = [
domain += [ ('public', '=', True),
('url', '=like', f'/web/assets/%/{filename}'), ('url', '!=', False),
('url', 'not like', f'/web/assets/%/%/{filename}') ('url', '=like', url),
] ('res_model', '=', 'ir.ui.view'),
attachments = request.env['ir.attachment'].sudo().search_read(domain, fields=['id'], limit=1) ('res_id', '=', 0),
if not attachments: ('create_uid', '=', SUPERUSER_ID),
raise request.not_found() ]
id = attachments[0]['id'] attachment = request.env['ir.attachment'].sudo().search(domain, limit=1)
with replace_exceptions(UserError, by=request.not_found()): if not attachment:
record = request.env['ir.binary']._find_record(res_id=int(id)) # try to generate one
stream = request.env['ir.binary']._get_stream_from(record, 'raw', filename) try:
if filename.endswith('.map'):
send_file_kwargs = {'as_attachment': False, 'content_security_policy': None} _logger.error(".map should have been generated through debug assets, (version %s most likely outdated)", unique)
if unique: raise request.not_found()
bundle_name, rtl, asset_type = request.env['ir.asset']._parse_bundle_name(filename, debug_assets)
css = asset_type == 'css'
js = asset_type == 'js'
bundle = request.env['ir.qweb']._get_asset_bundle(
bundle_name,
css=css,
js=js,
debug_assets=debug_assets,
rtl=rtl,
assets_params=assets_params,
)
# check if the version matches. If not, redirect to the last version
if not debug_assets and unique != ANY_UNIQUE and unique != bundle.get_version(asset_type):
return request.redirect(bundle.get_link(asset_type))
if css and bundle.stylesheets:
attachment = bundle.css()
elif js and bundle.javascripts:
attachment = bundle.js()
except ValueError as e:
_logger.warning("Parsing asset bundle %s has failed: %s", filename, e)
raise request.not_found() from e
if not attachment:
raise request.not_found()
stream = request.env['ir.binary']._get_stream_from(attachment, 'raw', filename)
send_file_kwargs = {'as_attachment': False}
if unique and unique != 'debug':
send_file_kwargs['immutable'] = True send_file_kwargs['immutable'] = True
send_file_kwargs['max_age'] = http.STATIC_CACHE_LONG send_file_kwargs['max_age'] = http.STATIC_CACHE_LONG
if nocache: if nocache:
@ -190,7 +215,7 @@ class Binary(http.Controller):
try: try:
attachment = Model.create({ attachment = Model.create({
'name': filename, 'name': filename,
'datas': base64.encodebytes(ufile.read()), 'raw': ufile.read(),
'res_model': model, 'res_model': model,
'res_id': int(id) 'res_id': int(id)
}) })
@ -203,7 +228,7 @@ class Binary(http.Controller):
else: else:
args.append({ args.append({
'filename': clean(filename), 'filename': clean(filename),
'mimetype': ufile.content_type, 'mimetype': attachment.mimetype,
'id': attachment.id, 'id': attachment.id,
'size': attachment.file_size 'size': attachment.file_size
}) })
@ -217,12 +242,11 @@ class Binary(http.Controller):
def company_logo(self, dbname=None, **kw): def company_logo(self, dbname=None, **kw):
imgname = 'logo' imgname = 'logo'
imgext = '.png' imgext = '.png'
placeholder = functools.partial(get_resource_path, 'web', 'static', 'img')
dbname = request.db dbname = request.db
uid = (request.session.uid if dbname else None) or odoo.SUPERUSER_ID uid = (request.session.uid if dbname else None) or odoo.SUPERUSER_ID
if not dbname: if not dbname:
response = http.Stream.from_path(placeholder(imgname + imgext)).get_response() response = http.Stream.from_path(file_path('web/static/img/logo.png')).get_response()
else: else:
try: try:
# create an empty registry # create an empty registry
@ -258,9 +282,9 @@ class Binary(http.Controller):
response_class=Response, response_class=Response,
) )
else: else:
response = http.Stream.from_path(placeholder('nologo.png')).get_response() response = http.Stream.from_path(file_path('web/static/img/nologo.png')).get_response()
except Exception: except Exception:
response = http.Stream.from_path(placeholder(imgname + imgext)).get_response() response = http.Stream.from_path(file_path(f'web/static/img/{imgname}{imgext}')).get_response()
return response return response
@ -276,7 +300,7 @@ class Binary(http.Controller):
""" """
supported_exts = ('.ttf', '.otf', '.woff', '.woff2') supported_exts = ('.ttf', '.otf', '.woff', '.woff2')
fonts = [] fonts = []
fonts_directory = file_path(os.path.join('web', 'static', 'fonts', 'sign')) fonts_directory = file_path('web/static/fonts/sign')
if fontname: if fontname:
font_path = os.path.join(fonts_directory, fontname) font_path = os.path.join(fonts_directory, fontname)
with file_open(font_path, 'rb', filter_ext=supported_exts) as font_file: with file_open(font_path, 'rb', filter_ext=supported_exts) as font_file:

View file

@ -75,7 +75,7 @@ class Database(http.Controller):
dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd]) dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd])
try: try:
if not re.match(DBNAME_PATTERN, name): if not re.match(DBNAME_PATTERN, name):
raise Exception(_('Invalid database name. Only alphanumerical characters, underscore, hyphen and dot are allowed.')) raise Exception(_('Houston, we have a database naming issue! Make sure you only use letters, numbers, underscores, hyphens, or dots in the database name, and you\'ll be golden.'))
# country code could be = "False" which is actually True in python # country code could be = "False" which is actually True in python
country_code = post.get('country_code') or False country_code = post.get('country_code') or False
dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code, post['phone']]) dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code, post['phone']])
@ -94,7 +94,7 @@ class Database(http.Controller):
dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd]) dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd])
try: try:
if not re.match(DBNAME_PATTERN, new_name): if not re.match(DBNAME_PATTERN, new_name):
raise Exception(_('Invalid database name. Only alphanumerical characters, underscore, hyphen and dot are allowed.')) raise Exception(_('Houston, we have a database naming issue! Make sure you only use letters, numbers, underscores, hyphens, or dots in the database name, and you\'ll be golden.'))
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name, neutralize_database]) dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name, neutralize_database])
if request.db == name: if request.db == name:
request.env.cr.close() # duplicating a database leads to an unusable cursor request.env.cr.close() # duplicating a database leads to an unusable cursor
@ -140,7 +140,7 @@ class Database(http.Controller):
error = "Database backup error: %s" % (str(e) or repr(e)) error = "Database backup error: %s" % (str(e) or repr(e))
return self._render_template(error=error) return self._render_template(error=error)
@http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False) @http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False, max_content_length=None)
def restore(self, master_pwd, backup_file, name, copy=False, neutralize_database=False): def restore(self, master_pwd, backup_file, name, copy=False, neutralize_database=False):
insecure = odoo.tools.config.verify_admin_password('admin') insecure = odoo.tools.config.verify_admin_password('admin')
if insecure and master_pwd: if insecure and master_pwd:

View file

@ -15,29 +15,11 @@ _logger = logging.getLogger(__name__)
class DataSet(http.Controller): class DataSet(http.Controller):
@http.route('/web/dataset/search_read', type='json', auth="user")
def search_read(self, model, fields=False, offset=0, limit=False, domain=None, sort=None):
return request.env[model].web_search_read(domain, fields, offset=offset, limit=limit, order=sort)
@http.route('/web/dataset/load', type='json', auth="user")
def load(self, model, id, fields):
warnings.warn("the route /web/dataset/load is deprecated and will be removed in Odoo 17. Use /web/dataset/call_kw with method 'read' and a list containing the id as args instead", DeprecationWarning)
value = {}
r = request.env[model].browse([id]).read()
if r:
value = r[0]
return {'value': value}
def _call_kw(self, model, method, args, kwargs): def _call_kw(self, model, method, args, kwargs):
Model = request.env[model] Model = request.env[model]
get_public_method(Model, method) # Don't use the result, call_kw will redo the getattr get_public_method(Model, method) # Don't use the result, call_kw will redo the getattr
return call_kw(Model, method, args, kwargs) return call_kw(Model, method, args, kwargs)
@http.route('/web/dataset/call', type='json', auth="user")
def call(self, model, method, args, domain_id=None, context_id=None):
warnings.warn("the route /web/dataset/call is deprecated and will be removed in Odoo 17. Use /web/dataset/call_kw with empty kwargs instead", DeprecationWarning)
return self._call_kw(model, method, args, {})
@http.route(['/web/dataset/call_kw', '/web/dataset/call_kw/<path:path>'], type='json', auth="user") @http.route(['/web/dataset/call_kw', '/web/dataset/call_kw/<path:path>'], type='json', auth="user")
def call_kw(self, model, method, args, kwargs, path=None): def call_kw(self, model, method, args, kwargs, path=None):
return self._call_kw(model, method, args, kwargs) return self._call_kw(model, method, args, kwargs)
@ -50,7 +32,7 @@ class DataSet(http.Controller):
return False return False
@http.route('/web/dataset/resequence', type='json', auth="user") @http.route('/web/dataset/resequence', type='json', auth="user")
def resequence(self, model, ids, field='sequence', offset=0): def resequence(self, model, ids, field='sequence', offset=0, context=None):
""" Re-sequences a number of records in the model, by their ids """ Re-sequences a number of records in the model, by their ids
The re-sequencing starts at the first model of ``ids``, the sequence The re-sequencing starts at the first model of ``ids``, the sequence
@ -64,6 +46,8 @@ class DataSet(http.Controller):
starting the resequencing from an arbitrary number, starting the resequencing from an arbitrary number,
defaults to ``0`` defaults to ``0``
""" """
if context:
request.update_context(**context)
m = request.env[model] m = request.env[model]
if not m.fields_get([field]): if not m.fields_get([field]):
return False return False

View file

@ -225,7 +225,7 @@ class ExportXlsxWriter:
cell_value = pycompat.to_text(cell_value) cell_value = pycompat.to_text(cell_value)
except UnicodeDecodeError: except UnicodeDecodeError:
raise UserError(_("Binary fields can not be exported to Excel unless their content is base64-encoded. That does not seem to be the case for %s.", self.field_names)[column]) raise UserError(_("Binary fields can not be exported to Excel unless their content is base64-encoded. That does not seem to be the case for %s.", self.field_names)[column])
elif isinstance(cell_value, (list, tuple)): elif isinstance(cell_value, (list, tuple, dict)):
cell_value = pycompat.to_text(cell_value) cell_value = pycompat.to_text(cell_value)
if isinstance(cell_value, str): if isinstance(cell_value, str):
@ -335,10 +335,7 @@ class Export(http.Controller):
if field.get('type') in ('properties', 'properties_definition'): if field.get('type') in ('properties', 'properties_definition'):
continue continue
if field.get('readonly'): if field.get('readonly'):
# If none of the field's states unsets readonly, skip the field continue
if all(dict(attrs).get('readonly', True)
for attrs in field.get('states', {}).values()):
continue
if not field.get('exportable', True): if not field.get('exportable', True):
continue continue
@ -488,7 +485,7 @@ class ExportFormat(object):
if not import_compat and groupby: if not import_compat and groupby:
groupby_type = [Model._fields[x.split(':')[0]].type for x in groupby] groupby_type = [Model._fields[x.split(':')[0]].type for x in groupby]
domain = [('id', 'in', ids)] if ids else domain domain = [('id', 'in', ids)] if ids else domain
groups_data = Model.with_context(active_test=False).read_group(domain, [x if x != '.id' else 'id' for x in field_names], groupby, lazy=False) groups_data = Model.with_context(active_test=False).read_group(domain, ['__count'], groupby, lazy=False)
# read_group(lazy=False) returns a dict only for final groups (with actual data), # read_group(lazy=False) returns a dict only for final groups (with actual data),
# not for intermediary groups. The full group tree must be re-constructed. # not for intermediary groups. The full group tree must be re-constructed.
@ -523,7 +520,7 @@ class ExportFormat(object):
class CSVExport(ExportFormat, http.Controller): class CSVExport(ExportFormat, http.Controller):
@http.route('/web/export/csv', type='http', auth="user") @http.route('/web/export/csv', type='http', auth="user")
def index(self, data): def web_export_csv(self, data):
try: try:
return self.base(data) return self.base(data)
except Exception as exc: except Exception as exc:
@ -567,7 +564,7 @@ class CSVExport(ExportFormat, http.Controller):
class ExcelExport(ExportFormat, http.Controller): class ExcelExport(ExportFormat, http.Controller):
@http.route('/web/export/xlsx', type='http', auth="user") @http.route('/web/export/xlsx', type='http', auth="user")
def index(self, data): def web_export_xlsx(self, data):
try: try:
return self.base(data) return self.base(data)
except Exception as exc: except Exception as exc:

View file

@ -41,7 +41,7 @@ class Home(http.Controller):
# Ensure we have both a database and a user # Ensure we have both a database and a user
ensure_db() ensure_db()
if not request.session.uid: if not request.session.uid:
return request.redirect('/web/login', 303) return request.redirect_query('/web/login', query=request.params, code=303)
if kw.get('redirect'): if kw.get('redirect'):
return request.redirect(kw.get('redirect'), 303) return request.redirect(kw.get('redirect'), 303)
if not security.check_session(request.session, request.env): if not security.check_session(request.session, request.env):
@ -63,12 +63,16 @@ class Home(http.Controller):
return request.redirect('/web/login?error=access') return request.redirect('/web/login?error=access')
@http.route('/web/webclient/load_menus/<string:unique>', type='http', auth='user', methods=['GET']) @http.route('/web/webclient/load_menus/<string:unique>', type='http', auth='user', methods=['GET'])
def web_load_menus(self, unique): def web_load_menus(self, unique, lang=None):
""" """
Loads the menus for the webclient Loads the menus for the webclient
:param unique: this parameters is not used, but mandatory: it is used by the HTTP stack to make a unique request :param unique: this parameters is not used, but mandatory: it is used by the HTTP stack to make a unique request
:param lang: language in which the menus should be loaded (only works if language is installed)
:return: the menus (including the images in Base64) :return: the menus (including the images in Base64)
""" """
if lang:
request.update_context(lang=lang)
menus = request.env["ir.ui.menu"].load_web_menus(request.session.debug) menus = request.env["ir.ui.menu"].load_web_menus(request.session.debug)
body = json.dumps(menus, default=ustr) body = json.dumps(menus, default=ustr)
response = request.make_response(body, [ response = request.make_response(body, [
@ -143,7 +147,7 @@ class Home(http.Controller):
if request.env.user._is_system(): if request.env.user._is_system():
uid = request.session.uid = odoo.SUPERUSER_ID uid = request.session.uid = odoo.SUPERUSER_ID
# invalidate session token cache as we've changed the uid # invalidate session token cache as we've changed the uid
request.env['res.users'].clear_caches() request.env.registry.clear_cache()
request.session.session_token = security.compute_session_token(request.session, request.env) request.session.session_token = security.compute_session_token(request.session, request.env)
return request.redirect(self._login_redirect(uid)) return request.redirect(self._login_redirect(uid))
@ -165,11 +169,16 @@ class Home(http.Controller):
('Cache-Control', 'no-store')] ('Cache-Control', 'no-store')]
return request.make_response(data, headers, status=status) return request.make_response(data, headers, status=status)
@http.route(['/robots.txt'], type='http', auth="none")
def robots(self, **kwargs):
allowed_routes = self._get_allowed_robots_routes()
robots_content = ["User-agent: *", "Disallow: /"]
robots_content.extend(f"Allow: {route}" for route in allowed_routes)
return request.make_response("\n".join(robots_content), [('Content-Type', 'text/plain')])
def _get_allowed_robots_routes(self): def _get_allowed_robots_routes(self):
"""Override this method to return a list of allowed routes. """Override this method to return a list of allowed routes.
By default this controller does not serve robots.txt so all routes
are implicitly open but we want any module to be able to append
to this list, in case the website module is installed.
:return: A list of URL paths that should be allowed by robots.txt :return: A list of URL paths that should be allowed by robots.txt
Examples: ['/social_instagram/', '/sitemap.xml', '/web/'] Examples: ['/social_instagram/', '/sitemap.xml', '/web/']

View file

@ -133,7 +133,7 @@ class ReportController(http.Controller):
else: else:
return return
except Exception as e: except Exception as e:
_logger.exception("Error while generating report %s", reportname) _logger.warning("Error while generating report %s", reportname, exc_info=True)
se = http.serialize_exception(e) se = http.serialize_exception(e)
error = { error = {
'code': 200, 'code': 200,

View file

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import importlib.util
import io
import zipfile
import odoo.http as http
from odoo.exceptions import UserError
from odoo.http import request, content_disposition
class Partner(http.Controller):
@http.route(['/web_enterprise/partner/<model("res.partner"):partner>/vcard',
'/web/partner/vcard'], type='http', auth="user")
def download_vcard(self, partner_ids=None, partner=None, **kwargs):
if importlib.util.find_spec('vobject') is None:
raise UserError('vobject library is not installed')
if partner_ids:
partner_ids = list(filter(None, (int(pid) for pid in partner_ids.split(',') if pid.isdigit())))
partners = request.env['res.partner'].browse(partner_ids)
if len(partners) > 1:
with io.BytesIO() as buffer:
with zipfile.ZipFile(buffer, 'w') as zipf:
for partner in partners:
filename = f"{partner.name or partner.email}.vcf"
content = partner._get_vcard_file()
zipf.writestr(filename, content)
return request.make_response(buffer.getvalue(), [
('Content-Type', 'application/zip'),
('Content-Length', len(content)),
('Content-Disposition', content_disposition('Contacts.zip'))
])
if partner or partners:
partner = partner or partners
content = partner._get_vcard_file()
return request.make_response(content, [
('Content-Type', 'text/vcard'),
('Content-Length', len(content)),
('Content-Disposition', content_disposition(f"{partner.name or partner.email}.vcf")),
])
return request.not_found()

View file

@ -1,6 +1,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import AccessError
from odoo.http import Controller, route, request from odoo.http import Controller, route, request
from odoo.tools.translate import _
class View(Controller): class View(Controller):
@ -14,6 +16,8 @@ class View(Controller):
:param str arch: the edited arch of the custom view :param str arch: the edited arch of the custom view
:returns: dict with acknowledged operation (result set to True) :returns: dict with acknowledged operation (result set to True)
""" """
custom_view = request.env['ir.ui.view.custom'].browse(custom_id) custom_view = request.env['ir.ui.view.custom'].sudo().browse(custom_id)
if not custom_view.user_id == request.env.user:
raise AccessError(_("Custom view %s does not belong to user %s", custom_id, self.env.user.login))
custom_view.write({'arch': arch}) custom_view.write({'arch': arch})
return {'result': True} return {'result': True}

View file

@ -13,10 +13,10 @@ import werkzeug.wsgi
import odoo import odoo
import odoo.modules.registry import odoo.modules.registry
from odoo import http from odoo import http
from odoo.modules import get_manifest, get_resource_path from odoo.modules import get_manifest
from odoo.http import request from odoo.http import request
from odoo.tools import lazy from odoo.tools import lazy
from odoo.tools.misc import file_open from odoo.tools.misc import file_open, file_path
from .utils import _local_web_translations from .utils import _local_web_translations
@ -29,32 +29,11 @@ def CONTENT_MAXAGE():
return http.STATIC_CACHE_LONG return http.STATIC_CACHE_LONG
MOMENTJS_LANG_CODES_MAP = {
"sr_RS": "sr_cyrl",
"sr@latin": "sr"
}
class WebClient(http.Controller): class WebClient(http.Controller):
# FIXME: to be removed in master, deprecated since momentjs removal in commit 4327c062d820
@http.route('/web/webclient/locale/<string:lang>', type='http', auth="none") @http.route('/web/webclient/locale/<string:lang>', type='http', auth="none")
def load_locale(self, lang): def load_locale(self, lang):
lang = MOMENTJS_LANG_CODES_MAP.get(lang, lang)
magic_file_finding = [lang.replace("_", '-').lower(), lang.split('_')[0]]
for code in magic_file_finding:
try:
return http.Response(
werkzeug.wsgi.wrap_file(
request.httprequest.environ,
file_open(f'web/static/lib/moment/locale/{code}.js', 'rb')
),
content_type='application/javascript; charset=utf-8',
headers=[('Cache-Control', f'max-age={http.STATIC_CACHE}')],
direct_passthrough=True,
)
except IOError:
_logger.debug("No moment locale for code %s", code)
return request.make_response("", headers=[ return request.make_response("", headers=[
('Content-Type', 'application/javascript'), ('Content-Type', 'application/javascript'),
('Cache-Control', f'max-age={http.STATIC_CACHE}'), ('Cache-Control', f'max-age={http.STATIC_CACHE}'),
@ -80,7 +59,7 @@ class WebClient(http.Controller):
for addon_name in mods: for addon_name in mods:
manifest = get_manifest(addon_name) manifest = get_manifest(addon_name)
if manifest and manifest['bootstrap']: if manifest and manifest['bootstrap']:
f_name = get_resource_path(addon_name, 'i18n', f'{lang}.po') f_name = file_path(f'{addon_name}/i18n/{lang}.po')
if not f_name: if not f_name:
continue continue
translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)} translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)}
@ -103,10 +82,13 @@ class WebClient(http.Controller):
elif mods is None: elif mods is None:
mods = list(request.env.registry._init_modules) + (odoo.conf.server_wide_modules or []) mods = list(request.env.registry._init_modules) + (odoo.conf.server_wide_modules or [])
if lang and lang not in {code for code, _ in request.env['res.lang'].sudo().get_installed()}:
lang = None
translations_per_module, lang_params = request.env["ir.http"].get_translations_for_webclient(mods, lang) translations_per_module, lang_params = request.env["ir.http"].get_translations_for_webclient(mods, lang)
body = json.dumps({ body = json.dumps({
'lang': lang_params and lang_params["code"], 'lang': lang,
'lang_parameters': lang_params, 'lang_parameters': lang_params,
'modules': translations_per_module, 'modules': translations_per_module,
'multi_lang': len(request.env['res.lang'].sudo().get_installed()) > 1, 'multi_lang': len(request.env['res.lang'].sudo().get_installed()) > 1,
@ -131,10 +113,6 @@ class WebClient(http.Controller):
def test_mobile_suite(self, mod=None, **kwargs): def test_mobile_suite(self, mod=None, **kwargs):
return request.render('web.qunit_mobile_suite') return request.render('web.qunit_mobile_suite')
@http.route('/web/benchmarks', type='http', auth="none")
def benchmarks(self, mod=None, **kwargs):
return request.render('web.benchmark_suite')
@http.route('/web/bundle/<string:bundle_name>', auth="public", methods=["GET"]) @http.route('/web/bundle/<string:bundle_name>', auth="public", methods=["GET"])
def bundle(self, bundle_name, **bundle_params): def bundle(self, bundle_name, **bundle_params):
""" """
@ -148,7 +126,6 @@ class WebClient(http.Controller):
data = [{ data = [{
"type": tag, "type": tag,
"src": attrs.get("src") or attrs.get("data-src") or attrs.get('href'), "src": attrs.get("src") or attrs.get("data-src") or attrs.get('href'),
"content": content, } for tag, attrs in files]
} for tag, attrs, content in files]
return request.make_json_response(data) return request.make_json_response(data)

View file

@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import json
import mimetypes
from odoo import http
from odoo.exceptions import AccessError
from odoo.http import request
from odoo.tools import ustr, file_open
class WebManifest(http.Controller):
def _get_shortcuts(self):
module_names = ['mail', 'crm', 'project', 'project_todo']
try:
module_ids = request.env['ir.module.module'].search([('state', '=', 'installed'), ('name', 'in', module_names)]) \
.sorted(key=lambda r: module_names.index(r["name"]))
except AccessError:
return []
menu_roots = request.env['ir.ui.menu'].get_user_roots()
datas = request.env['ir.model.data'].sudo().search([('model', '=', 'ir.ui.menu'),
('res_id', 'in', menu_roots.ids),
('module', 'in', module_names)])
shortcuts = []
for module in module_ids:
data = datas.filtered(lambda res: res.module == module.name)
if data:
shortcuts.append({
'name': module.display_name,
'url': '/web#menu_id=%s' % data.mapped('res_id')[0],
'description': module.summary,
'icons': [{
'sizes': '100x100',
'src': module.icon,
'type': mimetypes.guess_type(module.icon)[0] or 'image/png'
}]
})
return shortcuts
@http.route('/web/manifest.webmanifest', type='http', auth='public', methods=['GET'])
def webmanifest(self):
""" Returns a WebManifest describing the metadata associated with a web application.
Using this metadata, user agents can provide developers with means to create user
experiences that are more comparable to that of a native application.
"""
web_app_name = request.env['ir.config_parameter'].sudo().get_param('web.web_app_name', 'Odoo')
manifest = {
'name': web_app_name,
'scope': '/web',
'start_url': '/web',
'display': 'standalone',
'background_color': '#714B67',
'theme_color': '#714B67',
'prefer_related_applications': False,
}
icon_sizes = ['192x192', '512x512']
manifest['icons'] = [{
'src': '/web/static/img/odoo-icon-%s.png' % size,
'sizes': size,
'type': 'image/png',
} for size in icon_sizes]
manifest['shortcuts'] = self._get_shortcuts()
body = json.dumps(manifest, default=ustr)
response = request.make_response(body, [
('Content-Type', 'application/manifest+json'),
])
return response
@http.route('/web/service-worker.js', type='http', auth='public', methods=['GET'])
def service_worker(self):
response = request.make_response(
self._get_service_worker_content(),
[
('Content-Type', 'text/javascript'),
('Service-Worker-Allowed', '/web'),
]
)
return response
def _get_service_worker_content(self):
""" Returns a ServiceWorker javascript file scoped for the backend (aka. '/web')
"""
with file_open('web/static/src/service_worker.js') as f:
body = f.read()
return body
def _icon_path(self):
return 'web/static/img/odoo-icon-192x192.png'
@http.route('/web/offline', type='http', auth='public', methods=['GET'])
def offline(self):
""" Returns the offline page delivered by the service worker """
return request.render('web.webclient_offline', {
'odoo_icon': base64.b64encode(file_open(self._icon_path(), 'rb').read())
})

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~12.5\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-23 11:33+0000\n"
"PO-Revision-Date: 2019-09-23 11:33+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es_BO\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web
#: model_terms:ir.ui.view,arch_db:web.external_layout_background
msgid ""
"<i class=\"fa fa-building-o\" role=\"img\" aria-label=\"Fiscal number\"/>"
msgstr "<i class=\"fa fa-building-o\" role=\"img\" aria-label=\"NIT\"/>"

View file

@ -6,9 +6,9 @@
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo 16.0\n" "Project-Id-Version: Odoo 9.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-01-25 10:43+0000\n" "POT-Creation-Date: 2024-02-05 16:24+0000\n"
"PO-Revision-Date: 2016-03-12 06:25+0000\n" "PO-Revision-Date: 2016-03-12 06:25+0000\n"
"Last-Translator: Martin Trigaux\n" "Last-Translator: Martin Trigaux\n"
"Language-Team: Spanish (Chile) (http://www.transifex.com/odoo/odoo-9/" "Language-Team: Spanish (Chile) (http://www.transifex.com/odoo/odoo-9/"
@ -25,12 +25,11 @@ msgstr ""
#. module: web #. module: web
#: model_terms:ir.ui.view,arch_db:web.report_invoice_wizard_preview #: model_terms:ir.ui.view,arch_db:web.report_invoice_wizard_preview
msgid "<strong>Untaxed Amount</strong>" msgid "<strong>Untaxed Amount</strong>"
msgstr "<strong>Total neto</strong>" msgstr "<strong>Monto neto</strong>"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/components/action_menus.js:0 #: code:addons/web/static/src/legacy/js/components/action_menus.js:0
#: code:addons/web/static/src/search/action_menus/action_menus.xml:0
#: code:addons/web/static/src/views/form/status_bar_buttons/status_bar_buttons.xml:0 #: code:addons/web/static/src/views/form/status_bar_buttons/status_bar_buttons.xml:0
#, python-format #, python-format
msgid "Action" msgid "Action"
@ -38,8 +37,7 @@ msgstr "Acción"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.js:0
#: code:addons/web/static/src/legacy/xml/kanban.xml:0
#: code:addons/web/static/src/views/fields/x2many/x2many_field.js:0 #: code:addons/web/static/src/views/fields/x2many/x2many_field.js:0
#: code:addons/web/static/src/views/kanban/kanban_column_quick_create.xml:0 #: code:addons/web/static/src/views/kanban/kanban_column_quick_create.xml:0
#: code:addons/web/static/src/views/kanban/kanban_record_quick_create.xml:0 #: code:addons/web/static/src/views/kanban/kanban_record_quick_create.xml:0
@ -49,17 +47,8 @@ msgstr "Agregar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0 #: code:addons/web/static/src/core/datetime/datetime_picker_popover.xml:0
#, python-format #: code:addons/web/static/src/search/custom_group_by_item/custom_group_by_item.xml:0
msgid "Add: "
msgstr "Agregar: "
#. module: web
#. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/basic_fields.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.xml:0
#: code:addons/web/static/src/search/group_by_menu/custom_group_by_item.xml:0
#: code:addons/web/static/src/views/fields/daterange/daterange_field.js:0
#, python-format #, python-format
msgid "Apply" msgid "Apply"
msgstr "Aplicar" msgstr "Aplicar"
@ -67,17 +56,10 @@ msgstr "Aplicar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0 #: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0
#: code:addons/web/static/src/core/errors/error_dialogs.xml:0
#: code:addons/web/static/src/core/signature/signature_dialog.xml:0 #: code:addons/web/static/src/core/signature/signature_dialog.xml:0
#: code:addons/web/static/src/legacy/js/core/dialog.js:0 #: code:addons/web/static/src/legacy/js/core/dialog.js:0
#: code:addons/web/static/src/legacy/js/fields/basic_fields.js:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.js:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_column.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_confirm_dialog.js:0
#: code:addons/web/static/src/legacy/js/views/signature_dialog.js:0
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#: code:addons/web/static/src/legacy/xml/control_panel.xml:0
#: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0 #: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0
#: code:addons/web/static/src/views/fields/daterange/daterange_field.js:0
#: code:addons/web/static/src/views/list/list_confirmation_dialog.xml:0 #: code:addons/web/static/src/views/list/list_confirmation_dialog.xml:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0
#: code:addons/web/static/src/webclient/settings_form_view/fields/upgrade_dialog.xml:0 #: code:addons/web/static/src/webclient/settings_form_view/fields/upgrade_dialog.xml:0
@ -91,14 +73,14 @@ msgstr "Cancelar"
#: code:addons/web/static/src/core/debug/debug_menu_items.xml:0 #: code:addons/web/static/src/core/debug/debug_menu_items.xml:0
#: code:addons/web/static/src/core/dialog/dialog.xml:0 #: code:addons/web/static/src/core/dialog/dialog.xml:0
#: code:addons/web/static/src/core/domain_selector_dialog/domain_selector_dialog.xml:0 #: code:addons/web/static/src/core/domain_selector_dialog/domain_selector_dialog.xml:0
#: code:addons/web/static/src/core/errors/error_dialogs.xml:0
#: code:addons/web/static/src/core/file_viewer/file_viewer.xml:0
#: code:addons/web/static/src/core/model_field_selector/model_field_selector_popover.xml:0 #: code:addons/web/static/src/core/model_field_selector/model_field_selector_popover.xml:0
#: code:addons/web/static/src/core/notifications/notification.xml:0 #: code:addons/web/static/src/core/notifications/notification.xml:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_column_quick_create.js:0
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#: code:addons/web/static/src/legacy/js/widgets/domain_selector_dialog.js:0 #: code:addons/web/static/src/legacy/js/widgets/domain_selector_dialog.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/legacy/xml/dialog.xml:0 #: code:addons/web/static/src/legacy/xml/dialog.xml:0
#: code:addons/web/static/src/views/fields/dynamic_placeholder_popover.xml:0
#: code:addons/web/static/src/views/fields/relational_utils.xml:0 #: code:addons/web/static/src/views/fields/relational_utils.xml:0
#: code:addons/web/static/src/views/kanban/kanban_column_examples_dialog.xml:0 #: code:addons/web/static/src/views/kanban/kanban_column_examples_dialog.xml:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0
@ -112,7 +94,6 @@ msgstr "Cerrar"
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0 #: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0
#: code:addons/web/static/src/legacy/js/core/dialog.js:0 #: code:addons/web/static/src/legacy/js/core/dialog.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_confirm_dialog.js:0
#: code:addons/web/static/src/views/calendar/calendar_controller.js:0 #: code:addons/web/static/src/views/calendar/calendar_controller.js:0
#: code:addons/web/static/src/views/list/list_confirmation_dialog.js:0 #: code:addons/web/static/src/views/list/list_confirmation_dialog.js:0
#, python-format #, python-format
@ -122,17 +103,22 @@ msgstr "Confirmación"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0 #: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_controller.js:0
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.xml:0 #: code:addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.xml:0
#: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0 #: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0
#: code:addons/web/static/src/views/fields/many2one/many2one_field.xml:0 #: code:addons/web/static/src/views/fields/many2one/many2one_field.xml:0
#: code:addons/web/static/src/views/kanban/kanban_renderer.js:0 #: code:addons/web/static/src/views/kanban/kanban_record_quick_create.js:0
#, python-format #, python-format
msgid "Create" msgid "Create"
msgstr "Crear" msgstr "Crear"
#. module: web
#. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0
#, python-format
msgid "Create: "
msgstr "Crear: "
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
@ -144,7 +130,7 @@ msgstr "Día"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/core/file_viewer/file_viewer.xml:0
#: code:addons/web/static/src/views/fields/binary/binary_field.xml:0 #: code:addons/web/static/src/views/fields/binary/binary_field.xml:0
#: code:addons/web/static/src/views/fields/many2many_binary/many2many_binary_field.xml:0 #: code:addons/web/static/src/views/fields/many2many_binary/many2many_binary_field.xml:0
#, python-format #, python-format
@ -153,13 +139,12 @@ msgstr "Descargar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/legacy/xml/kanban.xml:0
#: code:addons/web/static/src/views/calendar/calendar_common/calendar_common_popover.xml:0 #: code:addons/web/static/src/views/calendar/calendar_common/calendar_common_popover.xml:0
#: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0 #: code:addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml:0
#: code:addons/web/static/src/views/fields/binary/binary_field.xml:0 #: code:addons/web/static/src/views/fields/binary/binary_field.xml:0
#: code:addons/web/static/src/views/fields/image/image_field.xml:0 #: code:addons/web/static/src/views/fields/image/image_field.xml:0
#: code:addons/web/static/src/views/fields/pdf_viewer/pdf_viewer_field.xml:0 #: code:addons/web/static/src/views/fields/pdf_viewer/pdf_viewer_field.xml:0
#: code:addons/web/static/src/views/kanban/kanban_header.xml:0
#: code:addons/web/static/src/views/kanban/kanban_record_quick_create.xml:0 #: code:addons/web/static/src/views/kanban/kanban_record_quick_create.xml:0
#, python-format #, python-format
msgid "Edit" msgid "Edit"
@ -167,7 +152,6 @@ msgstr "Editar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/basic_fields.js:0
#: code:addons/web/static/src/views/fields/email/email_field.js:0 #: code:addons/web/static/src/views/fields/email/email_field.js:0
#: model:ir.model.fields,field_description:web.field_base_document_layout__email #: model:ir.model.fields,field_description:web.field_base_document_layout__email
#: model_terms:ir.ui.view,arch_db:web.login #: model_terms:ir.ui.view,arch_db:web.login
@ -185,8 +169,6 @@ msgstr "Error"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/views/list/list_controller.js:0
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#: code:addons/web/static/src/views/list/list_controller.js:0 #: code:addons/web/static/src/views/list/list_controller.js:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.xml:0
#, python-format #, python-format
@ -195,7 +177,6 @@ msgstr "Exportar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0
#, python-format #, python-format
msgid "Export Data" msgid "Export Data"
@ -203,25 +184,18 @@ msgstr "Exportar datos"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/search/favorite_menu/favorite_menu.xml:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.xml:0
#, python-format #, python-format
msgid "Favorites" msgid "Favorites"
msgstr "Favoritos" msgstr "Favoritos"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/search/filter_menu/filter_menu.xml:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.xml:0
#, python-format #, python-format
msgid "Filters" msgid "Filters"
msgstr "Filtros" msgstr "Filtros"
#. module: web
#. odoo-javascript
#: code:addons/web/static/src/legacy/js/views/form/form_view.js:0
#, python-format
msgid "Form"
msgstr "Formulario"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/views/graph/graph_view.js:0 #: code:addons/web/static/src/views/graph/graph_view.js:0
@ -231,19 +205,15 @@ msgstr "Gráfico"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/search/group_by_menu/group_by_menu.xml:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.xml:0
#: code:addons/web/static/src/views/pivot/pivot_group_by_menu.xml:0
#, python-format #, python-format
msgid "Group By" msgid "Group By"
msgstr "Agrupar por" msgstr "Agrupar por"
#. module: web
#: model:ir.model.fields,field_description:web.field_base_document_layout__id
msgid "ID"
msgstr "ID (identificación)"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/basic_fields.js:0 #: code:addons/web/static/src/core/file_viewer/file_viewer.xml:0
#: code:addons/web/static/src/views/fields/attachment_image/attachment_image_field.xml:0 #: code:addons/web/static/src/views/fields/attachment_image/attachment_image_field.xml:0
#: code:addons/web/static/src/views/fields/image/image_field.js:0 #: code:addons/web/static/src/views/fields/image/image_field.js:0
#: code:addons/web/static/src/views/fields/image_url/image_url_field.js:0 #: code:addons/web/static/src/views/fields/image_url/image_url_field.js:0
@ -259,13 +229,6 @@ msgstr "Imagen"
msgid "Languages" msgid "Languages"
msgstr "Idiomas" msgstr "Idiomas"
#. module: web
#. odoo-javascript
#: code:addons/web/static/src/legacy/js/views/list/list_view.js:0
#, python-format
msgid "List"
msgstr "Lista"
#. module: web #. module: web
#: model_terms:ir.ui.view,arch_db:web.login #: model_terms:ir.ui.view,arch_db:web.login
msgid "Log in" msgid "Log in"
@ -294,11 +257,8 @@ msgstr "Nuevo"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_bar.js:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_column.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_renderer.js:0
#: code:addons/web/static/src/search/search_bar/search_bar.js:0 #: code:addons/web/static/src/search/search_bar/search_bar.js:0
#: code:addons/web/static/src/views/kanban/kanban_renderer.js:0 #: code:addons/web/static/src/views/kanban/kanban_header.js:0
#: code:addons/web/static/src/views/list/list_renderer.js:0 #: code:addons/web/static/src/views/list/list_renderer.js:0
#: code:addons/web/static/src/views/pivot/pivot_model.js:0 #: code:addons/web/static/src/views/pivot/pivot_model.js:0
#, python-format #, python-format
@ -307,7 +267,6 @@ msgstr "No"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/views/view_button/view_button.xml:0 #: code:addons/web/static/src/views/view_button/view_button.xml:0
#, python-format #, python-format
msgid "Object:" msgid "Object:"
@ -317,15 +276,10 @@ msgstr "Objeto:"
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0 #: code:addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js:0
#: code:addons/web/static/src/core/dialog/dialog.xml:0 #: code:addons/web/static/src/core/dialog/dialog.xml:0
#: code:addons/web/static/src/core/errors/error_dialogs.xml:0
#: code:addons/web/static/src/legacy/js/core/dialog.js:0 #: code:addons/web/static/src/legacy/js/core/dialog.js:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_column.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_confirm_dialog.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/legacy/xml/control_panel.xml:0
#: code:addons/web/static/src/public/error_notifications.js:0 #: code:addons/web/static/src/public/error_notifications.js:0
#: code:addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.xml:0 #: code:addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.xml:0
#: code:addons/web/static/src/views/list/list_confirmation_dialog.xml:0
#: code:addons/web/static/src/views/view_dialogs/form_view_dialog.xml:0 #: code:addons/web/static/src/views/view_dialogs/form_view_dialog.xml:0
#: code:addons/web/static/src/webclient/actions/action_dialog.xml:0 #: code:addons/web/static/src/webclient/actions/action_dialog.xml:0
#, python-format #, python-format
@ -335,8 +289,6 @@ msgstr "Aceptar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0 #: code:addons/web/static/src/legacy/js/fields/relational_fields.js:0
#: code:addons/web/static/src/legacy/js/views/form/form_controller.js:0
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#, python-format #, python-format
msgid "Open: " msgid "Open: "
msgstr "Abrir: " msgstr "Abrir: "
@ -348,7 +300,6 @@ msgstr "Contraseña"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0
#, python-format #, python-format
msgid "Please enter save field list name" msgid "Please enter save field list name"
@ -356,14 +307,6 @@ msgstr "Por favor, introduzca el nombre de la lista de campos a guardar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#, python-format
msgid "Please select fields to export..."
msgstr "Por favor, seleccione los campos a exportar"
#. module: web
#. odoo-javascript
#: code:addons/web/static/src/legacy/js/widgets/data_export.js:0
#: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0 #: code:addons/web/static/src/views/view_dialogs/export_data_dialog.js:0
#, python-format #, python-format
msgid "Please select fields to save export list..." msgid "Please select fields to save export list..."
@ -379,8 +322,10 @@ msgstr "Preferencias"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/file_viewer/file_viewer.xml:0
#: code:addons/web/static/src/legacy/js/components/action_menus.js:0 #: code:addons/web/static/src/legacy/js/components/action_menus.js:0
#: code:addons/web/static/src/search/action_menus/action_menus.xml:0 #: code:addons/web/static/src/search/action_menus/action_menus.xml:0
#: code:addons/web/static/src/search/cog_menu/cog_menu.xml:0
#: code:addons/web/static/src/webclient/actions/reports/report_action.xml:0 #: code:addons/web/static/src/webclient/actions/reports/report_action.xml:0
#, python-format #, python-format
msgid "Print" msgid "Print"
@ -388,8 +333,6 @@ msgstr "Imprimir"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/search_bar/search_bar.xml:0 #: code:addons/web/static/src/search/search_bar/search_bar.xml:0
#: code:addons/web/static/src/views/fields/relational_utils.js:0 #: code:addons/web/static/src/views/fields/relational_utils.js:0
#: code:addons/web/static/src/views/fields/relational_utils.xml:0 #: code:addons/web/static/src/views/fields/relational_utils.xml:0
@ -400,12 +343,8 @@ msgstr "Eliminar"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/domain_selector_dialog/domain_selector_dialog.xml:0
#: code:addons/web/static/src/legacy/js/views/view_dialogs.js:0
#: code:addons/web/static/src/legacy/js/widgets/domain_selector_dialog.js:0 #: code:addons/web/static/src/legacy/js/widgets/domain_selector_dialog.js:0
#: code:addons/web/static/src/legacy/js/widgets/translation_dialog.js:0 #: code:addons/web/static/src/search/custom_favorite_item/custom_favorite_item.xml:0
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/favorite_menu/custom_favorite_item.xml:0
#: code:addons/web/static/src/views/fields/relational_utils.xml:0 #: code:addons/web/static/src/views/fields/relational_utils.xml:0
#: code:addons/web/static/src/views/fields/translation_dialog.xml:0 #: code:addons/web/static/src/views/fields/translation_dialog.xml:0
#: code:addons/web/static/src/views/form/form_controller.xml:0 #: code:addons/web/static/src/views/form/form_controller.xml:0
@ -444,12 +383,8 @@ msgstr "Sin definir"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/errors/error_dialogs.js:0 #: code:addons/web/static/src/core/errors/error_dialogs.js:0
#: code:addons/web/static/src/legacy/js/views/basic/basic_controller.js:0 #: code:addons/web/static/src/search/search_bar_menu/search_bar_menu.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_controller.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/favorite_menu/favorite_menu.js:0
#: code:addons/web/static/src/views/fields/domain/domain_field.xml:0 #: code:addons/web/static/src/views/fields/domain/domain_field.xml:0
#: code:addons/web/static/src/views/fields/translation_button.js:0
#: code:addons/web/static/src/views/list/list_controller.js:0 #: code:addons/web/static/src/views/list/list_controller.js:0
#, python-format #, python-format
msgid "Warning" msgid "Warning"
@ -461,6 +396,7 @@ msgstr "Aviso"
#: code:addons/web/static/src/search/utils/dates.js:0 #: code:addons/web/static/src/search/utils/dates.js:0
#: code:addons/web/static/src/views/calendar/calendar_common/calendar_common_renderer.js:0 #: code:addons/web/static/src/views/calendar/calendar_common/calendar_common_renderer.js:0
#: code:addons/web/static/src/views/calendar/calendar_controller.js:0 #: code:addons/web/static/src/views/calendar/calendar_controller.js:0
#: code:addons/web/static/src/views/calendar/calendar_controller.xml:0
#, python-format #, python-format
msgid "Week" msgid "Week"
msgstr "Semana" msgstr "Semana"
@ -476,13 +412,9 @@ msgstr "Año"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_bar.js:0
#: code:addons/web/static/src/legacy/js/views/kanban/kanban_column.js:0
#: code:addons/web/static/src/legacy/js/views/list/list_renderer.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/search_bar/search_bar.js:0 #: code:addons/web/static/src/search/search_bar/search_bar.js:0
#: code:addons/web/static/src/views/fields/field_tooltip.xml:0 #: code:addons/web/static/src/views/fields/field_tooltip.xml:0
#: code:addons/web/static/src/views/kanban/kanban_renderer.js:0 #: code:addons/web/static/src/views/kanban/kanban_header.js:0
#: code:addons/web/static/src/views/list/list_renderer.js:0 #: code:addons/web/static/src/views/list/list_renderer.js:0
#: code:addons/web/static/src/views/pivot/pivot_model.js:0 #: code:addons/web/static/src/views/pivot/pivot_model.js:0
#, python-format #, python-format
@ -494,7 +426,6 @@ msgstr "Sí"
#: code:addons/web/static/src/core/domain_selector/domain_selector_operators.js:0 #: code:addons/web/static/src/core/domain_selector/domain_selector_operators.js:0
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0 #: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "contains" msgid "contains"
msgstr "contiene" msgstr "contiene"
@ -502,7 +433,6 @@ msgstr "contiene"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "doesn't contain" msgid "doesn't contain"
msgstr "no contiene" msgstr "no contiene"
@ -510,19 +440,16 @@ msgstr "no contiene"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "greater than" msgid "greater than"
msgstr "mayor que" msgstr "mayor que"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/domain_selector/domain_selector_leaf_node.xml:0 #: code:addons/web/static/src/core/domain_selector/domain_selector_operators.js:0
#: code:addons/web/static/src/core/domain_selector/fields/domain_selector_boolean_field.js:0
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0 #: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "is" msgid "is"
msgstr "es" msgstr "es"
@ -530,17 +457,15 @@ msgstr "es"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "is equal to" msgid "is equal to"
msgstr "es igual a" msgstr "es igual a"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/domain_selector/fields/domain_selector_boolean_field.js:0 #: code:addons/web/static/src/core/domain_selector/domain_selector_operators.js:0
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0 #: code:addons/web/static/src/legacy/js/widgets/domain_selector.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "is not" msgid "is not"
msgstr "no es" msgstr "no es"
@ -548,7 +473,6 @@ msgstr "no es"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "is not equal to" msgid "is not equal to"
msgstr "es distinto de" msgstr "es distinto de"
@ -556,17 +480,14 @@ msgstr "es distinto de"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0 #: code:addons/web/static/src/legacy/js/control_panel/search_utils.js:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.js:0
#, python-format #, python-format
msgid "less than" msgid "less than"
msgstr "menor que" msgstr "menor que"
#. module: web #. module: web
#. odoo-javascript #. odoo-javascript
#: code:addons/web/static/src/core/domain_selector/domain_selector_leaf_node.xml:0 #: code:addons/web/static/src/core/domain_selector/utils.js:0
#: code:addons/web/static/src/legacy/js/views/action_model.js:0
#: code:addons/web/static/src/legacy/xml/base.xml:0 #: code:addons/web/static/src/legacy/xml/base.xml:0
#: code:addons/web/static/src/search/filter_menu/custom_filter_item.xml:0
#: code:addons/web/static/src/search/search_model.js:0 #: code:addons/web/static/src/search/search_model.js:0
#, python-format #, python-format
msgid "or" msgid "or"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -7,3 +7,6 @@ from . import ir_model
from . import ir_ui_menu from . import ir_ui_menu
from . import models from . import models
from . import base_document_layout from . import base_document_layout
from . import res_config_settings
from . import res_partner
from . import res_users

View file

@ -2,12 +2,13 @@
import markupsafe import markupsafe
import os import os
from markupsafe import Markup from markupsafe import Markup
from math import ceil
from odoo import api, fields, models, tools from odoo import api, fields, models, tools
from odoo.addons.base.models.ir_qweb_fields import nl2br from odoo.addons.base.models.ir_qweb_fields import nl2br
from odoo.modules import get_resource_path from odoo.tools import html2plaintext, is_html_empty
from odoo.tools import file_path, html2plaintext, is_html_empty from odoo.tools.misc import file_path
try: try:
import sass as libsass import sass as libsass
@ -217,7 +218,7 @@ class BaseDocumentLayout(models.TransientModel):
return False, False return False, False
base_w, base_h = image.size base_w, base_h = image.size
w = int(50 * base_w / base_h) w = ceil(50 * base_w / base_h)
h = 50 h = 50
# Converts to RGBA (if already RGBA, this is a noop) # Converts to RGBA (if already RGBA, this is a noop)
@ -251,14 +252,6 @@ class BaseDocumentLayout(models.TransientModel):
return tools.rgb_to_hex(primary), tools.rgb_to_hex(secondary) return tools.rgb_to_hex(primary), tools.rgb_to_hex(secondary)
@api.model
def action_open_base_document_layout(self, action_ref=None):
if not action_ref:
action_ref = 'web.action_base_document_layout_configurator'
res = self.env["ir.actions.actions"]._for_xml_id(action_ref)
self.env[res["res_model"]].check_access_rights('write')
return res
def document_layout_save(self): def document_layout_save(self):
# meant to be overridden # meant to be overridden
return self.env.context.get('report_action') or {'type': 'ir.actions.act_window_close'} return self.env.context.get('report_action') or {'type': 'ir.actions.act_window_close'}
@ -306,7 +299,7 @@ class BaseDocumentLayout(models.TransientModel):
precision = 8 precision = 8
output_style = 'expanded' output_style = 'expanded'
bootstrap_path = get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss') bootstrap_path = file_path('web/static/lib/bootstrap/scss')
try: try:
return libsass.compile( return libsass.compile(

View file

@ -2,17 +2,14 @@
import hashlib import hashlib
import json import json
import logging
import odoo import odoo
from odoo import api, http, models from odoo import api, models
from odoo.http import request from odoo.http import request, DEFAULT_MAX_CONTENT_LENGTH
from odoo.tools import file_open, image_process, ustr from odoo.tools import ormcache, ustr
from odoo.tools.misc import str2bool from odoo.tools.misc import str2bool
_logger = logging.getLogger(__name__)
""" """
Debug mode is stored in session and should always be a string. Debug mode is stored in session and should always be a string.
It can be activated with an URL query string `debug=<mode>` where mode It can be activated with an URL query string `debug=<mode>` where mode
@ -58,6 +55,11 @@ class Http(models.AbstractModel):
super()._pre_dispatch(rule, args) super()._pre_dispatch(rule, args)
cls._handle_debug() cls._handle_debug()
@classmethod
def _post_logout(cls):
super()._post_logout()
request.future_response.set_cookie('cids', max_age=0)
def webclient_rendering_context(self): def webclient_rendering_context(self):
return { return {
'menu_data': request.env['ir.ui.menu'].load_menus(request.session.debug), 'menu_data': request.env['ir.ui.menu'].load_menus(request.session.debug),
@ -79,24 +81,27 @@ class Http(models.AbstractModel):
IrConfigSudo = self.env['ir.config_parameter'].sudo() IrConfigSudo = self.env['ir.config_parameter'].sudo()
max_file_upload_size = int(IrConfigSudo.get_param( max_file_upload_size = int(IrConfigSudo.get_param(
'web.max_file_upload_size', 'web.max_file_upload_size',
default=128 * 1024 * 1024, # 128MiB default=DEFAULT_MAX_CONTENT_LENGTH,
)) ))
mods = odoo.conf.server_wide_modules or [] mods = odoo.conf.server_wide_modules or []
if request.db: if request.db:
mods = list(request.registry._init_modules) + mods mods = list(request.registry._init_modules) + mods
is_internal_user = user.has_group('base.group_user')
session_info = { session_info = {
"uid": session_uid, "uid": session_uid,
"is_system": user._is_system() if session_uid else False, "is_system": user._is_system() if session_uid else False,
"is_admin": user._is_admin() if session_uid else False, "is_admin": user._is_admin() if session_uid else False,
"is_public": user._is_public(),
"is_internal_user": is_internal_user,
"user_context": user_context, "user_context": user_context,
"db": self.env.cr.dbname, "db": self.env.cr.dbname,
"user_settings": self.env['res.users.settings']._find_or_create_for_user(user)._res_users_settings_format(),
"server_version": version_info.get('server_version'), "server_version": version_info.get('server_version'),
"server_version_info": version_info.get('server_version_info'), "server_version_info": version_info.get('server_version_info'),
"support_url": "https://www.odoo.com/buy", "support_url": "https://www.odoo.com/buy",
"name": user.name, "name": user.name,
"username": user.login, "username": user.login,
"partner_display_name": user.partner_id.display_name, "partner_display_name": user.partner_id.display_name,
"company_id": user.company_id.id if session_uid else None, # YTI TODO: Remove this from the user context
"partner_id": user.partner_id.id if session_uid and user.partner_id else None, "partner_id": user.partner_id.id if session_uid and user.partner_id else None,
"web.base.url": IrConfigSudo.get_param('web.base.url', default=''), "web.base.url": IrConfigSudo.get_param('web.base.url', default=''),
"active_ids_limit": int(IrConfigSudo.get_param('web.active_ids_limit', default='20000')), "active_ids_limit": int(IrConfigSudo.get_param('web.active_ids_limit', default='20000')),
@ -117,7 +122,7 @@ class Http(models.AbstractModel):
} }
if request.session.debug: if request.session.debug:
session_info['bundle_params']['debug'] = request.session.debug session_info['bundle_params']['debug'] = request.session.debug
if self.env.user.has_group('base.group_user'): if is_internal_user:
# the following is only useful in the context of a webclient bootstrapping # the following is only useful in the context of a webclient bootstrapping
# but is still included in some other calls (e.g. '/web/session/authenticate') # but is still included in some other calls (e.g. '/web/session/authenticate')
# to avoid access errors and unnecessary information, it is only included for users # to avoid access errors and unnecessary information, it is only included for users
@ -128,6 +133,9 @@ class Http(models.AbstractModel):
session_info['cache_hashes'].update({ session_info['cache_hashes'].update({
"load_menus": hashlib.sha512(menu_json_utf8).hexdigest()[:64], # sha512/256 "load_menus": hashlib.sha512(menu_json_utf8).hexdigest()[:64], # sha512/256
}) })
# We need sudo since a user may not have access to ancestor companies
disallowed_ancestor_companies_sudo = user.company_ids.sudo().parent_ids - user.company_ids
all_companies_in_hierarchy_sudo = disallowed_ancestor_companies_sudo + user.company_ids
session_info.update({ session_info.update({
# current_company should be default_company # current_company should be default_company
"user_companies": { "user_companies": {
@ -137,8 +145,19 @@ class Http(models.AbstractModel):
'id': comp.id, 'id': comp.id,
'name': comp.name, 'name': comp.name,
'sequence': comp.sequence, 'sequence': comp.sequence,
'child_ids': (comp.child_ids & all_companies_in_hierarchy_sudo).ids,
'parent_id': comp.parent_id.id,
} for comp in user.company_ids } for comp in user.company_ids
}, },
'disallowed_ancestor_companies': {
comp.id: {
'id': comp.id,
'name': comp.name,
'sequence': comp.sequence,
'child_ids': (comp.child_ids & all_companies_in_hierarchy_sudo).ids,
'parent_id': comp.parent_id.id,
} for comp in disallowed_ancestor_companies_sudo
},
}, },
"show_effect": True, "show_effect": True,
"display_switch_company_menu": user.has_group('base.group_multi_company') and len(user.company_ids) > 1, "display_switch_company_menu": user.has_group('base.group_multi_company') and len(user.company_ids) > 1,
@ -152,6 +171,7 @@ class Http(models.AbstractModel):
session_info = { session_info = {
'is_admin': user._is_admin() if session_uid else False, 'is_admin': user._is_admin() if session_uid else False,
'is_system': user._is_system() if session_uid else False, 'is_system': user._is_system() if session_uid else False,
'is_public': user._is_public(),
'is_website_user': user._is_public() if session_uid else False, 'is_website_user': user._is_public() if session_uid else False,
'user_id': user.id if session_uid else False, 'user_id': user.id if session_uid else False,
'is_frontend': True, 'is_frontend': True,
@ -159,6 +179,7 @@ class Http(models.AbstractModel):
'profile_collectors': request.session.profile_collectors, 'profile_collectors': request.session.profile_collectors,
'profile_params': request.session.profile_params, 'profile_params': request.session.profile_params,
'show_effect': bool(request.env['ir.config_parameter'].sudo().get_param('base_setup.show_effect')), 'show_effect': bool(request.env['ir.config_parameter'].sudo().get_param('base_setup.show_effect')),
'currencies': self.get_currencies(),
'bundle_params': { 'bundle_params': {
'lang': request.session.context['lang'], 'lang': request.session.context['lang'],
}, },
@ -173,7 +194,11 @@ class Http(models.AbstractModel):
}) })
return session_info return session_info
@ormcache()
def get_currencies(self): def get_currencies(self):
Currency = self.env['res.currency'] Currency = self.env['res.currency']
currencies = Currency.search([]).read(['symbol', 'position', 'decimal_places']) currencies = Currency.search_fetch([], ['symbol', 'position', 'decimal_places'])
return {c['id']: {'symbol': c['symbol'], 'position': c['position'], 'digits': [69,c['decimal_places']]} for c in currencies} return {
c.id: {'symbol': c.symbol, 'position': c.position, 'digits': [69, c.decimal_places]}
for c in currencies
}

View file

@ -19,7 +19,7 @@ class IrModel(models.Model):
accessible_models = [] accessible_models = []
not_accessible_models = [] not_accessible_models = []
for model in models: for model in models:
if self._check_model_access(model): if self._is_valid_for_model_selector(model):
accessible_models.append(model) accessible_models.append(model)
else: else:
not_accessible_models.append({"display_name": model, "model": model}) not_accessible_models.append({"display_name": model, "model": model})
@ -34,9 +34,15 @@ class IrModel(models.Model):
} for model in records] } for model in records]
@api.model @api.model
def _check_model_access(self, model): def _is_valid_for_model_selector(self, model):
return (self.env.user._is_internal() and model in self.env model = self.env.get(model)
and self.env[model].check_access_rights("read", raise_exception=False)) return (
self.env.user._is_internal()
and model is not None
and model.check_access_rights("read", raise_exception=False)
and not model._transient
and not model._abstract
)
@api.model @api.model
def get_available_models(self): def get_available_models(self):
@ -44,5 +50,5 @@ class IrModel(models.Model):
Return the list of models the current user has access to, with their Return the list of models the current user has access to, with their
corresponding display name. corresponding display name.
""" """
accessible_models = [model for model in self.pool.keys() if self._check_model_access(model)] accessible_models = [model for model in self.pool if self._is_valid_for_model_selector(model)]
return self._display_name_for(accessible_models) return self._display_name_for(accessible_models)

View file

@ -6,7 +6,7 @@ from collections import OrderedDict
from werkzeug.urls import url_quote from werkzeug.urls import url_quote
from markupsafe import Markup from markupsafe import Markup
from odoo import api, models from odoo import api, models, fields
from odoo.tools import pycompat from odoo.tools import pycompat
from odoo.tools import html_escape as escape from odoo.tools import html_escape as escape
@ -36,7 +36,7 @@ class Image(models.AbstractModel):
if max_width or max_height: if max_width or max_height:
max_size = '%sx%s' % (max_width, max_height) max_size = '%sx%s' % (max_width, max_height)
sha = hashlib.sha512(str(getattr(record, '__last_update')).encode('utf-8')).hexdigest()[:7] sha = hashlib.sha512(str(getattr(record, 'write_date', fields.Datetime.now())).encode('utf-8')).hexdigest()[:7]
max_size = '' if max_size is None else '/%s' % max_size max_size = '' if max_size is None else '/%s' % max_size
if options.get('filename-field') and options['filename-field'] in record and record[options['filename-field']]: if options.get('filename-field') and options['filename-field'] in record and record[options['filename-field']]:

View file

@ -32,6 +32,7 @@ class IrUiMenu(models.Model):
"actionModel": False, "actionModel": False,
"webIcon": None, "webIcon": None,
"webIconData": None, "webIconData": None,
"webIconDataMimetype": None,
"backgroundImage": menu.get('backgroundImage'), "backgroundImage": menu.get('backgroundImage'),
} }
else: else:
@ -57,6 +58,7 @@ class IrUiMenu(models.Model):
"actionModel": action_model, "actionModel": action_model,
"webIcon": menu['web_icon'], "webIcon": menu['web_icon'],
"webIconData": menu['web_icon_data'], "webIconData": menu['web_icon_data'],
"webIconDataMimetype": menu['web_icon_data_mimetype'],
} }
return web_menus return web_menus

Some files were not shown because too many files have changed in this diff Show more