From 2d8e8d200188ffbc0cf1028f377f124824deb7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A0n=20Todorovich?= Date: Mon, 27 Feb 2023 12:27:37 -0300 Subject: [PATCH] [MIG] web_chatter_position: Migration to 16.0 --- .../odoo/addons/web_chatter_position | 1 + setup/web_chatter_position/setup.py | 6 + web_chatter_position/__manifest__.py | 12 +- web_chatter_position/models/res_users.py | 10 +- web_chatter_position/readme/CONTRIBUTORS.rst | 3 + web_chatter_position/readme/DESCRIPTION.rst | 5 +- web_chatter_position/readme/ROADMAP.rst | 1 - web_chatter_position/readme/USAGE.rst | 4 +- .../static/src/js/form_chatter_position.js | 48 --- .../static/src/js/web_chatter_position.esm.js | 158 ++++++++ .../static/src/scss/attachment_viewer.scss | 52 --- .../static/src/scss/chatter_position.scss | 338 ------------------ .../static/src/xml/form_buttons.xml | 15 - web_chatter_position/views/res_users.xml | 9 +- web_chatter_position/views/web.xml | 22 +- 15 files changed, 191 insertions(+), 493 deletions(-) create mode 120000 setup/web_chatter_position/odoo/addons/web_chatter_position create mode 100644 setup/web_chatter_position/setup.py delete mode 100644 web_chatter_position/readme/ROADMAP.rst delete mode 100644 web_chatter_position/static/src/js/form_chatter_position.js create mode 100644 web_chatter_position/static/src/js/web_chatter_position.esm.js delete mode 100644 web_chatter_position/static/src/scss/attachment_viewer.scss delete mode 100644 web_chatter_position/static/src/scss/chatter_position.scss delete mode 100644 web_chatter_position/static/src/xml/form_buttons.xml diff --git a/setup/web_chatter_position/odoo/addons/web_chatter_position b/setup/web_chatter_position/odoo/addons/web_chatter_position new file mode 120000 index 000000000..e34df916d --- /dev/null +++ b/setup/web_chatter_position/odoo/addons/web_chatter_position @@ -0,0 +1 @@ +../../../../web_chatter_position \ No newline at end of file diff --git a/setup/web_chatter_position/setup.py b/setup/web_chatter_position/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/web_chatter_position/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/web_chatter_position/__manifest__.py b/web_chatter_position/__manifest__.py index 685935692..2fbc833b0 100644 --- a/web_chatter_position/__manifest__.py +++ b/web_chatter_position/__manifest__.py @@ -4,24 +4,16 @@ { "name": "Chatter Position", "summary": "Add an option to change the chatter position", - "version": "15.0.1.0.0", + "version": "16.0.1.0.0", "author": "Hynsys Technologies, Camptocamp, Odoo Community Association (OCA)", "website": "https://github.com/OCA/web", "license": "LGPL-3", "category": "Extra Tools", - "images": ["static/description/images/web_chatter_position.png"], "depends": ["web", "mail"], "data": ["views/res_users.xml", "views/web.xml"], "assets": { "web.assets_backend": [ - "/web_chatter_position/static/src/scss/chatter_position.scss", - "/web_chatter_position/static/src/scss/attachment_viewer.scss", - "/web_chatter_position/static/src/js/form_chatter_position.js", - ], - "web.assets_qweb": [ - "/web_chatter_position/static/src/xml/form_buttons.xml", + "/web_chatter_position/static/src/**/*.js", ], }, - "installable": True, - "auto_install": False, } diff --git a/web_chatter_position/models/res_users.py b/web_chatter_position/models/res_users.py index 20f5492e4..3cfb7b7ac 100644 --- a/web_chatter_position/models/res_users.py +++ b/web_chatter_position/models/res_users.py @@ -8,12 +8,14 @@ class ResUsers(models.Model): _inherit = "res.users" chatter_position = fields.Selection( - [("bottom", "Bottom"), ("sided", "Sided")], - default="sided", + [ + ("auto", "Responsive"), + ("bottom", "Bottom"), + ("sided", "Sided"), + ], + default="auto", ) - # Override so that the user can change the chatter_position field - @property def SELF_READABLE_FIELDS(self): return super().SELF_READABLE_FIELDS + ["chatter_position"] diff --git a/web_chatter_position/readme/CONTRIBUTORS.rst b/web_chatter_position/readme/CONTRIBUTORS.rst index dbc15218d..e0a264ebb 100644 --- a/web_chatter_position/readme/CONTRIBUTORS.rst +++ b/web_chatter_position/readme/CONTRIBUTORS.rst @@ -1,2 +1,5 @@ * Hynsys Technologies * Juan Miguel Sánchez Arce +* `Camptocamp `_ + + * Iván Todorovich diff --git a/web_chatter_position/readme/DESCRIPTION.rst b/web_chatter_position/readme/DESCRIPTION.rst index 5c803862a..9c874e16e 100644 --- a/web_chatter_position/readme/DESCRIPTION.rst +++ b/web_chatter_position/readme/DESCRIPTION.rst @@ -1,4 +1,3 @@ -Configurable Chatter Position. -Change Chatter Position in User Preferences. -Change Chatter Position on the fly. +Configurable chatter position from the user preferences. + Supports Both Community & Enterprise Edition. diff --git a/web_chatter_position/readme/ROADMAP.rst b/web_chatter_position/readme/ROADMAP.rst deleted file mode 100644 index c3d019c98..000000000 --- a/web_chatter_position/readme/ROADMAP.rst +++ /dev/null @@ -1 +0,0 @@ -* This module implements the same feature as **web_responsive**. Once the enterprise interface is moved to community in version 16, only this module will be needed. diff --git a/web_chatter_position/readme/USAGE.rst b/web_chatter_position/readme/USAGE.rst index 605b46026..dd8265496 100644 --- a/web_chatter_position/readme/USAGE.rst +++ b/web_chatter_position/readme/USAGE.rst @@ -1,2 +1,2 @@ -#. There's a **Chatter Position** option in **User Preferences**, where you can choose between "bottom" and "sided". -#. The position can also be changed on the fly using a new button on the top left side of Form Views. +#. There's a **Chatter Position** option in **User Preferences**, where you can +choose between ``auto``, ``bottom`` and ``sided``. diff --git a/web_chatter_position/static/src/js/form_chatter_position.js b/web_chatter_position/static/src/js/form_chatter_position.js deleted file mode 100644 index dbcb119f8..000000000 --- a/web_chatter_position/static/src/js/form_chatter_position.js +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2022 Hynsys Technologies -// License LGPL - 3.0 or later(http://www.gnu.org/licenses/lgpl). - -odoo.define("web_chatter_position.ChatterPositionFormController", function (require) { - "use strict"; - - var config = require("web.config"); - var FormController = require("web.FormController"); - var FormRenderer = require("web.FormRenderer"); - - var ChatterPositionFormController = FormController.include({ - renderButtons: function () { - this._super.apply(this, arguments); - if (this.$buttons) { - this.$buttons.on( - "click", - ".o_chatter_position_button", - this._onChatterPosition.bind(this) - ); - } - }, - - _onChatterPosition: function () { - if (this.$el.offsetParent().hasClass("o_chatter_position_bottom")) { - this.$el - .offsetParent() - .attr("class", "o_web_client o_chatter_position_sided"); - } else if (this.$el.offsetParent().hasClass("o_chatter_position_sided")) { - this.$el - .offsetParent() - .attr("class", "o_web_client o_chatter_position_bottom"); - } - }, - }); - - FormRenderer.include({ - _applyFormSizeClass: function () { - const formEl = this.$el[0]; - if (config.device.size_class <= config.device.SIZES.XS) { - formEl.classList.add("o_xxs_form_view"); - } else { - formEl.classList.remove("o_xxs_form_view"); - } - }, - }); - - return ChatterPositionFormController; -}); diff --git a/web_chatter_position/static/src/js/web_chatter_position.esm.js b/web_chatter_position/static/src/js/web_chatter_position.esm.js new file mode 100644 index 000000000..3c648ce0f --- /dev/null +++ b/web_chatter_position/static/src/js/web_chatter_position.esm.js @@ -0,0 +1,158 @@ +/** @odoo-module **/ +/* + Copyright 2023 Camptocamp SA (https://www.camptocamp.com). + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +*/ + +import {FormCompiler} from "@web/views/form/form_compiler"; +import {FormController} from "@web/views/form/form_controller"; +import {MailFormCompiler} from "@mail/views/form/form_compiler"; +import {append} from "@web/core/utils/xml"; +import {patch} from "@web/core/utils/patch"; + +/** + * So, you've landed here and you have no idea what this is about. Don't worry, you're + * not the only one. Here's a quick summary of what's going on: + * + * In core, the chatter position depends on the size of the screen and wether there is + * an attachment viewer or not. There are 3 possible positions, and for each position a + * different chatter instance is displayed. + * + * So, in fact, we have 3 chatter instances running, and we switch their visibility + * depending on the desired position. + * + * A) Bottom position + * https://github.com/odoo/odoo/blob/2ef010907/addons/mail/static/src/views/form/form_compiler.js#L160 + * Condition: `!this.props.hasAttachmentViewer and uiService.size < ${SIZES.XXL}` + * + * This is the bottom position you would except. However it can only be there until + * XXL screen sizes, because the container is a flexbox and changes from row to + * column display. It's hidden in the presence of an attachment viewer. + * + * B) Bottom In-sheet position + * https://github.com/odoo/odoo/blob/2ef010907/addons/mail/static/src/views/form/form_compiler.js#L181 + * Condition: `this.props.hasAttachmentViewer` + * + * This is the bottom position that's used when there's an attachment viewer in place. + * It's rendered within the form sheet, possibly to by-pass the flexbox issue + * beforementioned. It's only instanciated when there's an attachment viewer. + * + * C) Sided position + * https://github.com/odoo/odoo/blob/2ef010907/addons/mail/static/src/views/form/form_compiler.js#L83 + * Condition: `!hasAttachmentViewer() and uiService.size >= ${SIZES.XXL}` + * + * This is the sided position, hidden in the presence of an attachment viewer. + * It's the better half of `A`. + * + * The patches and overrides you see below are here to alter these conditions to force + * a specific position regardless of the screen size, depending on an user setting. + */ + +patch(MailFormCompiler.prototype, "web_chatter_position", { + /** + * Patch the visibility of the Sided chatter (`C` above). + * + * @override + */ + compile() { + const res = this._super.apply(this, arguments); + const chatterContainerHookXml = res.querySelector( + ".o_FormRenderer_chatterContainer" + ); + if (!chatterContainerHookXml) { + return res; + } + // Don't patch anything if the setting is "auto": this is the core behaviour + if (odoo.web_chatter_position === "auto") { + return res; + } else if (odoo.web_chatter_position === "sided") { + chatterContainerHookXml.setAttribute("t-if", "!hasAttachmentViewer()"); + } else if (odoo.web_chatter_position === "bottom") { + chatterContainerHookXml.setAttribute("t-if", false); + } + return res; + }, +}); + +patch(FormCompiler.prototype, "web_chatter_position", { + /** + * Patch the css classes of the `Form`, to include an extra `h-100` class. + * Without it, the form sheet will not be full height in some situations, + * looking a bit weird. + * + * @override + */ + compileForm() { + const res = this._super.apply(this, arguments); + if (odoo.web_chatter_position === "sided") { + const classes = res.getAttribute("t-attf-class"); + res.setAttribute("t-attf-class", `${classes} h-100`); + } + return res; + }, + /** + * Patch the visibility of bottom chatters (`A` and `B` above). + * `B` may not exist in some situations, so we ensure it does by creating it. + * + * @override + */ + compile(node, params) { + const res = this._super.apply(this, arguments); + const chatterContainerHookXml = res.querySelector( + ".o_FormRenderer_chatterContainer:not(.o-isInFormSheetBg)" + ); + if (!chatterContainerHookXml) { + return res; + } + if (chatterContainerHookXml.parentNode.classList.contains("o_form_sheet")) { + return res; + } + // Don't patch anything if the setting is "auto": this is the core behaviour + if (odoo.web_chatter_position === "auto") { + return res; + // For "sided", we have to remote the bottom chatter + // (except if there is an attachment viewer, as we have to force bottom) + } else if (odoo.web_chatter_position === "sided") { + chatterContainerHookXml.setAttribute("t-if", false); + // For "bottom", we keep the chatter in the form sheet + // (the one used for the attachment viewer case) + // If it's not there, we create it. + } else if (odoo.web_chatter_position === "bottom") { + if (params.hasAttachmentViewerInArch) { + const sheetBgChatterContainerHookXml = res.querySelector( + ".o_FormRenderer_chatterContainer.o-isInFormSheetBg" + ); + sheetBgChatterContainerHookXml.setAttribute("t-if", true); + chatterContainerHookXml.setAttribute("t-if", false); + } else { + const formSheetBgXml = res.querySelector(".o_form_sheet_bg"); + const sheetBgChatterContainerHookXml = + chatterContainerHookXml.cloneNode(true); + sheetBgChatterContainerHookXml.classList.add("o-isInFormSheetBg"); + sheetBgChatterContainerHookXml.setAttribute("t-if", true); + append(formSheetBgXml, sheetBgChatterContainerHookXml); + const sheetBgChatterContainerXml = + sheetBgChatterContainerHookXml.querySelector("ChatterContainer"); + sheetBgChatterContainerXml.setAttribute("isInFormSheetBg", "true"); + chatterContainerHookXml.setAttribute("t-if", false); + } + } + return res; + }, +}); + +patch(FormController.prototype, "web_chatter_position", { + /** + * Patch the css classes of the form container, to include an extra `flex-row` class. + * Without it, it'd go for flex columns direction and it won't look good. + * + * @override + */ + get className() { + const result = this._super(); + if (odoo.web_chatter_position === "sided") { + result["flex-row"] = true; + } + return result; + }, +}); diff --git a/web_chatter_position/static/src/scss/attachment_viewer.scss b/web_chatter_position/static/src/scss/attachment_viewer.scss deleted file mode 100644 index 874191c66..000000000 --- a/web_chatter_position/static/src/scss/attachment_viewer.scss +++ /dev/null @@ -1,52 +0,0 @@ -// Attachment Viewer -.o_web_client.o_chatter_position_sided .o_DialogManager_dialog { - /* Show sided viewer on large screens */ - @include media-breakpoint-up(lg) { - position: static; - .o_AttachmentViewer_main { - padding-bottom: 20px; - } - .o_AttachmentViewer { - // On-top of navbar - z-index: 10; - position: absolute; - right: 0; - top: 0; - bottom: 0; - margin-left: auto; - background-color: rgba(0, 0, 0, 0.7); - - width: $chatter_zone_width; - &.o_AttachmentViewer_maximized { - width: 100%; - } - - /* Show/Hide control buttons (next, prev, etc..) */ - &:hover .o_AttachmentViewer_buttonNavigation, - &:hover .o_AttachmentViewer_toolbar { - display: flex; - } - .o_AttachmentViewer_buttonNavigation, - .o_AttachmentViewer_toolbar { - display: none; - } - .o_AttachmentViewer_viewIframe { - width: 95%; - } - } - } - @include media-breakpoint-down(md) { - .o_AttachmentViewer_headerItemButtonMinimize, - .o_AttachmentViewer_headerItemButtonMaximize { - display: none; - } - } -} - -/* Attachment Viewer Max/Min buttons only are useful in sided mode */ -.o_web_client:not(.o_chatter_position_sided) { - .o_AttachmentViewer_headerItemButtonMinimize, - .o_AttachmentViewer_headerItemButtonMaximize { - display: none; - } -} diff --git a/web_chatter_position/static/src/scss/chatter_position.scss b/web_chatter_position/static/src/scss/chatter_position.scss deleted file mode 100644 index dd64c0cb4..000000000 --- a/web_chatter_position/static/src/scss/chatter_position.scss +++ /dev/null @@ -1,338 +0,0 @@ -$chatter_zone_width: 35%; - -// Size of labels -.o_web_client { - &.o_chatter_position_sided { - .o_action_manager { - .o_content, - .modal-content { - @include media-breakpoint-up(xl, $o-extra-grid-breakpoints) { - .o_inner_group { - .o_td_label { - min-width: 260px !important; - } - } - } - @include media-breakpoint-between(lg, xl, $o-extra-grid-breakpoints) { - .o_group_col_6 { - width: 100% !important; - } - } - } - } - } - &:not(.o_chatter_position_sided) { - @include media-breakpoint-up(lg, $o-extra-grid-breakpoints) { - .o_action_manager { - .o_content, - .modal-content { - .o_inner_group { - .o_td_label { - min-width: 260px !important; - } - } - } - } - } - } -} - -// Normal views -.o_content, -.modal-content { - max-width: 100%; - - // Form views - .o_form_view { - .o_form_sheet { - max-width: calc(100% - 32px); - overflow-x: auto; - } - - .o_td_label .o_form_label:not(.o_status):not(.o_calendar_invitation) { - min-height: 23px; - @include media-breakpoint-up(md) { - margin-bottom: 10px; - } - } - .o_horizontal_separator { - font-size: 14px; - } - // Some UX improvements for form in edit mode - @include media-breakpoint-down(sm) { - .o_field_widget { - vertical-align: middle; - } - &.o_form_editable .o_field_widget { - &:not(.o_stat_info):not(.o_readonly_modifier):not(.oe_form_field_html):not(.o_field_image) { - min-height: 35px; - } - .o_x2m_control_panel { - margin-bottom: 10px; - } - &.o_field_float_percentage, - &.o_field_monetary, - &.o_field_many2manytags, - .o_field_many2one_selection { - align-items: center; - } - .o_field_many2one_selection .o_input_dropdown, - &.o_datepicker, - &.o_field_partner_autocomplete { - input { - min-height: 35px; - } - } - .o_external_button { - margin-left: 10px; - } - .o_dropdown_button, - .o_datepicker_button { - top: 8px; - right: 6px; - bottom: auto; - } - } - } - - .o_FormRenderer_chatterContainer { - padding-top: 0; - .o_Activity_info { - flex-wrap: wrap; - } - .o_ActivityBox_title { - margin-bottom: 0; - } - .o_MessageList_separatorDate { - padding-bottom: 0; - } - } - // Sided chatter scrolling behavior - .o_Chatter { - height: fit-content; - .o_Chatter_fixedPanel { - position: sticky; - top: 0; - z-index: 1; - background-color: white; - padding-bottom: 10px; - } - .o_Chatter_scrollPanel { - overflow: initial; - } - } - - // Sticky statusbar - .o_form_statusbar { - position: sticky; - top: 0; - z-index: 2; - } - - // Support for long title (with ellipsis) - .oe_title { - span.o_field_widget:not(.oe_inline) { - max-width: 100%; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - width: initial; - &:active { - white-space: normal; - } - } - } - - @include media-breakpoint-down(sm) { - min-width: auto; - - // More buttons border - .oe_button_box { - .o_dropdown_more { - button:last-child { - border-right: 1px solid gray("400"); - } - } - } - - // Avoid overflow on forms with title and/or button box - .oe_title { - max-width: 100%; - } - - .oe_button_box + .oe_title, - .oe_button_box + .oe_avatar + .oe_title { - width: 100%; - } - - // Avoid overflow on modals - .o_form_sheet { - min-width: auto; - } - - // Render website inputs properly in phones - .o_group .o_field_widget.o_text_overflow { - // Overrides another !important - width: auto !important; - } - - // Make all input groups vertical - .o_group_col_6, - .o_group_col_8 { - width: 100%; - } - - // Statusbar buttons dropdown for mobiles - .o_statusbar_buttons_dropdown { - border: { - bottom: 0; - radius: 0; - top: 0; - } - height: 100%; - } - .o_statusbar_buttons.dropdown-menu { - .btn { - border-radius: 0; - border: 0; - width: 100%; - margin-bottom: 0.2rem; - white-space: nowrap; - @include media-breakpoint-down(xs) { - max-width: 80vw; - overflow: hidden; - text-overflow: ellipsis; - } - - &:last-child { - margin-bottom: 0; - } - } - } - - .o_statusbar_status { - // Arrow from rightmost button exceeds allowed width - .o_arrow_button:first-child::before { - content: none; - display: none; - } - } - - // Full width in form sheets - .o_form_sheet, - .o_FormRenderer_chatterContainer { - min-width: auto; - max-width: 98%; - } - - // Settings pages - .app_settings_block { - .row { - margin: 0; - } - } - - .o_FormRenderer_chatterContainer { - padding-top: initial; - - // Display send button on small screens - .o_Chatter_composer { - &.o-has-current-partner-avatar { - grid-template-columns: 0px 1fr; - padding: 1rem 1rem 1.5rem 1rem; - } - - .o_Composer_sidebarMain { - display: none; - } - } - } - } - } - - //No content message improvements on mobile - @include media-breakpoint-down(md) { - .o_view_nocontent { - top: 80px; - } - .o_nocontent_help { - box-shadow: none; - } - .o_sample_data_disabled { - display: none; - } - } - - // Sided chatter, if user wants - .o_chatter_position_sided & { - @include media-breakpoint-up(lg) { - .o_form_view:not(.o_form_nosheet) { - display: flex; - flex-flow: row nowrap; - height: 100%; - - .o_form_sheet_bg { - flex: 1 1 auto; - overflow: auto; - - > .o_form_sheet { - min-width: unset; - } - } - - .o_FormRenderer_chatterContainer { - border-left: 1px solid gray("400"); - flex: 0 0 $chatter_zone_width; - max-width: initial; - min-width: initial; - overflow: auto; - - .o_chatter_header_container { - padding-top: $grid-gutter-width * 0.5; - top: 0; - position: sticky; - background-color: $o-view-background-color; - z-index: 1; - - // Scrollable input text to avoid hide conversation & buttons - .o_composer_text_field { - max-height: 120px; - overflow-y: auto !important; /* Forced because Odoo uses inline style */ - } - .o_attachments_list { - overflow: auto; - max-height: $o-mail-attachment-image-size * 3; - margin-top: 0.4em; - } - .o_attachments_previews { - overflow: auto; - max-height: $o-mail-attachment-image-size * 6; - } - } - } - } - } - } -} -.o_FormRenderer_chatterContainer { - &.o-aside { - border-left: $border-width 0; - padding: map-get($spacers, 0); - width: $o-form-view-sheet-max-width !important; - - .o_Message.o-not-discussion { - border-width: $border-width 0; - } - } - - &.o-isInFormSheetBg:not(.o-aside) { - max-width: $o-form-view-sheet-max-width; - background-color: $white; - @include o-form-sheet-negative-margin; - - &:not(.o-aside) { - width: auto; - border-top: 1px solid $border-color; - } - } -} diff --git a/web_chatter_position/static/src/xml/form_buttons.xml b/web_chatter_position/static/src/xml/form_buttons.xml deleted file mode 100644 index 07c534f52..000000000 --- a/web_chatter_position/static/src/xml/form_buttons.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/web_chatter_position/views/res_users.xml b/web_chatter_position/views/res_users.xml index 5bc49e1a9..0cf19ea22 100644 --- a/web_chatter_position/views/res_users.xml +++ b/web_chatter_position/views/res_users.xml @@ -1,13 +1,12 @@ - - view.users.form.simple.modif.chatter.position + res.users - - - + + + diff --git a/web_chatter_position/views/web.xml b/web_chatter_position/views/web.xml index 73f9ba71a..b65b4e1e8 100644 --- a/web_chatter_position/views/web.xml +++ b/web_chatter_position/views/web.xml @@ -1,20 +1,12 @@ -