[IMP] web: highlight searchValue in CommandItem

With this commit, when you perform a search in the command palette,
the part of the commandItem's name that matches the searchValue will
be highlighted.

closes odoo/odoo#82407

Task-id: 2741837
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2022-01-21 09:40:50 +00:00
parent f052624c97
commit 6daa9188cb
8 changed files with 152 additions and 33 deletions
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="web.DefaultCommandItem" owl="1">
<div class="o_command_default">
<t t-slot="name"/>
</div>
</t>
<t t-name="web.HotkeyCommandItem" owl="1">
<div class="o_command_hotkey">
<t t-slot="name"/>
<span>
<t t-foreach="getKeysToPress(props)" t-as="key">
<kbd t-esc="key" />
<span t-if="!key_last"> + </span>
</t>
</span>
</div>
</t>
</templates>
@@ -1,12 +1,13 @@
/** @odoo-module **/
import { useAutofocus, useService } from "@web/core/utils/hooks";
import { useHotkey } from "@web/core/hotkeys/hotkey_hook";
import { _lt } from "@web/core/l10n/translation";
import { KeepLast } from "@web/core/utils/concurrency";
import { useAutofocus, useService } from "@web/core/utils/hooks";
import { scrollTo } from "@web/core/utils/scrolling";
import { fuzzyLookup } from "@web/core/utils/search";
import { debounce } from "@web/core/utils/timing";
import { _lt } from "@web/core/l10n/translation";
import { escapeRegExp } from "../utils/strings";
const { Component, onWillStart, useRef, useState } = owl;
@@ -59,6 +60,11 @@ function commandsWithinCategory(categoryName, categories) {
};
}
function splitCommandName(name, searchValue) {
const splitName = name.split(new RegExp(`(${escapeRegExp(searchValue)})`, "ig"));
return searchValue.length && splitName.length > 1 ? splitName : [name];
}
export class DefaultCommandItem extends Component {}
DefaultCommandItem.template = "web.DefaultCommandItem";
@@ -175,11 +181,13 @@ export class CommandPalette extends Component {
this.state.commands = commands.map((command) => ({
...command,
keyId: this.keyId++,
splitName: splitCommandName(command.name, options.searchValue),
}));
this.selectCommand(this.state.commands.length ? 0 : -1);
this.mouseSelectionActive = false;
this.state.emptyMessage =
this.emptyMessageByNamespace[namespace] || DEFAULT_EMPTY_MESSAGE.toString();
this.clearSearchValue = options.searchValue;
}
selectCommand(index) {
@@ -91,6 +91,12 @@
}
}
.o_command_name {
> b {
color: $o-brand-primary;
}
}
.o_app_icon {
position: relative;
border-radius: 4%;
@@ -17,7 +17,16 @@
<t t-foreach="category.commands" t-as="command">
<t t-set="commandIndex" t-value="state.commands.indexOf(command)" />
<div t-attf-id="o_command_{{commandIndex}}" class="o_command" t-att-class="{ focused: state.selectedCommand === command }" t-on-click="onCommandClicked(commandIndex)" t-on-mouseenter="onCommandMouseEnter(commandIndex)" t-key="command.keyId">
<t t-component="command.Component || DefaultCommandItem" name="command.name" t-props="command.props" t-on-close="props.closeMe()" t-on-execute-command="executeCommand(command)"/>
<t t-component="command.Component || DefaultCommandItem" name="command.name" searchValue="clearSearchValue" t-props="command.props" t-on-close="props.closeMe()" t-on-execute-command="executeCommand(command)">
<t t-set-slot="name">
<span class="o_command_name">
<t t-foreach="command.splitName" t-as="name" t-key="name_index">
<b t-if="name_index % 2" t-esc="name"/>
<t t-else="" t-esc="name"/>
</t>
</span>
</t>
</t>
</div>
</t>
</div>
@@ -35,32 +44,4 @@
</div>
</t>
<t t-name="web.DefaultCommandItem" owl="1">
<div class="o_command_default">
<span t-esc="props.name" />
</div>
</t>
<t t-name="web.HotkeyCommandItem" owl="1">
<div class="o_command_hotkey">
<span t-esc="props.name" />
<span>
<t t-foreach="getKeysToPress(props)" t-as="key">
<kbd t-esc="key" />
<span t-if="!key_last"> + </span>
</t>
</span>
</div>
</t>
<t t-name="web.AppIconCommand" owl="1">
<div class="o_command_default">
<span t-esc="props.name"/>
<img t-if="props.webIconData" class="o_app_icon" t-attf-src="{{props.webIconData}}"/>
<div t-else="" class="o_app_icon" t-attf-style="background-color:{{props.webIcon.backgroundColor}}" >
<i t-att-class="props.webIcon.iconClass" t-attf-style="color:{{props.webIcon.color}}"></i>
</div>
</div>
</t>
</templates>