Skip to content

Commit 096f5b1

Browse files
committed
[IMP] web: show the search panel on click and search on icon click
This commit allows users: - to click on the search icon to trigger the search (as if pressing enter) - to open the search panel by clicking on the search input. This behaviour is deactivated on touch devices. task-id 3649979 closes odoo#156319 Signed-off-by: Luca Vitali (luvi) <[email protected]>
1 parent 8910e0a commit 096f5b1

File tree

7 files changed

+71
-5
lines changed

7 files changed

+71
-5
lines changed

addons/web/static/src/search/search_bar/search_bar.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { _t } from "@web/core/l10n/translation";
99
import { SearchBarMenu } from "../search_bar_menu/search_bar_menu";
1010

1111
import { Component, useExternalListener, useRef, useState } from "@odoo/owl";
12+
import { useDropdownState } from "@web/core/dropdown/dropdown_hooks";
13+
import { hasTouch } from "@web/core/browser/feature_detection";
1214
const parsers = registry.category("parsers");
1315

1416
const CHAR_FIELDS = ["char", "html", "many2many", "many2one", "one2many", "text", "properties"];
@@ -54,6 +56,8 @@ export class SearchBar extends Component {
5456
this.items = useState([]);
5557
this.subItems = {};
5658

59+
this.searchBarDropdownState = useDropdownState();
60+
5761
this.orm = useService("orm");
5862

5963
this.keepLast = new KeepLast();
@@ -562,10 +566,19 @@ export class SearchBar extends Component {
562566
}
563567
}
564568

569+
onSearchClick() {
570+
if (!hasTouch() && !this.inputRef.el.value.length) {
571+
this.searchBarDropdownState.open();
572+
}
573+
}
574+
565575
/**
566576
* @param {InputEvent} ev
567577
*/
568578
onSearchInput(ev) {
579+
if (!hasTouch()) {
580+
this.searchBarDropdownState.close();
581+
}
569582
const query = ev.target.value;
570583
if (query.trim()) {
571584
this.computeState({ query, expanded: [], focusedIndex: 0, subItems: [] });
@@ -574,6 +587,15 @@ export class SearchBar extends Component {
574587
}
575588
}
576589

590+
onClickSearchIcon() {
591+
const focusedItem = this.items[this.state.focusedIndex];
592+
if (!this.state.query.length) {
593+
this.env.searchModel.search();
594+
} else if (focusedItem) {
595+
this.selectItem(focusedItem);
596+
}
597+
}
598+
577599
onToggleSearchBar() {
578600
this.state.showSearchBar = !this.state.showSearchBar;
579601
}

addons/web/static/src/search/search_bar/search_bar.xml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
role="searchbox"
6060
t-ref="autofocus"
6161
t-on-keydown="onSearchKeydown"
62+
t-on-click="onSearchClick"
6263
t-on-input="onSearchInput"
6364
/>
6465
</t>
@@ -95,11 +96,16 @@
9596
<div class="o_cp_searchview d-flex input-group" role="search" t-ref="root">
9697
<div class="o_searchview form-control d-print-contents d-flex align-items-center py-1 border-end-0"
9798
role="search" aria-autocomplete="list">
98-
<i class="o_searchview_icon d-print-none oi oi-search me-2"
99-
role="img"
99+
<button class="d-print-none btn border-0 p-0"
100+
role="button"
100101
aria-label="Search..."
101102
title="Search..."
102-
/>
103+
t-on-click="this.onClickSearchIcon"
104+
>
105+
<i class="o_searchview_icon oi oi-search me-2"
106+
role="img"
107+
/>
108+
</button>
103109
<div class="o_searchview_input_container d-flex flex-grow-1 flex-wrap gap-1">
104110
<t t-call="web.SearchBar.Facets"/>
105111
<t t-call="web.SearchBar.Input"/>
@@ -108,7 +114,7 @@
108114
</t>
109115
</div>
110116
</div>
111-
<SearchBarMenu>
117+
<SearchBarMenu dropdownState="searchBarDropdownState">
112118
<t t-slot="search-bar-additional-menu"/>
113119
</SearchBarMenu>
114120
</div>

addons/web/static/src/search/search_bar_menu/search_bar_menu.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ export class SearchBarMenu extends Component {
3434
default: { optional: true },
3535
},
3636
},
37+
dropdownState: {
38+
type: Object,
39+
optional: true,
40+
shape: {
41+
isOpen: Boolean,
42+
open: Function,
43+
close: Function,
44+
},
45+
},
3746
};
3847

3948
setup() {

addons/web/static/src/search/search_bar_menu/search_bar_menu.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<Dropdown menuClass="'o_search_bar_menu d-flex flex-wrap flex-lg-nowrap w-100 w-md-auto mx-md-auto mt-2 py-3'"
66
position="'bottom-end'"
77
holdOnHover="true"
8+
state="this.props.dropdownState"
89
t-if="this.env.searchModel.searchMenuTypes.size">
910
<button
1011
class="o_searchview_dropdown_toggler d-print-none btn btn-outline-secondary o-dropdown-caret rounded-start-0"

addons/web/static/tests/legacy/search/search_bar_tests.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,4 +1720,30 @@ QUnit.module("Search", (hooks) => {
17201720
assert.deepEqual(getFacetTexts(target), ["Bar is in ( First record )"]);
17211721
assert.verifySteps([`/web/domain/validate`]);
17221722
});
1723+
1724+
QUnit.test("clicking on search input trigger the search menu", async function (assert) {
1725+
await makeWithSearch({
1726+
serverData,
1727+
resModel: "partner",
1728+
Component: SearchBar,
1729+
});
1730+
await click(target, ".o_searchview_input");
1731+
assert.containsOnce(target, ".o_search_bar_menu");
1732+
});
1733+
1734+
QUnit.test("clicking on the searchview icon trigger the search", async function (assert) {
1735+
await makeWithSearch({
1736+
serverData,
1737+
resModel: "partner",
1738+
Component: SearchBar,
1739+
searchViewId: false,
1740+
});
1741+
await editSearch(target, "a");
1742+
await click(target, ".o_searchview button");
1743+
assert.strictEqual(
1744+
target.querySelector(".o_searchview_input_container .o_facet_values").innerText.trim(),
1745+
"a",
1746+
"There should be a field facet with label 'a'"
1747+
);
1748+
});
17231749
});

addons/web/static/tests/legacy/views/kanban/kanban_view_tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14231,7 +14231,7 @@ QUnit.module("Views", (hooks) => {
1423114231
const cpButtons = getVisibleButtons(target);
1423214232
assert.deepEqual(
1423314233
[...cpButtons].map((button) => button.textContent.trim()),
14234-
["New", "display", ""]
14234+
["New", "display", "", ""]
1423514235
);
1423614236
assert.hasClass(cpButtons[1], "display");
1423714237

addons/web/static/tests/legacy/views/list_view_tests.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ QUnit.module("Views", (hooks) => {
10421042
[
10431043
"New",
10441044
"display",
1045+
"", // magnifying glass btn
10451046
"", // cog dropdown
10461047
"", // search btn
10471048
]
@@ -1065,6 +1066,7 @@ QUnit.module("Views", (hooks) => {
10651066
[
10661067
"New",
10671068
"display",
1069+
"", // magnifying glass btn
10681070
"", // cog dropdown
10691071
"", // search btn
10701072
]

0 commit comments

Comments
 (0)