[FW][REF] web: FormView, replace tables with grids

This PR replaces the FormView group tables with css grids.
Part of the overall v16 SCSS optimization/restyle, task-2704984

task-2918464

--
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr

closes odoo/odoo#101655

Forward-port-of: odoo/odoo#98911
Signed-off-by: Adrien Dieudonné (adr) <adr@odoo.com>
This commit is contained in:
Odoo's Mergebot
2022-09-29 19:54:50 +02:00
committed by GitHub
11 changed files with 191 additions and 280 deletions
+1 -1
View File
@@ -71,7 +71,7 @@
<notebook>
<page name="public" string="Work Information">
<div id="o_work_employee_container" class="d-lg-flex"> <!-- These two div are used to position org_chart -->
<div id="o_work_employee_main">
<div id="o_work_employee_main" class="flex-grow-1">
<group string="Location" name="location">
<field name="address_id"
context="{'show_address': 1}"
+1 -1
View File
@@ -103,7 +103,7 @@
<notebook>
<page name="public" string="Work Information">
<div id="o_work_employee_container" class="d-lg-flex"> <!-- These two div are used to position org_chart -->
<div id="o_work_employee_main">
<div id="o_work_employee_main" class="flex-grow-1">
<group string="Location">
<field name="address_id"
context="{'show_address': 1}"
+1 -1
View File
@@ -116,7 +116,7 @@
<notebook position="inside">
<page name="public" string="Work Information">
<div id="o_work_employee_container" class="d-lg-flex"> <!-- These two div are used to position org_chart -->
<div id="o_work_employee_main">
<div id="o_work_employee_main" class="flex-grow-1">
<group string="Location">
<field name="department_id" attrs="{'readonly': [('can_edit', '=', False)]}"/>
<field name="address_id"
@@ -56,6 +56,12 @@ $utilities: () !default;
$utilities: map-merge(
$utilities,
(
"display": map-merge(
map-get($utilities, "display"),
(
values: join(map-get(map-get($utilities, "display"), "values"), contents),
),
),
"position": map-merge(
map-get($utilities, "position"),
(
@@ -316,7 +316,7 @@ export class FormCompiler extends ViewCompiler {
}
if (getTag(child, true) === "separator") {
forceNewline = true;
itemSpan = parseInt(formGroup.getAttribute("maxCols") || 2, 10);
}
let slotContent;
@@ -343,9 +343,14 @@ export class FormCompiler extends ViewCompiler {
mainSlot.setAttribute("subType", "'item_component'");
}
} else {
if (child.classList.contains("o_td_label") || getTag(child, true) === "label") {
// TODO: When every apps will be revamp, we could remove the condition using 'o_td_label' in favor of 'o_wrap_label'
if (
child.classList.contains("o_wrap_label") ||
child.classList.contains("o_td_label") ||
getTag(child, true) === "label"
) {
mainSlot.setAttribute("subType", "'label'");
child.classList.remove("o_td_label");
child.classList.remove("o_wrap_label");
}
slotContent = this.compileNode(child, params, false);
}
@@ -28,53 +28,34 @@
margin-right: -$o-horizontal-padding;
}
@mixin o-td-label-style {
width: 0%;
padding: 0 15px 0 0;
min-width: 150px;
color: $headings-color;
}
// XXS form view specific rules
@mixin form-break-table {
display: block;
grid-template-columns: 1fr;
margin-bottom: $o-form-spacing-unit * 4;
> tbody {
display: block;
.o_wrap_field {
.o_cell {
max-width: 100%;
> tr {
display: flex;
flex-flow: row wrap;
padding-bottom: map-get($spacers, 3);
&.o_wrap_label {
line-height: $o-label-font-size-factor;
}
> td {
flex: 1 0 auto;
display: block;
.o_field_widget {
margin-bottom: $o-form-spacing-unit * 2;
> .o_field_widget {
margin-bottom: 0;
}
&.o_field_boolean {
margin-right: 0;
}
}
.o_input_dropdown {
width: auto;
max-width: 100%;
padding: 0;
&.o_td_label {
width: 94%!important; // The label must be on its own line except if the form field is small enough (checkbox)
line-height: $o-label-font-size-factor;
}
.o_field_widget {
margin-bottom: $o-form-spacing-unit * 2;
> .o_field_widget {
margin-bottom: 0;
}
&.o_field_boolean {
margin-right: 0;
}
}
.o_input_dropdown {
width: auto;
max-width: 100%;
}
}
}
}
@@ -104,11 +85,6 @@
}
.oe_inline, .o_field_widget.oe_inline > * {
width: auto!important;
@include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
&.o_inner_group {
width: 1px!important;
}
}
}
.oe_left {
@extend .oe_inline;
@@ -419,48 +395,6 @@
// Groups
.o_group {
display: inline-block;
width: 100%;
margin: 10px 0;
.o_group {
margin: 0;
}
// o_group contains nested groups
@for $i from 1 through $o-form-group-cols {
.o_group_col_#{$i} {
display: inline-block;
width: floor(100% / 12 * $i);
vertical-align: top;
@include media-breakpoint-down(lg) {
width: 100%;
}
}
}
&.o_inner_group {
display: inline-table;
> tbody > tr > td {
padding: 0 $o-innergroup-rpadding 0 0;
vertical-align: top;
&.o_td_label {
@include o-td-label-style;
}
}
.o_field_widget {
&.o_field_many2one_avatar {
.o_field_many2one_selection {
width: calc(100% - 24px);
}
}
}
}
.o_form_label {
font-weight: $font-weight-normal;
}
@@ -474,19 +408,6 @@
}
}
@include media-breakpoint-up(sm) {
:not(.o_row):not(.o_data_cell) > .o_field_widget,
.o_row > .o_field_widget:last-child { // Note: this does not take care
// of an invisible last-child but
// it does not really matter
// Makes extra buttons (e.g. m2o external button) overflow on the
// right padding of the parent element
.o_input_dropdown {
flex: 1 0 auto;
}
}
}
@include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
.o_field_widget {
&.o_text_overflow {
@@ -509,13 +430,29 @@
white-space: normal;
}
}
.o_td_label .o_form_label {
.o_wrap_label .o_form_label {
font-weight: $font-weight-bold;
margin-right: $o-form-label-margin-right;
}
}
.o_inner_group {
--columns: 1;
gap: map-get($spacers, 2) $o-horizontal-padding;
span, .o_field_boolean, .oe_avatar, .o_form_uri {
&.o_field_widget {
width: auto;
}
}
}
@include media-breakpoint-up(sm) {
.o_inner_group {
grid-template-columns: fit-content(150px) 1fr;
}
}
.o_checkbox_optional_field {
display: flex;
@@ -525,7 +462,7 @@
}
> .o_form_label {
@include o-td-label-style;
color: $headings-color;
margin-right: $o-form-label-margin-right;
font-weight: $font-weight-bold;
}
@@ -715,10 +652,7 @@
margin-bottom: 0px;
}
}
.o_td_label .o_form_label:not(.o_status), .o_checkbox_optional_field > .o_form_label {
min-height: 23px;
}
td:not(.o_field_cell) .o_form_uri > span:first-child {
.o_cell:not(.o_field_cell) .o_form_uri > span:first-child {
display: inline-block;
padding: 1px 0;
margin-bottom: 1px;
@@ -783,14 +717,15 @@
}
// Specific style classes
.o_group.o_inner_group.oe_subtotal_footer {
.o_inner_group.oe_subtotal_footer {
grid-template-columns: 1fr auto;
@extend .oe_right;
border-top: 1px solid $border-color;
> tbody > tr > td {
.o_cell {
padding: 0;
&.o_td_label {
&.o_wrap_label {
text-align: right;
}
@@ -811,7 +746,7 @@
}
}
> tbody > tr:first-child > td {
.o_wrap_field:first-child > .o_cell {
padding-top: 4px;
}
.oe_subtotal_footer_separator {
@@ -964,7 +899,7 @@
}
.oe_form_configuration {
.o_group .o_form_label {
.o_inner_group .o_form_label {
white-space: nowrap;
}
h2 {
@@ -1125,7 +1060,7 @@
}
@include media-breakpoint-down(lg) {
.o_group.o_inner_group > tbody > tr > td.o_td_label {
.o_group.o_inner_group .o_wrap_label {
min-width: 100px;
}
}
@@ -1138,7 +1073,7 @@
}
&.modal-sm .o_form_view {
.o_group {
.o_inner_group {
@include form-break-table;
}
}
@@ -1191,12 +1126,12 @@
word-break: break-all;
}
.o_group {
&.o_inner_group {
@include form-break-table;
.o_inner_group {
margin-bottom: $o-form-spacing-unit * 4;
// Target XXS form view on mobile devices in portrait mode
@include media-breakpoint-down(md) {
&:not(.oe_subtotal_footer) > tbody > tr > td {
&:not(.oe_subtotal_footer) > .o_cell {
> .o_field_widget {
margin-bottom: $o-form-spacing-unit * 4;
}
@@ -26,7 +26,7 @@ export class OuterGroup extends Group {
return items.map((item) => {
const [slotName, slot] = item;
const itemSpan = slot.itemSpan || 1;
return { name: slotName, size: itemSpan * colSize, newline: slot.newline };
return { name: slotName, size: itemSpan * colSize, newline: slot.newline, colspan: itemSpan };
});
}
}
@@ -34,6 +34,7 @@ OuterGroup.template = "web.Form.OuterGroup";
OuterGroup.defaultProps = {
...Group.defaultProps,
slots: [],
hasOuterTemplate: true,
};
export class InnerGroup extends Group {
@@ -66,6 +67,9 @@ export class InnerGroup extends Group {
const isVisible = !("isVisible" in slot) || slot.isVisible;
currentRow.push({ name: slotName, subType, itemSpan, props, isVisible, Component });
reservedSpace += itemSpan || 1;
// Allows to remove the line if the content is not visible instead of leaving an empty line.
currentRow.isVisible = isVisible;
}
rows.push(currentRow);
@@ -2,44 +2,48 @@
<templates xml:space="preserve">
<t t-name="web.Form.OuterGroup" owl="1">
<div class="o_group" t-attf-class="{{ allClasses }}" t-att-style="props.style">
<t t-slot="title" t-if="props.slots.title" />
<t t-foreach="getItems()" t-as="item" t-key="item_index" >
<br t-if="item.newline" />
<t t-slot="{{ item.name }}" className="'o_group_col_' + item.size"/>
</t>
</div>
<div class="o_group row g-2 gx-lg-5 align-items-start" t-attf-class="{{ allClasses }} {{ props.hasOuterTemplate and props.class ? '' : 'my-3' }}" t-att-style="props.style">
<t t-slot="title" t-if="props.slots.title" />
<t t-foreach="getItems()" t-as="item" t-key="item_index">
<span class="o_newline" t-if="item.newline" />
<t t-slot="{{ item.name }}" className="item.colspan !== props.maxCols ? 'col-lg-' + item.size : ''"/>
</t>
</div>
</t>
<t t-name="web.Form.InnerGroup" owl="1">
<table t-attf-class="{{ allClasses }}" class="o_inner_group o_group" t-if="props.slots" t-att-style="props.style">
<tbody>
<td t-if="props.slots.title" t-attf-colspan="{{ props.maxCols }}" style="width: 100%">
<t t-slot="title" />
</td>
<tr t-foreach="getRows()" t-as="row" t-key="row_index">
<t t-foreach="row" t-as="cell" t-key="cell_index" >
<div t-attf-class="{{ allClasses }}" class="o_inner_group grid" t-if="props.slots" t-att-style="props.style">
<div t-if="props.slots.title" t-attf-class="g-col-sm-{{ props.maxCols }}">
<t t-slot="title" />
</div>
<div t-foreach="getRows()" t-as="row" t-key="row_index" class="o_wrap_field d-flex d-sm-contents flex-column mb-3 mb-sm-0" t-if="row.isVisible">
<t t-foreach="row" t-as="cell" t-key="cell_index">
<t t-if="cell.subType === 'item_component'" >
<td class="o_td_label">
<t t-component="cell.Component" t-if="cell.isVisible" t-props="cell.props" />
</td>
<td t-att-colspan="cell.itemSpan -1 > 1 ? cell.itemSpan - 1 : undefined" t-attf-style="{{ cell.width ? 'width: ' + cell.width + '%' : undefined }}">
<t t-if="cell.isVisible" t-slot="{{ cell.name }}" />
</td>
</t>
<t t-if="cell.subType === 'item_component'">
<div class="o_cell o_wrap_label flex-grow-1 flex-sm-grow-0 w-100 text-break text-900">
<t t-component="cell.Component" t-if="cell.isVisible" t-props="cell.props"/>
</div>
<div
class="o_cell o_wrap_input flex-grow-1 flex-sm-grow-0"
t-attf-style="{{ cell.itemSpan -1 > 1 ? 'grid-column: span ' + (cell.itemSpan -1) + ';' : '' }}{{ cell.width ? 'width: ' + cell.width + '%' + ';' : '' }}"
>
<t t-slot="{{ cell.name }}" />
</div>
</t>
<t t-else="">
<td t-attf-class="{{ cell.subType === 'label' ? 'o_td_label' : null }}" t-attf-colspan="{{ cell.itemSpan > 1 ? cell.itemSpan : undefined }}"
t-attf-style="{{ cell.width ? 'width: ' + cell.width + '%' : undefined }}">
<t t-if="cell.isVisible" t-slot="{{ cell.name }}" />
</td>
</t>
<t t-else="">
<div
class="o_cell flex-grow-1 flex-sm-grow-0"
t-attf-style="{{ cell.itemSpan > 1 ? 'grid-column: span ' + cell.itemSpan + ';' : '' }}{{ cell.width ? 'width: ' + cell.width + '%' + ';' : '' }}"
t-attf-class="{{ cell.subType === 'label' ? 'o_wrap_label w-100 text-break text-900' : null }}"
t-if="cell.isVisible">
<t t-slot="{{ cell.name }}" />
</div>
</t>
</t>
</tr>
</tbody>
</table>
</div>
</div>
</t>
</templates>
@@ -5429,7 +5429,7 @@ QUnit.module("Fields", (hooks) => {
await click(target.querySelector(".modal-footer button.btn-primary"));
assert.containsOnce(target, ".modal");
assert.containsOnce(target, ".modal tbody label.o_field_invalid");
assert.containsOnce(target, ".modal label.o_field_invalid");
});
QUnit.test("one2many list with action button", async function (assert) {
@@ -919,7 +919,7 @@ QUnit.module("Fields", (hooks) => {
</form>`,
});
const groups = target.querySelectorAll(".o_group");
const groups = target.querySelectorAll(".o_inner_group");
assert.containsNone(
groups[0],
@@ -276,7 +276,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_field_char input");
assert.strictEqual(target.querySelector(".o_field_char input").value, "blip");
assert.hasAttrValue(
target.querySelector(".o_group .o_group"),
target.querySelector(".o_group .o_inner_group"),
"style",
"background-color: red",
"should apply style attribute on groups"
@@ -292,7 +292,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, "div.o_field_one2many table");
assert.containsOnce(
target,
"tbody td:not(.o_list_record_selector) .o-checkbox input:checked"
"div.o_cell:not(.o_list_record_selector) .o-checkbox input:checked"
);
assert.containsNone(target, "label.o_form_label_empty:contains(timmy)");
});
@@ -825,7 +825,7 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
assert.containsOnce(target, "table.o_inner_group");
assert.containsOnce(target, "div.o_inner_group");
});
QUnit.test("group containing both a field and a group", async function (assert) {
@@ -854,7 +854,7 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_group .o_inner_group .o_field_widget[name=int_field]");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_field_char");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_group_col_6");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "col-lg-6");
});
QUnit.test("Form and subview with _view_ref contexts", async function (assert) {
@@ -1035,8 +1035,8 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_form_statusbar button:contains(coucou)");
assert.containsOnce(target, ".o_notebook li a:contains(visible)");
assert.containsNone(target, ".o_notebook li a:contains(invisible)");
assert.containsOnce(target, "table.o_inner_group td:contains(visgroup)");
assert.containsNone(target, "table.o_inner_group td:contains(invgroup)");
assert.containsOnce(target, "div.o_inner_group:contains(visgroup)");
assert.containsNone(target, "div.o_inner_group:contains(invgroup)");
});
QUnit.test(
@@ -3962,18 +3962,18 @@ QUnit.module("Views", (hooks) => {
);
assert.hasAttrValue(
target.querySelector(".firstgroup td"),
"colspan",
target.querySelector(".firstgroup div"),
"style",
undefined,
"foo td should have a default colspan (1)"
"foo div should have a default colspan (1)"
);
assert.containsN(target, ".secondgroup tr", 2, "int_field and qux should have same tr");
assert.containsN(target, ".secondgroup div.o_wrap_field", 2, "int_field and qux should have same o_wrap_field");
assert.containsN(
target,
".secondgroup tr:first td",
".secondgroup div.o_wrap_field:first div.o_cell",
2,
"product_id field should be on its own tr"
"product_id field should be on its own o_wrap_field"
);
});
@@ -4867,8 +4867,8 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
assert.hasClass(target.querySelector(".inner_group"), "o_group_col_6");
assert.hasClass(target.querySelector(".inner_div"), "o_group_col_6");
assert.hasClass(target.querySelector(".inner_group"), "col-lg-6");
assert.hasClass(target.querySelector(".inner_div"), "col-lg-6");
});
QUnit.test("deleting a record", async function (assert) {
@@ -7804,10 +7804,10 @@ QUnit.module("Views", (hooks) => {
// Verify outergroup/innergroup
assert.strictEqual($parentGroup[0].tagName, "DIV", ".parent_group should be an outergroup");
assert.strictEqual($group4[0].tagName, "TABLE", ".group_4 should be an innergroup");
assert.strictEqual($group4[0].tagName, "DIV", ".group_4 should be an innergroup");
assert.strictEqual($group3[0].tagName, "DIV", ".group_3 should be an outergroup");
assert.strictEqual($group1[0].tagName, "TABLE", ".group_1 should be an innergroup");
assert.strictEqual($fieldGroup[0].tagName, "TABLE", ".field_group should be an innergroup");
assert.strictEqual($group1[0].tagName, "DIV", ".group_1 should be an innergroup");
assert.strictEqual($fieldGroup[0].tagName, "DIV", ".field_group should be an innergroup");
// Verify .parent_group content
var $parentGroupChildren = $parentGroup.children();
@@ -7817,174 +7817,131 @@ QUnit.module("Views", (hooks) => {
"there should be 2 groups in .parent_group"
);
assert.ok(
$parentGroupChildren.eq(0).is(".o_group_col_6"),
$parentGroupChildren.eq(0).is(".col-lg-6"),
"first .parent_group group should be 1/2 parent width"
);
assert.ok(
$parentGroupChildren.eq(1).is(".o_group_col_8"),
"second .parent_group group should be 2/3 parent width"
$parentGroupChildren.eq(1).is(".col-lg-8"),
"second .parent_group group should be 3/4 parent width"
);
// Verify .group_4 content
var $group4rows = $group4.find("> tbody > tr");
var $group4rows = $group4.find("> div.o_wrap_field");
assert.strictEqual($group4rows.length, 3, "there should be 3 rows in .group_4");
var $group4firstRowTd = $group4rows.eq(0).children("td");
assert.strictEqual($group4firstRowTd.length, 1, "there should be 1 td in first row");
assert.hasAttrValue($group4firstRowTd, "colspan", "3", "the first td colspan should be 3");
var $group4firstRowTd = $group4rows.eq(0).children("div.o_cell");
assert.strictEqual($group4firstRowTd.length, 1, "there should be 1 cell in first row");
assert.strictEqual($group4firstRowTd.attr("style").substr(0, 19), "grid-column: span 3", "the first cell column span should be 3");
assert.strictEqual(
$group4firstRowTd.attr("style").substr(0, 9),
"width: 75",
"the first td should be 75% width"
$group4firstRowTd.attr("style").substr(0, 19),
"grid-column: span 3",
"the first cell should be 75% width"
);
assert.strictEqual(
$group4firstRowTd.children()[0].tagName,
"DIV",
"the first td should contain a div"
);
var $group4secondRowTds = $group4rows.eq(1).children("td");
assert.strictEqual($group4secondRowTds.length, 2, "there should be 2 tds in second row");
assert.hasAttrValue(
$group4secondRowTds.eq(0),
"colspan",
"2",
"the first td colspan should be 2"
"the first cell should contain a div"
);
var $group4secondRowTds = $group4rows.eq(1).children("div.o_cell");
assert.strictEqual($group4secondRowTds.length, 2, "there should be 2 cells in second row");
assert.strictEqual(
$group4secondRowTds.eq(0).attr("style").substr(0, 9),
"width: 50",
"the first td be 50% width"
);
assert.hasAttrValue(
$group4secondRowTds.eq(1),
"colspan",
undefined,
"the second td colspan should be default one (1)"
$group4secondRowTds.attr("style").substr(0, 29),
"grid-column: span 2;width: 50",
"the first cell colspan should be 2 and be 50% width"
);
assert.strictEqual(
$group4secondRowTds.eq(1).attr("style").substr(0, 9),
"width: 25",
"the second td be 75% width"
"the second cell colspan should be default one (no style) and be 25% width"
);
var $group4thirdRowTd = $group4rows.eq(2).children("td");
assert.strictEqual($group4thirdRowTd.length, 1, "there should be 1 td in third row");
assert.hasAttrValue($group4thirdRowTd, "colspan", "4", "the first td colspan should be 4");
var $group4thirdRowTd = $group4rows.eq(2).children(".o_cell");
assert.strictEqual($group4thirdRowTd.length, 1, "there should be 1 cell in third row");
assert.strictEqual(
$group4thirdRowTd.attr("style").substr(0, 10),
"width: 100",
"the first td should be 100% width"
$group4thirdRowTd.attr("style").substr(0, 30),
"grid-column: span 4;width: 100",
"the first cell colspan should be 4 and be 100% width"
);
// Verify .group_3 content
assert.strictEqual($group3.children().length, 3, ".group_3 should have 3 children");
assert.strictEqual(
$group3.children(".o_group_col_4").length,
$group3.children(".col-lg-4").length,
3,
".group_3 should have 3 children of 1/3 width"
);
// Verify .group_1 content
assert.strictEqual(
$group1.find("> tbody > tr").length,
$group1.find("> .o_wrap_field").length,
3,
"there should be 3 rows in .group_1"
);
// Verify .field_group content
var $fieldGroupRows = $fieldGroup.find("> tbody > tr");
assert.strictEqual($fieldGroupRows.length, 5, "there should be 5 rows in .field_group");
var $fieldGroupFirstRowTds = $fieldGroupRows.eq(0).children("td");
assert.strictEqual($fieldGroupFirstRowTds.length, 2, "there should be 2 tds in first row");
var $fieldGroupRows = $fieldGroup.find("> .o_wrap_field");
assert.strictEqual($fieldGroupRows.length, 5, "there should be 5 rows in .o_wrap_field");
var $fieldGroupFirstRowTds = $fieldGroupRows.eq(0).children(".o_cell");
assert.strictEqual($fieldGroupFirstRowTds.length, 2, "there should be 2 cells in first row");
assert.hasClass(
$fieldGroupFirstRowTds.eq(0),
"o_td_label",
"first td should be a label td"
);
assert.hasAttrValue(
$fieldGroupFirstRowTds.eq(1),
"colspan",
"2",
"second td colspan should be given colspan (3) - 1 (label)"
"o_wrap_label",
"first cell should be a label cell"
);
assert.strictEqual(
$fieldGroupFirstRowTds.eq(1).attr("style").substr(0, 10),
"width: 100",
"second td width should be 100%"
$fieldGroupFirstRowTds.eq(1).attr("style").substr(0, 30),
"grid-column: span 2;width: 100",
"second cell colspan should be given colspan (3) - 1 (label) and be 100%"
);
var $fieldGroupSecondRowTds = $fieldGroupRows.eq(1).children("td");
var $fieldGroupSecondRowTds = $fieldGroupRows.eq(1).children(".o_cell");
assert.strictEqual(
$fieldGroupSecondRowTds.length,
2,
"there should be 2 tds in second row"
);
assert.hasAttrValue(
$fieldGroupSecondRowTds.eq(0),
"colspan",
undefined,
"first td colspan should be default one (1)"
"there should be 2 cells in second row"
);
assert.strictEqual(
$fieldGroupSecondRowTds.eq(0).attr("style").substr(0, 9),
"width: 33",
"first td width should be 33.3333%"
);
assert.hasAttrValue(
$fieldGroupSecondRowTds.eq(1),
"colspan",
undefined,
"second td colspan should be default one (1)"
"first cell colspan should be default one (no style) and be 33.3333%"
);
assert.strictEqual(
$fieldGroupSecondRowTds.eq(1).attr("style").substr(0, 9),
"width: 33",
"second td width should be 33.3333%"
"second cell colspan should be default one (no style) and be 33.3333%"
);
var $fieldGroupThirdRowTds = $fieldGroupRows.eq(2).children("td"); // new row as label/field pair colspan is greater than remaining space
assert.strictEqual($fieldGroupThirdRowTds.length, 2, "there should be 2 tds in third row");
var $fieldGroupThirdRowTds = $fieldGroupRows.eq(2).children(".o_cell"); // new row as label/field pair colspan is greater than remaining space
assert.strictEqual($fieldGroupThirdRowTds.length, 2, "there should be 2 cells in third row");
assert.hasClass(
$fieldGroupThirdRowTds.eq(0),
"o_td_label",
"first td should be a label td"
);
assert.hasAttrValue(
$fieldGroupThirdRowTds.eq(1),
"colspan",
undefined,
"second td colspan should be default one (1)"
"o_wrap_label",
"first cell should be a label cell"
);
assert.strictEqual(
$fieldGroupThirdRowTds.eq(1).attr("style").substr(0, 9),
"width: 50",
"second td should be 50% width"
);
var $fieldGroupFourthRowTds = $fieldGroupRows.eq(3).children("td");
assert.strictEqual($fieldGroupFourthRowTds.length, 1, "there should be 1 td in fourth row");
assert.hasAttrValue(
$fieldGroupFourthRowTds,
"colspan",
"3",
"the td should have a colspan equal to 3"
"second cell colspan should be default one (no style) and be 50% width"
);
var $fieldGroupFourthRowTds = $fieldGroupRows.eq(3).children(".o_cell");
assert.strictEqual($fieldGroupFourthRowTds.length, 1, "there should be 1 cell in fourth row");
assert.strictEqual(
$fieldGroupFourthRowTds.attr("style").substr(0, 10),
"width: 100",
"the td should have 100% width"
$fieldGroupFourthRowTds.attr("style").substr(0, 30),
"grid-column: span 3;width: 100",
"the cell should have a colspan equal to 3 and have 100% width"
);
var $fieldGroupFifthRowTds = $fieldGroupRows.eq(4).children("td"); // label/field pair can be put after the 1-colspan span
assert.strictEqual($fieldGroupFifthRowTds.length, 3, "there should be 3 tds in fourth row");
var $fieldGroupFifthRowTds = $fieldGroupRows.eq(4).children(".o_cell"); // label/field pair can be put after the 1-colspan span
assert.strictEqual($fieldGroupFifthRowTds.length, 3, "there should be 3 cells in fourth row");
assert.strictEqual(
$fieldGroupFifthRowTds.eq(0).attr("style").substr(0, 9),
"width: 50",
"the first td should 50% width"
"the first cell should 50% width"
);
assert.hasClass(
$fieldGroupFifthRowTds.eq(1),
"o_td_label",
"the second td should be a label td"
"o_wrap_label",
"the second cell should be a label cell"
);
assert.strictEqual(
$fieldGroupFifthRowTds.eq(2).attr("style").substr(0, 9),
"width: 50",
"the third td should 50% width"
"the third cell should 50% width"
);
});
@@ -8012,10 +7969,10 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
const rows = document.querySelectorAll(".o_inner_group tr");
assert.containsOnce(rows[0], "> td", "Should only contain one cell");
const rows = document.querySelectorAll(".o_inner_group > div");
assert.containsOnce(rows[0], "> .o_cell", "Should only contain one cell");
assert.containsOnce(rows[0], ".o_horizontal_separator");
assert.containsN(rows[1], "> td", 2, "Should contain 2 cells");
assert.containsN(rows[1], "> .o_cell", 2, "Should contain 2 cells");
assert.containsOnce(rows[1], "label[for=display_name]");
assert.containsOnce(rows[1], "div[name=display_name]");
}
@@ -8045,7 +8002,7 @@ QUnit.module("Views", (hooks) => {
var $parentGroup = $(target.querySelector(".parent_group"));
var $group1 = $(target.querySelector(".group_1"));
var $group2 = $(target.querySelector(".group_2"));
assert.containsN(target, "table.o_inner_group", 2, "should contain two inner groups");
assert.containsN(target, "div.o_inner_group", 2, "should contain two inner groups");
assert.strictEqual(
$group1.find(".o_horizontal_separator").length,
1,
@@ -8089,7 +8046,7 @@ QUnit.module("Views", (hooks) => {
<group col="3">
<!-- col=3 otherwise the test is ok even without the
newline code as this will render a <newline/> DOM
element with the o_group_col_6 class, leaving no
element with the g-col-2 class, leaving no
place for the next group on the same line. -->
<group class="top_group">
<div style="height: 200px;"/>
@@ -8107,29 +8064,29 @@ QUnit.module("Views", (hooks) => {
// Inner group
assert.containsN(
target,
".main_inner_group > tbody > tr",
".main_inner_group > .o_wrap_field",
2,
"there should be 2 rows in the group"
);
assert.containsOnce(
target,
".main_inner_group > tbody > tr:first > .o_td_label",
".main_inner_group > .o_wrap_field:first > .o_wrap_label",
"there should be only one label in the first row"
);
assert.containsOnce(
target,
".main_inner_group > tbody > tr:first .o_field_widget",
".main_inner_group > .o_wrap_field:first .o_field_widget",
"there should be only one widget in the first row"
);
assert.containsN(
target,
".main_inner_group > tbody > tr:last > .o_td_label",
".main_inner_group > .o_wrap_field:last > .o_wrap_label",
2,
"there should be two labels in the second row"
);
assert.containsN(
target,
".main_inner_group > tbody > tr:last .o_field_widget",
".main_inner_group > .o_wrap_field:last .o_field_widget",
2,
"there should be two widgets in the second row"
);