diff --git a/web_remember_tree_column_width/README.rst b/web_remember_tree_column_width/README.rst new file mode 100644 index 000000000..5906fbb13 --- /dev/null +++ b/web_remember_tree_column_width/README.rst @@ -0,0 +1,97 @@ +============================== +Web Remember Tree Column Width +============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ec03536e8e88c5e3dbb117d391ba923b60e328998f72c81cee3b41c8ecaea9c2 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github + :target: https://github.com/OCA/web/tree/18.0/web_remember_tree_column_width + :alt: OCA/web +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_remember_tree_column_width + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Remember the tree columns' widths across sessions, and after filtering, +grouping, or reordering. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Vauxoo + +Contributors +------------ + +- Francisco Javier Luna Vázquez +- Tomás Álvarez +- `Komit `__: + + - Cuong Nguyen Mtm + +- Jasmin Solanki + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-frahikLV| image:: https://github.com/frahikLV.png?size=40px + :target: https://github.com/frahikLV + :alt: frahikLV +.. |maintainer-luisg123v| image:: https://github.com/luisg123v.png?size=40px + :target: https://github.com/luisg123v + :alt: luisg123v +.. |maintainer-cuongnmtm| image:: https://github.com/cuongnmtm.png?size=40px + :target: https://github.com/cuongnmtm + :alt: cuongnmtm + +Current `maintainers `__: + +|maintainer-frahikLV| |maintainer-luisg123v| |maintainer-cuongnmtm| + +This module is part of the `OCA/web `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_remember_tree_column_width/__init__.py b/web_remember_tree_column_width/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/web_remember_tree_column_width/__manifest__.py b/web_remember_tree_column_width/__manifest__.py new file mode 100644 index 000000000..f2a63b3ba --- /dev/null +++ b/web_remember_tree_column_width/__manifest__.py @@ -0,0 +1,24 @@ +{ + "name": "Web Remember Tree Column Width", + "summary": "Remember the tree columns' widths across sessions.", + "author": "Vauxoo, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/web", + "license": "LGPL-3", + "category": "Extra Tools", + "version": "18.0.1.0.0", + "maintainers": [ + "frahikLV", + "luisg123v", + "cuongnmtm", + ], + "depends": [ + "web", + ], + "data": [], + "assets": { + "web.assets_backend": [ + "web_remember_tree_column_width/static/src/**/*", + ], + }, + "installable": True, +} diff --git a/web_remember_tree_column_width/i18n/it.po b/web_remember_tree_column_width/i18n/it.po new file mode 100644 index 000000000..e69de29bb diff --git a/web_remember_tree_column_width/i18n/web_remember_tree_column_width.pot b/web_remember_tree_column_width/i18n/web_remember_tree_column_width.pot new file mode 100644 index 000000000..716a0702d --- /dev/null +++ b/web_remember_tree_column_width/i18n/web_remember_tree_column_width.pot @@ -0,0 +1,13 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" diff --git a/web_remember_tree_column_width/pyproject.toml b/web_remember_tree_column_width/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/web_remember_tree_column_width/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/web_remember_tree_column_width/readme/CONTRIBUTORS.md b/web_remember_tree_column_width/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..763d20923 --- /dev/null +++ b/web_remember_tree_column_width/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +- Francisco Javier Luna Vázquez \<\> +- Tomás Álvarez \<\> +- [Komit](https://komit-consulting.com/): + - Cuong Nguyen Mtm \<\> +- Jasmin Solanki \<\> \ No newline at end of file diff --git a/web_remember_tree_column_width/readme/DESCRIPTION.md b/web_remember_tree_column_width/readme/DESCRIPTION.md new file mode 100644 index 000000000..28df572da --- /dev/null +++ b/web_remember_tree_column_width/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +Remember the tree columns' widths across sessions, and after filtering, +grouping, or reordering. diff --git a/web_remember_tree_column_width/static/description/icon.png b/web_remember_tree_column_width/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/web_remember_tree_column_width/static/description/icon.png differ diff --git a/web_remember_tree_column_width/static/description/index.html b/web_remember_tree_column_width/static/description/index.html new file mode 100644 index 000000000..1c8dd4ebd --- /dev/null +++ b/web_remember_tree_column_width/static/description/index.html @@ -0,0 +1,432 @@ + + + + + +Web Remember Tree Column Width + + + +
+

