Merge PR #3016 into 16.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2024-12-12 13:12:36 +00:00
7 changed files with 163 additions and 3 deletions

View File

@@ -57,7 +57,7 @@ Usage
Known issues / Roadmap
======================
- Add compatibility with `sale` module
- Add compatibility with `sale_product_configurator` module
- Add compatibility with `purchase_product_matrix` module
- When this module is installed, the PDF report will always display the column `name` as a combination of the `product code`, `product name`, and `description`. This behavior may differ from the expected behavior, where only the column `name` is displayed and can be customized independently.

View File

@@ -13,6 +13,7 @@
],
"assets": {
"web.assets_backend": [
"web_widget_product_label_section_and_note/static/src/core/utils/**/*",
"web_widget_product_label_section_and_note/static/src/components/**/*",
],
},

View File

@@ -1,3 +1,3 @@
- Add compatibility with `sale` module
- Add compatibility with `sale_product_configurator` module
- Add compatibility with `purchase_product_matrix` module
- When this module is installed, the PDF report will always display the column `name` as a combination of the `product code`, `product name`, and `description`. This behavior may differ from the expected behavior, where only the column `name` is displayed and can be customized independently.

View File

@@ -407,7 +407,7 @@ in a new module, it is necessary to create an inherited view to change the widge
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Add compatibility with <cite>sale</cite> module</li>
<li>Add compatibility with <cite>sale_product_configurator</cite> module</li>
<li>Add compatibility with <cite>purchase_product_matrix</cite> module</li>
<li>When this module is installed, the PDF report will always display the column <cite>name</cite> as a combination of the <cite>product code</cite>, <cite>product name</cite>, and <cite>description</cite>. This behavior may differ from the expected behavior, where only the column <cite>name</cite> is displayed and can be customized independently.</li>
</ul>

View File

@@ -20,6 +20,7 @@ import {X2ManyField} from "@web/views/fields/x2many/x2many_field";
import {_t} from "@web/core/l10n/translation";
import {getActiveHotkey} from "@web/core/hotkeys/hotkey_service";
import {registry} from "@web/core/registry";
import {useProductAndLabelAutoresize} from "../../core/utils/product_and_label_autoresize.esm";
export class ProductLabelSectionAndNoteListRender extends SectionAndNoteListRenderer {
setup() {
@@ -138,7 +139,13 @@ export class ProductLabelSectionAndNoteField extends Many2OneField {
value: this.props.record.columnIsProductAndLabel,
});
this.labelNode = useRef("labelNodeRef");
useProductAndLabelAutoresize(this.labelNode, {
targetParentName: this.props.name,
});
this.productNode = useRef("productNodeRef");
useProductAndLabelAutoresize(this.productNode, {
targetParentName: this.props.name,
});
useEffect(
() => {

View File

@@ -0,0 +1,111 @@
/** @odoo-module **/
/* Copyright Odoo S.A.
* Copyright 2024 Tecnativa - Carlos Lopez
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
import {useEffect} from "@odoo/owl";
import {browser} from "@web/core/browser/browser";
function resizeInput(input) {
// This mesures the maximum width of the input which can get from the flex layout.
input.style.width = "100%";
const maxWidth = input.clientWidth;
// Somehow Safari 16 computes input sizes incorrectly. This is fixed in Safari 17
const isSafari16 = /Version\/16.+Safari/i.test(browser.navigator.userAgent);
// Minimum width of the input
input.style.width = "10px";
if (input.value === "" && input.placeholder !== "") {
input.style.width = "auto";
return;
}
if (input.scrollWidth + 5 + (isSafari16 ? 8 : 0) > maxWidth) {
input.style.width = "100%";
return;
}
input.style.width = input.scrollWidth + 5 + (isSafari16 ? 8 : 0) + "px";
}
export function resizeTextArea(textarea, options = {}) {
const minimumHeight = options.minimumHeight || 0;
let heightOffset = 0;
const style = window.getComputedStyle(textarea);
if (style.boxSizing === "border-box") {
const paddingHeight =
parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
const borderHeight =
parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
heightOffset = borderHeight + paddingHeight;
}
const previousStyle = {
borderTopWidth: style.borderTopWidth,
borderBottomWidth: style.borderBottomWidth,
padding: style.padding,
};
Object.assign(textarea.style, {
height: "auto",
borderTopWidth: 0,
borderBottomWidth: 0,
paddingTop: 0,
paddingRight: style.paddingRight,
paddingBottom: 0,
paddingLeft: style.paddingLeft,
});
textarea.style.height = "auto";
const height = Math.max(minimumHeight, textarea.scrollHeight + heightOffset);
Object.assign(textarea.style, previousStyle, {height: `${height}px`});
textarea.parentElement.style.height = `${height}px`;
}
/**
* This is used on text inputs or textareas to automatically resize it based on its
* content each time it is updated. It takes the reference of the element as
* parameter and some options. Do note that it may introduce mild performance issues
* since it will force a reflow of the layout each time the element is updated.
* Do also note that it only works with textareas that are nested as only child
* of some parent div (like in the text_field component).
*
* @param {Ref} ref
*/
export function useAutoresize(ref, options = {}) {
let wasProgrammaticallyResized = false;
let resize = null;
useEffect(
(el) => {
if (el) {
resize = (programmaticResize = false) => {
wasProgrammaticallyResized = programmaticResize;
if (el instanceof HTMLInputElement) {
resizeInput(el, options);
} else {
resizeTextArea(el, options);
}
if (options.onResize) {
options.onResize(el, options);
}
};
el.addEventListener("input", () => resize(true));
const resizeObserver = new ResizeObserver(() => {
// This ensures that the resize function is not called twice on input or page load
if (wasProgrammaticallyResized) {
wasProgrammaticallyResized = false;
return;
}
resize();
});
resizeObserver.observe(el);
return () => {
el.removeEventListener("input", resize);
resizeObserver.unobserve(el);
resizeObserver.disconnect();
resize = null;
};
}
},
() => [ref.el]
);
useEffect(() => {
if (resize) {
resize(true);
}
});
}

View File

@@ -0,0 +1,41 @@
/** @odoo-module **/
/* Copyright Odoo S.A.
* Copyright 2024 Tecnativa - Carlos Lopez
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
import {useAutoresize} from "./autoresize.esm";
export function productAndLabelResizeTextArea(textarea, options = {}) {
const style = window.getComputedStyle(textarea);
if (options.targetParentName) {
let target = textarea.parentElement;
let shouldContinue = true;
while (target && shouldContinue) {
const totalParentHeight = Array.from(target.children).reduce(
(total, child) => {
const childHeight = child.style.height || style.lineHeight;
return total + parseFloat(childHeight);
},
0
);
target.style.height = `${totalParentHeight}px`;
if (target.getAttribute("name") === options.targetParentName) {
shouldContinue = false;
}
target = target.parentElement;
}
}
}
/**
* This overriden version of the resizeTextArea method is specificly done for the product_label_section_and_note widget
* His necessity is found in the fact that the cell of said widget doesn't contain only the input or textarea to resize
* but also another node containing the name of the product if said data is available. This means that the autoresize
* method which sets the height of the parent cell should sometimes add an additional row to the parent cell so that
* no text overflows
*
* @param {Ref} ref
*/
export function useProductAndLabelAutoresize(ref, options = {}) {
useAutoresize(ref, {onResize: productAndLabelResizeTextArea, ...options});
}