[IMP] account,web: SearchPanel: move carets to the left
In this commit, hierarchy carets in the search panel have been moved to the left side of the labels. To achieve a consistent and correct alignment, some DOM elements have been added/moved and the related SCSS sheets have been adapted. Carets on filter sections of the search panel have also been removed. Task 2258508
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
.o_search_panel.account_root {
|
||||
flex: 0 0 48px;
|
||||
flex: 0 0 50px;
|
||||
padding: 6px;
|
||||
scrollbar-width: thin;
|
||||
.o_search_panel_section_header {
|
||||
@@ -8,9 +8,14 @@
|
||||
.list-group-item span.o_search_panel_label_title {
|
||||
display: contents;
|
||||
}
|
||||
.o_search_panel_category_value header {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
.o_search_panel_category_value {
|
||||
header {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.o_search_panel_category_value .o_toggle_fold_container {
|
||||
width: 0.3rem;
|
||||
}
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
|
||||
@@ -67,10 +67,9 @@ const SearchPanel = Widget.extend({
|
||||
className: 'o_search_panel',
|
||||
events: {
|
||||
'click .o_search_panel_category_value header': '_onCategoryValueClicked',
|
||||
'click .o_search_panel_category_value .o_toggle_fold': '_onToggleFoldCategory',
|
||||
'click .o_search_panel_filter_group .o_toggle_fold': '_onToggleFoldFilterGroup',
|
||||
'change .o_search_panel_filter_value > div > input': '_onFilterValueChanged',
|
||||
'change .o_search_panel_filter_group > div > input': '_onFilterGroupChanged',
|
||||
'click .o_search_panel_category_value .o_toggle_fold_container': '_onToggleFoldCategory',
|
||||
'change .o_search_panel_filter_value > header > div > input': '_onFilterValueChanged',
|
||||
'change .o_search_panel_filter_group > header > div > input': '_onFilterGroupChanged',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -783,19 +782,6 @@ const SearchPanel = Widget.extend({
|
||||
category.values[valueId].folded = !category.values[valueId].folded;
|
||||
this._render();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onToggleFoldFilterGroup(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
const item = ev.currentTarget.closest('.o_search_panel_filter_group');
|
||||
const filter = this.filters[item.dataset.filterId];
|
||||
const groupId = item.dataset.groupId;
|
||||
filter.groups[groupId].folded = !filter.groups[groupId].folded;
|
||||
this._render();
|
||||
},
|
||||
});
|
||||
|
||||
return SearchPanel;
|
||||
|
||||
@@ -27,48 +27,51 @@ $o-searchpanel-filter-default-color: #D59244;
|
||||
.o_search_panel_category .o_search_panel_section_icon {
|
||||
color: $o-brand-odoo;
|
||||
}
|
||||
|
||||
.o_search_panel_filter .o_search_panel_section_icon {
|
||||
color: $o-searchpanel-filter-default-color;
|
||||
}
|
||||
|
||||
.o_toggle_fold_container {
|
||||
text-align: center;
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.o_search_panel_label {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
user-select: none;
|
||||
|
||||
// Without counters: the caret is set at the right border
|
||||
&:not(.o_with_counters) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.o_toggle_fold {
|
||||
width: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.o_search_panel_section_header {
|
||||
padding: $o-searchpanel-p-small 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-bottom: $o-searchpanel-p-tiny;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
padding: 0 0 $o-searchpanel-p-small 0;
|
||||
padding: 0;
|
||||
|
||||
.list-group-item {
|
||||
padding: 0 0 0 $custom-control-gutter;
|
||||
margin-bottom: $o-searchpanel-p-tiny*0.5;
|
||||
&:first-child {
|
||||
margin-top: $o-searchpanel-p-tiny*0.5;
|
||||
}
|
||||
}
|
||||
|
||||
span.o_search_panel_label_title {
|
||||
color: $headings-color;
|
||||
@include o-text-overflow;
|
||||
}
|
||||
|
||||
header.active {
|
||||
background-color: $o-searchpanel-active-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.o_search_panel_category_value {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -76,9 +79,7 @@ $o-searchpanel-filter-default-color: #D59244;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: -4px;
|
||||
margin-bottom: -4px;
|
||||
padding: 4px 6px;
|
||||
padding: 4px 6px 4px 0px;
|
||||
}
|
||||
.o_search_panel_label.o_with_counters {
|
||||
overflow: hidden;
|
||||
@@ -86,7 +87,6 @@ $o-searchpanel-filter-default-color: #D59244;
|
||||
.o_search_panel_category_value {
|
||||
position: relative;
|
||||
padding-left: $o-searchpanel-p;
|
||||
padding-bottom: $o-searchpanel-p-tiny;
|
||||
margin-bottom: 0;
|
||||
|
||||
&:before, &:after {
|
||||
@@ -94,23 +94,34 @@ $o-searchpanel-filter-default-color: #D59244;
|
||||
@include size(1px, 100%);
|
||||
background: $gray-500;
|
||||
content: '';
|
||||
margin-left: 4px;
|
||||
}
|
||||
&:after {
|
||||
top: 10px;
|
||||
top: 12px;
|
||||
@include size(8px, 1px);
|
||||
}
|
||||
&:last-child {
|
||||
&:before {
|
||||
height: 11px;
|
||||
}
|
||||
&:after {
|
||||
top: 11px;
|
||||
}
|
||||
&:last-child:before {
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_search_panel_filter_value,
|
||||
.o_search_panel_filter_group {
|
||||
padding-right: 6px;
|
||||
cursor: pointer;
|
||||
padding-bottom: $o-searchpanel-p-small;
|
||||
|
||||
.o_search_panel_label,
|
||||
.o_search_panel_label_title {
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_search_panel_filter_group {
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.o_search_panel_label.o_with_counters {
|
||||
justify-content: flex-start;
|
||||
|
||||
@@ -225,7 +225,8 @@
|
||||
<ul class="list-group d-block o_search_panel_field" t-att-data-field-name="category.fieldName">
|
||||
<li class="o_search_panel_category_value border-0 list-group-item" t-att-data-category-id="category.id">
|
||||
<header t-att-class="'list-group-item-action' + (!category.activeValueId ? ' active' : '')">
|
||||
<label class="o_search_panel_label mb0 d-block">
|
||||
<label class="o_search_panel_label mb0">
|
||||
<div class="o_toggle_fold_container"/>
|
||||
<span class="o_search_panel_label_title"><b>All</b></span>
|
||||
</label>
|
||||
</header>
|
||||
@@ -245,16 +246,18 @@
|
||||
<t t-set="value" t-value="category.values[valueId]"/>
|
||||
<li class="o_search_panel_category_value border-0 list-group-item" t-att-data-id="value.id" t-att-data-category-id="category.id">
|
||||
<header t-att-class="'list-group-item-action' + (value.id === category.activeValueId ? ' active' : '')">
|
||||
<label t-att-for="value.display_name" t-attf-class="o_search_panel_label mb0{{ category.disableCounters ? '' : ' o_with_counters' }}">
|
||||
<label t-attf-class="o_search_panel_label mb0{{ category.disableCounters ? '' : ' o_with_counters' }}">
|
||||
<div class="o_toggle_fold_container">
|
||||
<i t-if="value.childrenIds.length" t-attf-class="o_toggle_fold fa fa-caret-{{ value.folded ? 'right' : 'down' }}"/>
|
||||
</div>
|
||||
<span class="o_search_panel_label_title"><t t-esc="value.display_name"/></span>
|
||||
<i t-if="value.childrenIds.length" t-attf-class="o_toggle_fold fa fa-fw fa-caret-{{ value.folded ? 'right' : 'down' }}"/>
|
||||
</label>
|
||||
<span t-if="!category.disableCounters and value.__count > 0"
|
||||
class="text-muted ml-2 small"
|
||||
t-esc="value.__count"
|
||||
/>
|
||||
</header>
|
||||
<ul t-if="!value.folded" class="list-group d-block">
|
||||
<ul t-if="!value.folded and value.childrenIds.length" class="list-group d-block">
|
||||
<t t-call="SearchPanel.CategoryValues">
|
||||
<t t-set="values" t-value="value.childrenIds"/>
|
||||
</t>
|
||||
@@ -286,17 +289,18 @@
|
||||
<li t-foreach="filter.sortedGroupIds" t-as="groupId" t-att-data-group-id="groupId" t-att-data-filter-id="filter.id"
|
||||
class="o_search_panel_filter_group list-group-item border-0">
|
||||
<t t-set="group" t-value="groups[groupId]"/>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<t t-set="inputId" t-value="_.uniqueId('input_')"/>
|
||||
<input type="checkbox" t-att-id="inputId" t-att-checked="group.state === 'checked' ? 'checked' : undefined" class="custom-control-input"/>
|
||||
<label t-att-for="inputId" t-attf-class="o_search_panel_label custom-control-label{{ group.disableCounters ? '' : ' o_with_counters' }}" t-att-title="group.tooltip">
|
||||
<span class="o_search_panel_label_title">
|
||||
<span t-if="group.hex_color" t-attf-style="color: {{ group.hex_color }};">●</span>
|
||||
<t t-esc="group.name"/>
|
||||
</span>
|
||||
<i t-attf-class="o_toggle_fold fa fa-fw fa-caret-{{ group.folded ? 'right' : 'down' }}"/>
|
||||
</label>
|
||||
</div>
|
||||
<t t-set="inputId" t-value="_.uniqueId('input_')"/>
|
||||
<header class="o_search_panel_group_header">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" t-att-id="inputId" t-att-checked="group.state === 'checked' ? 'checked' : undefined" class="custom-control-input"/>
|
||||
<label t-att-for="inputId" t-attf-class="o_search_panel_label custom-control-label{{ group.disableCounters ? '' : ' o_with_counters' }}" t-att-title="group.tooltip">
|
||||
<span class="o_search_panel_label_title">
|
||||
<span t-if="group.hex_color" t-attf-style="color: {{ group.hex_color }};">●</span>
|
||||
<t t-esc="group.name"/>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</header>
|
||||
<ul t-if="!group.folded" class="list-group d-block">
|
||||
<t t-call="SearchPanel.FilterValues">
|
||||
<t t-set="sortedValueIds" t-value="group.sortedValueIds"/>
|
||||
@@ -316,17 +320,19 @@
|
||||
<li t-foreach="sortedValueIds" t-as="valueId" t-att-data-value-id="valueId" t-att-data-filter-id="filter.id"
|
||||
class="o_search_panel_filter_value list-group-item border-0">
|
||||
<t t-set="value" t-value="values[valueId]"/>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<t t-set="inputId" t-value="_.uniqueId('input_')"/>
|
||||
<input type="checkbox" t-att-id="inputId" t-att-checked="value.checked ? 'checked' : undefined" class="custom-control-input"/>
|
||||
<label t-att-for="inputId" class="o_search_panel_label custom-control-label" t-att-title="group && group.tooltip">
|
||||
<span class="o_search_panel_label_title" t-esc="value.display_name"/>
|
||||
<span t-if="!filter.disableCounters and value.__count > 0"
|
||||
class="text-muted ml-2 small"
|
||||
t-esc="value.__count"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<t t-set="inputId" t-value="_.uniqueId('input_')"/>
|
||||
<header class="o_search_panel_group_header">
|
||||
<div class="custom-control custom-checkbox w-100">
|
||||
<input type="checkbox" t-att-id="inputId" t-att-checked="value.checked ? 'checked' : undefined" class="custom-control-input"/>
|
||||
<label t-att-for="inputId" class="o_search_panel_label custom-control-label" t-att-title="group && group.tooltip">
|
||||
<span class="o_search_panel_label_title" t-esc="value.display_name"/>
|
||||
<span t-if="!filter.disableCounters and value.__count > 0"
|
||||
class="text-muted ml-2 small"
|
||||
t-esc="value.__count"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</header>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -1746,7 +1746,7 @@ QUnit.module('Views', {
|
||||
assert.containsOnce(kanban, '.o_search_panel_filter_group:first .o_search_panel_filter_value');
|
||||
assert.containsN(kanban, '.o_search_panel_filter_group:nth(1) .o_search_panel_filter_value', 2);
|
||||
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
||||
assert.strictEqual(kanban.$('.o_search_panel_filter_group > div > label').text().replace(/\s/g, ''),
|
||||
assert.strictEqual(kanban.$('.o_search_panel_filter_group > header > div > label').text().replace(/\s/g, ''),
|
||||
'goldsilver');
|
||||
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
||||
'asustek2agrolait1camptocamp');
|
||||
@@ -1756,7 +1756,7 @@ QUnit.module('Views', {
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
||||
|
||||
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
||||
var firstGroupCheckbox = kanban.$('.o_search_panel_filter_group:first > div > input').get(0);
|
||||
var firstGroupCheckbox = kanban.$('.o_search_panel_filter_group:first > header > div > input').get(0);
|
||||
assert.strictEqual(firstGroupCheckbox.checked, true,
|
||||
"first group checkbox should be checked");
|
||||
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
||||
@@ -1767,7 +1767,7 @@ QUnit.module('Views', {
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
||||
|
||||
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
|
||||
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > header > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.checked, false,
|
||||
"second group checkbox should not be checked");
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, true,
|
||||
@@ -1780,7 +1780,7 @@ QUnit.module('Views', {
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(2) input'));
|
||||
|
||||
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 3);
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > header > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.checked, true,
|
||||
"second group checkbox should be checked");
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, false,
|
||||
@@ -1790,10 +1790,10 @@ QUnit.module('Views', {
|
||||
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 0);
|
||||
|
||||
// uncheck second group
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) > div > input'));
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) > header > div > input'));
|
||||
|
||||
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > header > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.checked, false,
|
||||
"second group checkbox should not be checked");
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, false,
|
||||
@@ -1875,72 +1875,6 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('(un)fold filter group', async function (assert) {
|
||||
assert.expect(13);
|
||||
|
||||
this.data.company.records.push({id: 11, name: 'camptocamp', category_id: 7});
|
||||
|
||||
var kanban = await createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
services: this.services,
|
||||
arch: `
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div>
|
||||
<field name="foo"/>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>`,
|
||||
archs: {
|
||||
'partner,false,search': `
|
||||
<search>
|
||||
<searchpanel>
|
||||
<field select="multi" name="company_id" groupby="category_id"/>
|
||||
</searchpanel>
|
||||
</search>`,
|
||||
},
|
||||
});
|
||||
|
||||
// groups are opened by default
|
||||
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
||||
assert.containsN(kanban, '.o_search_panel_filter_value', 3);
|
||||
|
||||
// check 'agrolait'
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
||||
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
||||
assert.hasAttrValue(kanban.$('.o_search_panel_filter_value:nth(1) input'), 'checked', 'checked');
|
||||
|
||||
// fold second group
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) .o_toggle_fold'));
|
||||
|
||||
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
||||
assert.containsOnce(kanban, '.o_search_panel_filter_value');
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
||||
|
||||
// fold first group
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:first .o_toggle_fold'));
|
||||
|
||||
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
||||
assert.containsNone(kanban, '.o_search_panel_filter_value');
|
||||
|
||||
// unfold second group
|
||||
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) .o_toggle_fold'));
|
||||
|
||||
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
||||
assert.containsN(kanban, '.o_search_panel_filter_value', 2);
|
||||
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
||||
assert.hasAttrValue(kanban.$('.o_search_panel_filter_value:first input'), 'checked', 'checked');
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('filter with domain depending on category', async function (assert) {
|
||||
assert.expect(22);
|
||||
|
||||
@@ -2155,7 +2089,7 @@ QUnit.module('Views', {
|
||||
},
|
||||
});
|
||||
|
||||
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
||||
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > header > div > input').get(0);
|
||||
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
||||
|
||||
kanban.destroy();
|
||||
|
||||
Reference in New Issue
Block a user