Web Remember Tree Column Width

+ + +

Beta License: LGPL-3 OCA/web Translate me on Weblate Try me on Runboat

+

Remember the tree columns’ widths across sessions, and after filtering, +grouping, or reordering.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Vauxoo
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainers:

+

frahikLV luisg123v cuongnmtm

+

This module is part of the OCA/web project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/web_remember_tree_column_width/static/src/js/column_width_hook.esm.js b/web_remember_tree_column_width/static/src/js/column_width_hook.esm.js new file mode 100644 index 000000000..3ad76af78 --- /dev/null +++ b/web_remember_tree_column_width/static/src/js/column_width_hook.esm.js @@ -0,0 +1,443 @@ +/* eslint init-declarations: 0 */ +/* eslint no-undef: 0 */ +/* eslint no-use-before-define: 0 */ + +// Copy file web/static/src/views/list/column_width_hook.js and added custom code for remeber width of column + +import {useDebounced} from "@web/core/utils/timing"; +import {browser} from "@web/core/browser/browser"; +import {useComponent, useEffect, useExternalListener} from "@odoo/owl"; + +// Hardcoded widths +const DEFAULT_MIN_WIDTH = 80; +const SELECTOR_WIDTH = 20; +const OPEN_FORM_VIEW_BUTTON_WIDTH = 54; +const DELETE_BUTTON_WIDTH = 12; +const FIELD_WIDTHS = { + boolean: [20, 100], // [minWidth, maxWidth] + char: [80], // Only minWidth, no maxWidth + date: 80, // MinWidth = maxWidth + datetime: 145, + float: 93, + integer: 71, + many2many: [80], + many2one_reference: [80], + many2one: [80], + monetary: 105, + one2many: [80], + reference: [80], + selection: [80], + text: [80, 1200], +}; + +/** + * Compute ideal widths based on the rules described on top of this file. + * + * @params {Element} table + * @params {Object} state + * @params {Number} allowedWidth + * @params {Number[]} startingWidths + * @returns {Number[]} + */ +function computeWidths(table, state, allowedWidth, startingWidths) { + let _columnWidths; + const headers = [...table.querySelectorAll("thead th")]; + const columns = state.columns; + + // Starting point: compute widths + if (startingWidths) { + _columnWidths = startingWidths.slice(); + } else if (state.isEmpty) { + // Table is empty => uniform distribution as starting point + _columnWidths = headers.map(() => allowedWidth / headers.length); + } else { + // Table contains records => let the browser compute ideal widths + // Set table layout auto and remove inline style + table.style.tableLayout = "auto"; + headers.forEach((th) => { + th.style.width = null; + }); + // Toggle a className used to remove style that could interfere with the ideal width + // computation algorithm (e.g. prevent text fields from being wrapped during the + // computation, to prevent them from being completely crushed) + table.classList.add("o_list_computing_widths"); + _columnWidths = headers.map((th) => th.getBoundingClientRect().width); + table.classList.remove("o_list_computing_widths"); + } + + // Force columns to comply with their min and max widths + if (state.hasSelectors) { + _columnWidths[0] = SELECTOR_WIDTH; + } + if (state.hasOpenFormViewColumn) { + const index = _columnWidths.length - (state.hasActionsColumn ? 2 : 1); + _columnWidths[index] = OPEN_FORM_VIEW_BUTTON_WIDTH; + } + if (state.hasActionsColumn) { + _columnWidths[_columnWidths.length - 1] = DELETE_BUTTON_WIDTH; + } + const columnWidthSpecs = getWidthSpecs(columns); + const columnOffset = state.hasSelectors ? 1 : 0; + for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) { + const thIndex = columnIndex + columnOffset; + const {minWidth, maxWidth} = columnWidthSpecs[columnIndex]; + if (_columnWidths[thIndex] < minWidth) { + _columnWidths[thIndex] = minWidth; + } else if (maxWidth && _columnWidths[thIndex] > maxWidth) { + _columnWidths[thIndex] = maxWidth; + } + } + + // Expand/shrink columns for the table to fill 100% of available space + const totalWidth = _columnWidths.reduce((tot, width) => tot + width, 0); + let diff = totalWidth - allowedWidth; + if (diff >= 1) { + // Case 1: table overflows its parent => shrink some columns + const shrinkableColumns = []; + let totalAvailableSpace = 0; // Total space we can gain by shrinking columns + for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) { + const thIndex = columnIndex + columnOffset; + const {minWidth, canShrink} = columnWidthSpecs[columnIndex]; + if (_columnWidths[thIndex] > minWidth && canShrink) { + shrinkableColumns.push({thIndex, minWidth}); + totalAvailableSpace += _columnWidths[thIndex] - minWidth; + } + } + if (diff > totalAvailableSpace) { + // We can't find enough space => set all columns to their min width, and there'll be an + // horizontal scrollbar + for (const {thIndex, minWidth} of shrinkableColumns) { + _columnWidths[thIndex] = minWidth; + } + } else { + // There's enough available space among shrinkable columns => shrink them uniformly + let remainingColumnsToShrink = shrinkableColumns.length; + while (diff >= 1) { + const colDiff = diff / remainingColumnsToShrink; + for (const {thIndex, minWidth} of shrinkableColumns) { + const currentWidth = _columnWidths[thIndex]; + if (currentWidth === minWidth) { + continue; + } + const newWidth = Math.max(currentWidth - colDiff, minWidth); + diff -= currentWidth - newWidth; + _columnWidths[thIndex] = newWidth; + if (newWidth === minWidth) { + remainingColumnsToShrink--; + } + } + } + } + } else if (diff <= -1) { + // Case 2: table is narrower than its parent => expand some columns + diff = -diff; // For better readability + const expandableColumns = []; + for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) { + const thIndex = columnIndex + columnOffset; + const maxWidth = columnWidthSpecs[columnIndex].maxWidth; + if (!maxWidth || _columnWidths[thIndex] < maxWidth) { + expandableColumns.push({thIndex, maxWidth}); + } + } + // Expand all expandable columns uniformly (i.e. at most, expand columns with a maxWidth + // to their maxWidth) + let remainingExpandableColumns = expandableColumns.length; + while (diff >= 1 && remainingExpandableColumns > 0) { + const colDiff = diff / remainingExpandableColumns; + for (const {thIndex, maxWidth} of expandableColumns) { + const currentWidth = _columnWidths[thIndex]; + const newWidth = Math.min( + currentWidth + colDiff, + maxWidth || Number.MAX_VALUE + ); + diff -= newWidth - currentWidth; + _columnWidths[thIndex] = newWidth; + if (newWidth === maxWidth) { + remainingExpandableColumns--; + } + } + } + if (diff >= 1) { + // All columns have a maxWidth and have been expanded to their max => expand them more + for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) { + const thIndex = columnIndex + columnOffset; + _columnWidths[thIndex] += diff / columns.length; + } + } + } + return _columnWidths; +} + +/** + * Returns for each column its minimal and (if any) maximal widths. + * + * @param {Object[]} columns + * @returns {Object[]} each entry in this array has a minWidth and optionally a maxWidth key + */ +function getWidthSpecs(columns) { + return columns.map((column) => { + let minWidth; + let maxWidth; + if (column.attrs && column.attrs.width) { + minWidth = maxWidth = parseInt(column.attrs.width.split("px")[0]); + } else { + let width; + if (column.type === "field") { + if (column.field.listViewWidth) { + width = column.field.listViewWidth; + if (typeof width === "function") { + width = width({ + type: column.fieldType, + hasLabel: column.hasLabel, + }); + } + } else { + width = FIELD_WIDTHS[column.widget || column.fieldType]; + } + } else if (column.type === "widget") { + width = column.widget.listViewWidth; + } + if (width) { + minWidth = Array.isArray(width) ? width[0] : width; + maxWidth = Array.isArray(width) ? width[1] : width; + } else { + minWidth = DEFAULT_MIN_WIDTH; + } + } + return {minWidth, maxWidth, canShrink: column.type === "field"}; + }); +} + +/** + * Given an html element, returns the sum of its left and right padding. + * + * @param {HTMLElement} el + * @returns {Number} + */ +function getHorizontalPadding(el) { + const {paddingLeft, paddingRight} = getComputedStyle(el); + return parseFloat(paddingLeft) + parseFloat(paddingRight); +} + +export function useMagicColumnWidths(tableRef, getState) { + const renderer = useComponent(); + let columnWidths = null; + let allowedWidth = 0; + let hasAlwaysBeenEmpty = true; + let parentWidthFixed = false; + let hash; + let _resizing = false; + + /** + * Apply the column widths in the DOM. If necessary, compute them first (e.g. if they haven't + * been computed yet, or if columns have changed). + * + * Note: the following code manipulates the DOM directly to avoid having to wait for a + * render + patch which would occur on the next frame and cause flickering. + */ + function forceColumnWidths() { + const table = tableRef.el; + const headers = [...table.querySelectorAll("thead th")]; + const state = getState(); + const resModel = state.model.config.resModel; + + // Generate a hash to be able to detect when the columns change + const columns = state.columns; + // The last part of the hash is there to detect that static columns changed (typically, the + // selector column, which isn't displayed on small screens) + const nextHash = `${columns.map((column) => column.id).join("/")}/${headers.length}`; + if (nextHash !== hash) { + hash = nextHash; + resetWidths(); + } + // If the table has always been empty until now, and it now contains records, we want to + // recompute the widths based on the records (typical case: we removed a filter). + // Exception: we were in an empty editable list, and we just added a first record. + if (hasAlwaysBeenEmpty && !state.isEmpty) { + hasAlwaysBeenEmpty = false; + const rows = table.querySelectorAll(".o_data_row"); + if (rows.length !== 1 || !rows[0].classList.contains("o_selected_row")) { + resetWidths(); + } + } + + const parentPadding = getHorizontalPadding(table.parentNode); + const cellPaddings = headers.map((th) => getHorizontalPadding(th)); + const totalCellPadding = cellPaddings.reduce( + (total, padding) => padding + total, + 0 + ); + const nextAllowedWidth = + table.parentNode.clientWidth - parentPadding - totalCellPadding; + const allowedWidthDiff = Math.abs(allowedWidth - nextAllowedWidth); + allowedWidth = nextAllowedWidth; + + // When a vertical scrollbar appears/disappears, it may (depending on the browser/os) change + // the available width. When it does, we want to keep the current widths, but tweak them a + // little bit s.t. the table fits in the new available space. + if (!columnWidths || allowedWidthDiff > 0) { + columnWidths = computeWidths(table, state, allowedWidth, columnWidths); + } + + // Custom code to get width from browser storage and update in list + // custom code start here + headers.forEach((el, elIndex) => { + const fieldName = + (state.columns[elIndex] && state.columns[elIndex].name) || ""; + if ( + !el.classList.contains("o_list_button") && + fieldName && + resModel && + browser.localStorage + ) { + const storedWidth = browser.localStorage.getItem( + `odoo.columnWidth.${resModel}.${fieldName}` + ); + if (storedWidth) { + columnWidths[elIndex + 1] = parseInt(storedWidth, 10); + } + } + }); + // Custom code end here + + // Set the computed widths in the DOM. + table.style.tableLayout = "fixed"; + headers.forEach((th, index) => { + th.style.width = `${Math.floor(columnWidths[index] + cellPaddings[index])}px`; + }); + } + + /** + * Resets the widths. After next patch, ideal widths will be recomputed. + */ + function resetWidths() { + columnWidths = null; + // Unset widths that might have been set on the table by resizing a column + tableRef.el.style.width = null; + if (parentWidthFixed) { + tableRef.el.parentElement.style.width = null; + } + } + + /** + * Handles the resize feature on the column headers + * + * @private + * @param {MouseEvent} ev + */ + function onStartResize(ev) { + _resizing = true; + const table = tableRef.el; + const th = ev.target.closest("th"); + const handler = th.querySelector(".o_resize"); + table.style.width = `${Math.floor(table.getBoundingClientRect().width)}px`; + const thPosition = [...th.parentNode.children].indexOf(th); + const resizingColumnElements = [...table.getElementsByTagName("tr")] + .filter((tr) => tr.children.length === th.parentNode.children.length) + .map((tr) => tr.children[thPosition]); + const initialX = ev.clientX; + const initialWidth = th.getBoundingClientRect().width; + const initialTableWidth = table.getBoundingClientRect().width; + const resizeStoppingEvents = ["keydown", "pointerdown", "pointerup"]; + + // Fix the width so that if the resize overflows, it doesn't affect the layout of the parent + if (!table.parentElement.style.width) { + parentWidthFixed = true; + table.parentElement.style.width = `${Math.floor( + table.parentElement.getBoundingClientRect().width + )}px`; + } + + // Apply classes to table and selected column + table.classList.add("o_resizing"); + for (const el of resizingColumnElements) { + el.classList.add("o_column_resizing"); + handler.classList.add("bg-primary", "opacity-100"); + handler.classList.remove("bg-black-25", "opacity-50-hover"); + } + // Mousemove event : resize header + const resizeHeader = (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + const delta = ev.clientX - initialX; + const newWidth = Math.max(10, initialWidth + delta); + const tableDelta = newWidth - initialWidth; + th.style.width = `${Math.floor(newWidth)}px`; + table.style.width = `${Math.floor(initialTableWidth + tableDelta)}px`; + }; + window.addEventListener("pointermove", resizeHeader); + + // Mouse or keyboard events : stop resize + const stopResize = (ev) => { + _resizing = false; + + // Store current column widths to freeze them + const headers = [...table.querySelectorAll("thead th")]; + columnWidths = headers.map((th) => { + return th.getBoundingClientRect().width - getHorizontalPadding(th); + }); + + // Ignores the 'left mouse button down' event as it used to start resizing + if (ev.type === "pointerdown" && ev.button === 0) { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + + table.classList.remove("o_resizing"); + for (const el of resizingColumnElements) { + el.classList.remove("o_column_resizing"); + handler.classList.remove("bg-primary", "opacity-100"); + handler.classList.add("bg-black-25", "opacity-50-hover"); + } + + window.removeEventListener("pointermove", resizeHeader); + for (const eventType of resizeStoppingEvents) { + window.removeEventListener(eventType, stopResize); + } + + // Custom code to set width to browser storage + // custom code start here + const th = ev.target.closest("th"); + const fieldName = th.dataset.name; + const resModel = this.props.list.model.config.resModel; + if (resModel && fieldName && browser.localStorage) { + browser.localStorage.setItem( + "odoo.columnWidth." + resModel + "." + fieldName, + parseInt((th.style.width || "0").replace("px", ""), 10) || 0 + ); + } + // Custom code end here + + // We remove the focus to make sure that the there is no focus inside + // the tr. If that is the case, there is some css to darken the whole + // thead, and it looks quite weird with the small css hover effect. + document.activeElement.blur(); + }; + // We have to listen to several events to properly stop the resizing function. Those are: + // - pointerdown (e.g. pressing right click) + // - pointerup : logical flow of the resizing feature (drag & drop) + // - keydown : (e.g. pressing 'Alt' + 'Tab' or 'Windows' key) + for (const eventType of resizeStoppingEvents) { + window.addEventListener(eventType, stopResize); + } + } + + // Side effects + if (renderer.constructor.useMagicColumnWidths) { + useEffect(forceColumnWidths); + const debouncedResizeCallback = useDebounced(() => { + resetWidths(); + forceColumnWidths(); + }, 200); + useExternalListener(window, "resize", debouncedResizeCallback); + } + + // API + return { + get resizing() { + return _resizing; + }, + onStartResize, + }; +} diff --git a/web_remember_tree_column_width/static/src/js/list_renderer.esm.js b/web_remember_tree_column_width/static/src/js/list_renderer.esm.js new file mode 100644 index 000000000..ccfc4a024 --- /dev/null +++ b/web_remember_tree_column_width/static/src/js/list_renderer.esm.js @@ -0,0 +1,21 @@ +import {ListRenderer} from "@web/views/list/list_renderer"; +import {useMagicColumnWidths} from "./column_width_hook.esm"; +import {patch} from "@web/core/utils/patch"; + +patch(ListRenderer.prototype, { + setup() { + super.setup(); + this.columnWidths = useMagicColumnWidths(this.tableRef, () => { + return { + columns: this.columns, + isEmpty: + !this.props.list.records.length || + this.props.list.model.useSampleModel, + hasSelectors: this.hasSelectors, + hasOpenFormViewColumn: this.hasOpenFormViewColumn, + hasActionsColumn: this.hasActionsColumn, + model: this.props.list.model, + }; + }); + }, +}); diff --git a/web_remember_tree_column_width/static/src/scss/main.scss b/web_remember_tree_column_width/static/src/scss/main.scss new file mode 100644 index 000000000..07b5aa024 --- /dev/null +++ b/web_remember_tree_column_width/static/src/scss/main.scss @@ -0,0 +1,4 @@ +th.o_column_sortable { + max-width: none !important; + min-width: 0 !important; +}