[IMP] web: ListRenderer improve design, simplify scss
Part of the overall v16 SCSS optimization/restyle, task-2704984. task-2946835 Part-of: odoo/odoo#98234
This commit is contained in:
committed by
Pierre Paridans
parent
eb1fa44652
commit
8add0bf5ec
@@ -132,7 +132,7 @@ $headings-color: $o-main-headings-color !default;
|
||||
|
||||
$table-striped-color: inherit !default;
|
||||
$table-striped-bg-factor: .01 !default;
|
||||
$table-hover-bg: rgba($black, .04) !default;
|
||||
$table-hover-bg-factor: .075 !default;
|
||||
$table-border-color: $gray-200 !default;
|
||||
$table-group-separator-color: $gray-200 !default;
|
||||
$table-cell-padding-x: .75rem !default;
|
||||
@@ -140,6 +140,10 @@ $table-cell-padding-y: .75rem !default;
|
||||
$table-cell-padding-x-sm: .3rem !default;
|
||||
$table-cell-padding-y-sm: .3rem !default;
|
||||
|
||||
$table-active-bg-factor: .05 !default;
|
||||
$table-active-color: $headings-color !default;
|
||||
$table-th-font-weight: $headings-font-weight !default;
|
||||
|
||||
// Buttons
|
||||
//
|
||||
$btn-border-radius-lg: $border-radius !default;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
.o_input {
|
||||
border:$input-border-width solid var(--o-input-border-color);
|
||||
padding: $o-input-padding-y $o-input-padding-x;
|
||||
background-color: var(--o-input-background-color, unset);
|
||||
|
||||
// -- Nested o_input(s)
|
||||
.o_input {
|
||||
|
||||
@@ -1,32 +1,52 @@
|
||||
.o_list_renderer {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
--ListRenderer-table-padding-h: #{$table-cell-padding-x-sm};
|
||||
|
||||
--ListRenderer-thead-padding-v: #{$table-cell-padding-y * 1.25};
|
||||
--ListRenderer-thead-bg-color: #{$gray-200};
|
||||
--ListRenderer-thead-border-end-color: #{$border-color};
|
||||
|
||||
.o_list_view & {
|
||||
--ListRenderer-table-padding-h: #{$o-horizontal-padding};
|
||||
}
|
||||
|
||||
.o_list_table {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background-color: $o-view-background-color;
|
||||
margin-bottom: 0px;
|
||||
|
||||
// Don't understand why but without those, the list view appears broken
|
||||
// in both form views and standalone list views.
|
||||
border-collapse: initial;
|
||||
border-spacing: 0;
|
||||
> thead, > tbody, > tfoot {
|
||||
> tr > :first-child {
|
||||
padding-left: var(--ListRenderer-table-padding-h);
|
||||
}
|
||||
|
||||
thead {
|
||||
color: $o-main-headings-color;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
> tr > th:not(.o_list_record_selector) {
|
||||
border-left: 1px solid #dfdfdf;
|
||||
@include o-text-overflow(table-cell);
|
||||
&:not(.o_column_sortable):hover {
|
||||
cursor: default;
|
||||
}
|
||||
&.o_list_number_th {
|
||||
text-align: right;
|
||||
}
|
||||
> tr > :last-child {
|
||||
padding-right: var(--ListRenderer-table-padding-h);
|
||||
}
|
||||
|
||||
> tr > :empty {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
thead, tfoot {
|
||||
tr > :not(:empty) {
|
||||
padding-top: var(--ListRenderer-thead-padding-v);
|
||||
padding-bottom: var(--ListRenderer-thead-padding-v);
|
||||
}
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: var(--ListRenderer-thead-bg-color);
|
||||
color: $headings-color;
|
||||
|
||||
th:not(.o_list_record_selector) {
|
||||
border-left: $border-width solid var(--ListRenderer-thead-border-end-color);
|
||||
}
|
||||
}
|
||||
|
||||
// Override BS default
|
||||
> :not(:first-child) {
|
||||
border-top-width: 0;
|
||||
}
|
||||
|
||||
tbody > tr > td:not(.o_list_record_selector) {
|
||||
&:not(.o_handle_cell):not(.o_list_button):not(.o_state_selection_cell) {
|
||||
@include o-text-overflow(table-cell);
|
||||
@@ -68,72 +88,32 @@
|
||||
}
|
||||
|
||||
tfoot {
|
||||
cursor: default;
|
||||
// cursor: default;
|
||||
color: $o-list-footer-color;
|
||||
background-color: $o-list-footer-bg-color;
|
||||
font-weight: $o-list-footer-font-weight;
|
||||
border-top: 2px solid #cacaca;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
border-top: 1px solid $table-border-color;
|
||||
border-bottom: 1px solid $table-border-color;
|
||||
|
||||
|
||||
> tr > td {
|
||||
@include o-text-overflow(table-cell);
|
||||
}
|
||||
.o_list_number {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.o_column_sortable:not(.o_handle_cell) {
|
||||
position: relative;
|
||||
user-select: none; // Prevent unwanted selection while sorting
|
||||
|
||||
&::after {
|
||||
font-family: FontAwesome;
|
||||
content: "\f0d7";
|
||||
opacity: 0;
|
||||
}
|
||||
&:not(:empty)::after {
|
||||
margin-left: 6px;
|
||||
}
|
||||
&.o-sort-up {
|
||||
cursor: n-resize;
|
||||
&::after {
|
||||
content: "\f0d7";
|
||||
}
|
||||
}
|
||||
&.o-sort-down {
|
||||
cursor: s-resize;
|
||||
&::after {
|
||||
content: "\f0d8";
|
||||
}
|
||||
}
|
||||
&:hover::after {
|
||||
opacity: 0.3;
|
||||
}
|
||||
&.o-sort-up, &.o-sort-down {
|
||||
color: $headings-color;
|
||||
&::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_record_selector {
|
||||
width: 40px;
|
||||
padding-left: $o-horizontal-padding;
|
||||
.o-checkbox {
|
||||
margin-bottom: $form-check-margin-bottom;
|
||||
}
|
||||
.form-check-label {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.o_list_record_remove, .o_handle_cell {
|
||||
width: 1px; // to prevent the column to expand
|
||||
}
|
||||
|
||||
.o_list_record_selector, .o_handle_cell {
|
||||
max-width: 35px !important;
|
||||
|
||||
.o_list_table_ungrouped {
|
||||
.o_list_controller {
|
||||
max-width: 35px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_record_remove button {
|
||||
@@ -144,6 +124,42 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
outline-offset: -1px;
|
||||
|
||||
&:hover {
|
||||
outline: 1px solid $gray-400;
|
||||
}
|
||||
|
||||
&.table-info {
|
||||
outline-color: $info;
|
||||
}
|
||||
|
||||
&.o_selected_row {
|
||||
th:focus-within, td:focus-within {
|
||||
--table-accent-bg: none;
|
||||
|
||||
background-color: $o-view-background-color;
|
||||
outline-offset: -1px;
|
||||
outline: 1px solid $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_keyboard_navigation {
|
||||
tr:hover {
|
||||
outline-color: transparent;
|
||||
}
|
||||
|
||||
th:focus-within, td:focus-within {
|
||||
--table-accent-bg: none;
|
||||
|
||||
background-color: $o-view-background-color;
|
||||
outline-offset: -1px;
|
||||
outline: 1px solid $primary;
|
||||
}
|
||||
}
|
||||
|
||||
// Grouped list views
|
||||
tbody > tr.o_group_header {
|
||||
> th, > td {
|
||||
@@ -189,16 +205,7 @@
|
||||
border-top: none; // Override bootstrap for grouped list views
|
||||
}
|
||||
|
||||
&, &.table-striped {
|
||||
tr:focus-within {
|
||||
background-color: lighten($o-form-lightsecondary, 10%);
|
||||
}
|
||||
}
|
||||
thead th:focus-within,
|
||||
tbody.o_keyboard_navigation td:focus-within {
|
||||
background-color: $o-form-lightsecondary;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
.o_data_cell.o_text_overflow,
|
||||
.o_data_cell.o_invisible_modifier {
|
||||
@@ -220,13 +227,7 @@
|
||||
}
|
||||
|
||||
span.o_resize {
|
||||
bottom: 0;
|
||||
cursor: col-resize;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 10px;
|
||||
z-index: 1; // must be over the sort caret (::after pseudo-element)
|
||||
}
|
||||
|
||||
.o_list_actions_header {
|
||||
@@ -274,10 +275,7 @@
|
||||
}
|
||||
|
||||
.o_data_row.o_selected_row > .o_data_cell {
|
||||
position: relative; // for o_field_translate
|
||||
&:not(.o_handle_cell) {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
> .o_field_widget:not(.o_readonly_modifier):not(.o_invisible_modifier) {
|
||||
width: 100%;
|
||||
.o_input {
|
||||
@@ -306,6 +304,9 @@
|
||||
// reduce basis to prevent many2one input from going to the next line to often
|
||||
flex-basis: 40px;
|
||||
}
|
||||
.o_field_many2one_avatar {
|
||||
display: flex;
|
||||
}
|
||||
&.o_field_badge {
|
||||
width: auto; // override width: 100% to keep the optimal badge width
|
||||
}
|
||||
@@ -349,8 +350,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_view.o_view_controller > .o_content > .table-responsive {
|
||||
// in main list views, let .o_content scroll
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@@ -562,13 +562,15 @@ export class ListRenderer extends Component {
|
||||
const field = this.fields[column.name];
|
||||
const classNames = ["align-middle"];
|
||||
if (field.sortable && column.hasLabel) {
|
||||
classNames.push("o_column_sortable");
|
||||
classNames.push("o_column_sortable", "position-relative", "cursor-pointer");
|
||||
} else {
|
||||
classNames.push("cursor-default");
|
||||
}
|
||||
const orderBy = this.props.list.orderBy;
|
||||
if (orderBy.length && orderBy[0].name === column.name) {
|
||||
classNames.push(orderBy[0].asc ? "o-sort-up" : "o-sort-down");
|
||||
if (orderBy.length && column.widget !== "handle" && orderBy[0].name === column.name) {
|
||||
classNames.push("table-active");
|
||||
}
|
||||
if (["float", "integer", "monetary"].includes(field.type)) {
|
||||
if (this.isNumericColumn(column)) {
|
||||
classNames.push("o_list_number_th");
|
||||
}
|
||||
if (column.type === "button_group") {
|
||||
@@ -592,6 +594,24 @@ export class ListRenderer extends Component {
|
||||
return this.state.columns;
|
||||
}
|
||||
|
||||
isNumericColumn(column) {
|
||||
const { type } = this.fields[column.name];
|
||||
return ["float", "integer", "monetary"].includes(type);
|
||||
}
|
||||
|
||||
getSortableIconClass(column) {
|
||||
const { sortable } = this.fields[column.name];
|
||||
const { orderBy } = this.props.list;
|
||||
const classNames = sortable && column.hasLabel ? ["fa", "fa-lg", "px-2"] : ["d-none"];
|
||||
if (orderBy.length && orderBy[0].name === column.name) {
|
||||
classNames.push(orderBy[0].asc ? "fa-angle-up" : "fa-angle-down");
|
||||
} else {
|
||||
classNames.push("fa-angle-down", "opacity-0", "opacity-75-hover");
|
||||
}
|
||||
|
||||
return classNames.join(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the classnames to apply to the row representing the given record.
|
||||
* @param {Record} record
|
||||
@@ -602,6 +622,9 @@ export class ListRenderer extends Component {
|
||||
const classNames = this.props.archInfo.decorations
|
||||
.filter((decoration) => evaluateExpr(decoration.condition, record.evalContext))
|
||||
.map((decoration) => decoration.class);
|
||||
if (record.selected) {
|
||||
classNames.push("table-info");
|
||||
}
|
||||
// "o_selected_row" classname for the potential row in edition
|
||||
if (record.isInEdition) {
|
||||
classNames.push("o_selected_row");
|
||||
@@ -661,6 +684,15 @@ export class ListRenderer extends Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
record.isInEdition &&
|
||||
this.props.list.editedRecord &&
|
||||
this.props.list.editedRecord.isReadonly(column.name)
|
||||
) {
|
||||
classNames.push("pe-none", "text-muted");
|
||||
} else {
|
||||
classNames.push("cursor-pointer");
|
||||
}
|
||||
}
|
||||
return classNames.join(" ");
|
||||
}
|
||||
@@ -1592,6 +1624,24 @@ export class ListRenderer extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the :hover effect on sortable column headers
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
onHoverSortColumn(ev, column) {
|
||||
if (this.props.list.orderBy.length && this.props.list.orderBy[0].name === column.name) {
|
||||
return;
|
||||
} else if (
|
||||
this.fields[column.name].sortable &&
|
||||
column.widget !== "handle" &&
|
||||
column.hasLabel
|
||||
) {
|
||||
ev.target.classList.toggle("table-active", ev.type == "mouseenter");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the resize feature on the column headers
|
||||
*
|
||||
@@ -1601,6 +1651,7 @@ export class ListRenderer extends Component {
|
||||
onStartResize(ev) {
|
||||
const table = this.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")]
|
||||
@@ -1622,6 +1673,8 @@ export class ListRenderer extends Component {
|
||||
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) => {
|
||||
@@ -1648,6 +1701,8 @@ export class ListRenderer extends Component {
|
||||
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("mousemove", resizeHeader);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="web.ListRenderer" owl="1">
|
||||
<div
|
||||
class="o_list_renderer o_renderer"
|
||||
class="o_list_renderer o_renderer position-relative"
|
||||
t-att-class="{'table-responsive': showTable}"
|
||||
t-attf-class="{{ props.archInfo.className or '' }}"
|
||||
tabindex="-1"
|
||||
@@ -12,22 +12,38 @@
|
||||
<t t-if="showNoContentHelper" t-call="web.ActionHelper">
|
||||
<t t-set="noContentHelp" t-value="props.noContentHelp"/>
|
||||
</t>
|
||||
<table t-if="showTable" t-attf-class="o_list_table table table-sm table-hover table-striped {{props.list.isGrouped ? 'o_list_table_grouped' : 'o_list_table_ungrouped'}}" t-ref="table">
|
||||
<table t-if="showTable" t-attf-class="o_list_table table table-sm position-relative mb-0 {{props.list.isGrouped ? 'o_list_table_grouped' : 'o_list_table_ungrouped table-striped'}}" t-ref="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th t-if="hasSelectors" class="o_list_record_selector align-middle pe-1" t-att-class="{o_sample_data_disabled: props.list.model.useSampleModel}" tabindex="-1" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-on-click.stop="toggleSelection">
|
||||
<CheckBox disabled="!!props.list.editedRecord or props.list.model.useSampleModel" value="selectAll" onChange.bind="toggleSelection"/>
|
||||
<th t-if="hasSelectors" class="o_list_record_selector o_list_controller align-middle pe-1 cursor-pointer" t-att-class="{o_sample_data_disabled: props.list.model.useSampleModel}" tabindex="-1" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-on-click.stop="toggleSelection">
|
||||
<CheckBox disabled="!!props.list.editedRecord or props.list.model.useSampleModel" value="selectAll" className="'d-flex'" onChange.bind="toggleSelection"/>
|
||||
</th>
|
||||
<t t-foreach="state.columns" t-as="column" t-key="column.id">
|
||||
<th t-if="column.type === 'field'" t-att-data-name="column.name" t-att-class="getColumnClass(column)" t-on-click="() => this.onClickSortColumn(column)" tabindex="-1" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-att-data-tooltip-template="isDebugMode ? 'web.FieldTooltip' : false" t-att-data-tooltip-info="isDebugMode ? makeTooltip(column) : false">
|
||||
<th t-if="column.type === 'field'"
|
||||
t-att-data-name="column.name"
|
||||
t-att-class="getColumnClass(column) + ' opacity-trigger-hover'"
|
||||
t-on-mouseenter="ev => this.onHoverSortColumn(ev, column)"
|
||||
t-on-mouseleave="ev => this.onHoverSortColumn(ev, column)"
|
||||
t-on-click="() => this.onClickSortColumn(column)"
|
||||
t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-att-data-tooltip-template="isDebugMode ? 'web.FieldTooltip' : false" t-att-data-tooltip-info="isDebugMode ? makeTooltip(column) : false"
|
||||
tabindex="-1">
|
||||
<t t-if="column.hasLabel and column.widget !== 'handle'">
|
||||
<t t-esc="column.label"/>
|
||||
<span t-if="!isEmpty" class="o_resize" t-on-click.stop.prevent="" t-on-mousedown.stop.prevent="onStartResize"/>
|
||||
<t t-set="isNumeric" t-value="isNumericColumn(column)"/>
|
||||
<div t-att-class="{'d-flex': true, 'flex-row-reverse': isNumeric}">
|
||||
<span class="d-block min-w-0 text-truncate flex-grow-1" t-att-class="isNumeric ? 'text-end' : ''"
|
||||
t-esc="column.label"/>
|
||||
<i t-if="!props.list.isGrouped"
|
||||
t-att-class="getSortableIconClass(column)"/>
|
||||
</div>
|
||||
<span t-if="!isEmpty"
|
||||
class="o_resize position-absolute top-0 end-0 bottom-0 ps-1 bg-black-25 opacity-0 opacity-50-hover z-index-1"
|
||||
t-on-click.stop.prevent=""
|
||||
t-on-mousedown.stop.prevent="onStartResize"/>
|
||||
</t>
|
||||
</th>
|
||||
<th t-else="" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-att-class="{o_list_button: column.type === 'button_group'}"/>
|
||||
</t>
|
||||
<th t-if="displayOptionalFields or (props.activeActions and props.activeActions.onDelete)" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" class="o_list_actions_header" style="width: 32px; min-width: 32px">
|
||||
<th t-if="displayOptionalFields or (props.activeActions and props.activeActions.onDelete)" t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" class="o_list_controller o_list_actions_header" style="width: 32px; min-width: 32px">
|
||||
<Dropdown t-if="displayOptionalFields"
|
||||
class="'o_optional_columns_dropdown text-center border-top-0'"
|
||||
togglerClass="'btn p-0'"
|
||||
@@ -56,12 +72,12 @@
|
||||
<t t-set="list" t-value="props.list"/>
|
||||
</t>
|
||||
</tbody>
|
||||
<tfoot t-on-click="() => props.list.unselectRecord(true)" t-att-class="{o_sample_data_disabled: props.list.model.useSampleModel}">
|
||||
<tfoot t-on-click="() => props.list.unselectRecord(true)" class="cursor-default" t-att-class="{o_sample_data_disabled: props.list.model.useSampleModel}">
|
||||
<tr>
|
||||
<td t-if="hasSelectors"/>
|
||||
<t t-foreach="state.columns" t-as="column" t-key="column.id">
|
||||
<t t-set="aggregate" t-value="aggregates[column.name]"/>
|
||||
<td t-if="aggregate" class="o_list_number" t-att-data-tooltip="aggregate.help">
|
||||
<td t-if="aggregate" class="o_list_number text-end" t-att-data-tooltip="aggregate.help">
|
||||
<t t-esc="aggregate.value"/>
|
||||
</td>
|
||||
<td t-else=""/>
|
||||
@@ -142,11 +158,15 @@
|
||||
</t>
|
||||
|
||||
<t t-name="web.ListRenderer.GroupRow" owl="1">
|
||||
<tr t-attf-class="{{group.count > 0 ? 'o_group_has_content' : ''}} o_group_header {{!group.isFolded ? 'o_group_open' : ''}}"
|
||||
<tr t-attf-class="{{group.count > 0 ? 'o_group_has_content' : ''}} o_group_header {{!group.isFolded ? 'o_group_open' : ''}} cursor-pointer"
|
||||
t-on-click="() => this.toggleGroup(group)"
|
||||
>
|
||||
<th t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev, group)" tabindex="-1" class="o_group_name" t-att-colspan="getGroupNameCellColSpan(group)">
|
||||
<span t-attf-class="fa {{group.isFolded ? 'fa-caret-right' : 'fa-caret-down' }}"
|
||||
<th t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev, group)"
|
||||
tabindex="-1"
|
||||
t-attf-class="o_group_name fs-6 fw-bold {{!group.isFolded ? 'text-900' : 'text-700'}}"
|
||||
t-att-colspan="getGroupNameCellColSpan(group)">
|
||||
|
||||
<span t-attf-class="fa fa-fw {{group.isFolded ? 'fa-caret-right' : 'fa-caret-down' }}"
|
||||
t-attf-style="padding-left: {{2 + getGroupLevel(group) * 20}}px; padding-right: 5px"/>
|
||||
<t t-esc="getGroupDisplayName(group)"/> (<t t-esc="group.count"/>)
|
||||
<div t-if="(groupByButtons[group.groupByField.name] and !group.isFolded)" class="o_group_buttons">
|
||||
@@ -197,7 +217,7 @@
|
||||
<t t-foreach="getColumns(record)" t-as="column" t-key="column.id">
|
||||
<t t-if="column.type === 'field'">
|
||||
<td t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev, group, record)"
|
||||
class="o_data_cell"
|
||||
class="o_data_cell cursor-pointer"
|
||||
t-att-class="getCellClass(column, record)"
|
||||
t-att-name="column.name"
|
||||
t-att-colspan="column.colspan"
|
||||
@@ -233,7 +253,7 @@
|
||||
<t t-if="displayOptionalFields or activeActions">
|
||||
<t t-set="canDelete" t-value="activeActions.canDelete" />
|
||||
<t t-set="canUnlink" t-value="activeActions.canUnlink" />
|
||||
<td t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev, group, record)" t-if="'canUnlink' in activeActions ? canUnlink : canDelete" class="o_list_record_remove" t-on-click.stop="() => this.onDeleteRecord(record)" tabindex="-1">
|
||||
<td t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev, group, record)" t-if="'canUnlink' in activeActions ? canUnlink : canDelete" class="o_list_record_remove text-center" t-on-click.stop="() => this.onDeleteRecord(record)" tabindex="-1">
|
||||
<button class="fa"
|
||||
t-att-class="{ 'fa-trash-o': 'canUnlink' in activeActions ? false : canDelete, 'fa-times': 'canUnlink' in activeActions ? canUnlink : false }"
|
||||
name="delete"
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
|
||||
.o_list_view {
|
||||
thead {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
tbody > tr.o_group_header {
|
||||
background-image: linear-gradient(to bottom, #fcfcfc, #dedede);
|
||||
|
||||
|
||||
@@ -254,9 +254,9 @@ QUnit.module("Views", (hooks) => {
|
||||
assert.containsN(target, "tbody tr", 4, "should have 4 rows");
|
||||
assert.containsOnce(target, "th.o_column_sortable", "should have 1 sortable column");
|
||||
|
||||
assert.strictEqual(
|
||||
$(target).find("thead th:nth(2)").css("text-align"),
|
||||
"right",
|
||||
assert.containsOnce(
|
||||
target,
|
||||
"thead th:nth(2) .text-end",
|
||||
"header cells of integer fields should be right aligned"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -3495,7 +3495,7 @@ QUnit.module("Views", (hooks) => {
|
||||
|
||||
const [titi, grosminet] = target.querySelectorAll(".tab-pane:last-child th");
|
||||
assert.ok(
|
||||
titi.style.width.split("px")[0] > 80 && grosminet.style.width.split("px")[0] > 700,
|
||||
titi.style.width.split("px")[0] > 80 && grosminet.style.width.split("px")[0] > 500,
|
||||
"list has been correctly frozen after being visible"
|
||||
);
|
||||
}
|
||||
@@ -3649,9 +3649,8 @@ QUnit.module("Views", (hooks) => {
|
||||
const thRect = charTh.getBoundingClientRect();
|
||||
const resizeRect = charTh.querySelector(".o_resize").getBoundingClientRect();
|
||||
|
||||
assert.strictEqual(
|
||||
thRect.x + thRect.width,
|
||||
resizeRect.x + resizeRect.width,
|
||||
assert.ok(
|
||||
resizeRect.right - thRect.right <= 1,
|
||||
"First resize handle should be attached at the end of the first header"
|
||||
);
|
||||
assert.containsNone(
|
||||
@@ -3900,7 +3899,6 @@ QUnit.module("Views", (hooks) => {
|
||||
</tree>`,
|
||||
});
|
||||
|
||||
assert.strictEqual($(target).find('th[data-name="datetime"]')[0].offsetWidth, 146);
|
||||
assert.strictEqual($(target).find('th[data-name="int_field"]')[0].offsetWidth, 200);
|
||||
}
|
||||
);
|
||||
@@ -3992,7 +3990,7 @@ QUnit.module("Views", (hooks) => {
|
||||
);
|
||||
assert.strictEqual(
|
||||
window.getComputedStyle(target.querySelectorAll("th")[2]).maxWidth,
|
||||
"100%",
|
||||
"none",
|
||||
"no max-width should be harcoded on the buttons column"
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user