Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING CHANGE] Change configuration file name and refactor the matcher logic #18

Merged
merged 1 commit into from Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Expand Up @@ -98,7 +98,7 @@ frontend:

Depending on the file that you have added to [extra_module_url], you will need to add your configuration in `JSON` or `YAML` format. If you used `custom-sidebar.js` you need to provide the configuration in `JSON` format. If you have used `custom-sidebar-yaml.js` you need to provide the configuration in `YAML` format.

Add a file named `sidebar-order.json` or `sidebar-order.yaml` into your `<config directory>/www/` directory. It could be easier if you copy the [example sidebar-order.json] or the [example sidebar-order.yaml] file, delete the `id` parameter, and edit it to match your needs.
Add a file named `sidebar-config.json` or `sidebar-config.yaml` into your `<config directory>/www/` directory. It could be easier if you copy the [example sidebar-config.json] or the [example sidebar-config.yaml] file, delete the `id` parameter, and edit it to match your needs.

### Configuration options

Expand All @@ -109,14 +109,15 @@ Add a file named `sidebar-order.json` or `sidebar-order.yaml` into your `<config

#### Item properties

| Property | Type | Required | Description |
| --------- | ------- | -------- | ----------- |
| item | String | true | This is a string that will be used to match each sidebar item by its text or its `data-panel` attribute. In the case of the item text, it can be a substring such as `developer` instead of `Developer Tools`. If the `exact` property is not set, it is case insensitive. |
| Property | Type | Required | Description |
| --------- | ------- | --------- | ----------- |
| item | String | true | This is a string that will be used to match each sidebar item by its text, its `data-panel` attribute or its `href`. If the `exact` property is not set, it is case insensitive and it can be a substring such as `developer` instead of `Developer Tools` or `KITCHEN` instead of `kitchen-lights`. |
| match | String | false | This property will define which string will be used to match the `item` property. It has three possible values "text" (default) to match the text content of the element, "data-panel" to match the `data-panel` attribute of the element, or "href", to match the `href` attribute of the element |
| exact | Boolean | false | Specifies whether the `item` string match should be an exact match (`true`) or not (`false`). |
| name | String | false | Changes the name of the sidebar item |
| order | Number | false | Sets the order number of the sidebar item |
| bottom | Boolean | false | Setting this property to `true` will group the item with the bottom items (Configuration, Developer Tools, etc) |
| hide | Boolean | false | Setting this property to `true` will hide the sidebar item |
| exact | Boolean | false | Specifies whether the `item` string match should be an exact match of the item text or an exact match of the `data-panel` attribute (case sensitive) |
| href | String | false | Specifies the `href` of the sidebar item |
| target | String | false | Specifies the [target property] of the sidebar item |
| icon | String | false | Specifies the icon of the sidebar item |
Expand Down Expand Up @@ -174,6 +175,7 @@ order:
#### Notes

* All items in `config.order` should have unique `item` property
* Avoid an `item` property that could match multiple elements. If you find that an item property matches with multiple elements, try to use the `match` and `exact` properties to match the specific item that you want to match.
* The items will be ordered according to their `order` property OR in the order of appearance
* If you use the `order` property, make sure either all items (except hidden ones) have this property, or none of them (otherwise order may be messed up)
* All the items placed in the bottom will be moved to the top by default. If you want to have some items in the bottom you need to add them to the `config.order` and specify their `bottom` property on `true`.
Expand Down Expand Up @@ -291,8 +293,8 @@ order:
[extra_module_url]: https://www.home-assistant.io/integrations/frontend/#extra_module_url
[browser_mod]: https://github.com/thomasloven/hass-browser_mod
[custom-sidebar release]: https://github.com/elchininet/custom-sidebar/releases
[example sidebar-order.json]: https://raw.githubusercontent.com/elchininet/custom-sidebar/master/sidebar-order.json
[example sidebar-order.yaml]: https://raw.githubusercontent.com/elchininet/custom-sidebar/master/sidebar-order.yaml
[example sidebar-config.json]: https://raw.githubusercontent.com/elchininet/custom-sidebar/master/sidebar-config.json
[example sidebar-config.yaml]: https://raw.githubusercontent.com/elchininet/custom-sidebar/master/sidebar-config.yaml
[target property]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target
[user-agent]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
[Home Assistant's Iframe Panel feature]: https://www.home-assistant.io/integrations/panel_iframe/
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/constants/index.ts
@@ -1,5 +1,5 @@
export const NAMESPACE = 'custom-sidebar';
export const CONFIG_PATH = '/local/sidebar-order';
export const CONFIG_PATH = '/local/sidebar-config';
export const MAX_ATTEMPTS = 500;
export const RETRY_DELAY = 50;

Expand Down
39 changes: 26 additions & 13 deletions src/custom-sidebar.ts
Expand Up @@ -12,7 +12,8 @@ import {
ConfigOrderWithItem,
HomeAssistant,
PartialPanelResolver,
PaperListBox
PaperListBox,
Match
} from '@types';
import {
ELEMENT,
Expand Down Expand Up @@ -185,24 +186,36 @@ class CustomSidebar {

if (!order.length) return;

const itemsArray = Array.from(items);
const matched: Set<Element> = new Set();

const orderWithItems: ConfigOrderWithItem[] = order.map((orderItem: ConfigOrder): ConfigOrderWithItem => {
const { item, new_item, exact } = orderItem;
const { item, match, exact, new_item } = orderItem;
const itemLowerCase = item.toLocaleLowerCase();
const element = new_item
? undefined
: Array.from(items).find((element: Element): boolean => {
const text = element.querySelector(SELECTOR.ITEM_TEXT).textContent.trim();
const dataPanel = element.getAttribute(ATTRIBUTE.PANEL);
if (exact) {
return (
text === item ||
dataPanel === item
: itemsArray.find((element: Element): boolean => {
const text = match === Match.DATA_PANEL
? element.getAttribute(ATTRIBUTE.PANEL)
: (
match === Match.HREF
? element.getAttribute(ATTRIBUTE.HREF)
: element.querySelector(SELECTOR.ITEM_TEXT).textContent.trim()
);

const matchText = (
(!!exact && item === text) ||
(!exact && text.toLowerCase().includes(itemLowerCase))
);
if (matchText) {
if (matched.has(element)) {
return false;
} else {
matched.add(element);
return true;
}
}
if (dataPanel.toLocaleLowerCase() === itemLowerCase) {
return true;
}
return text.toLocaleLowerCase().includes(itemLowerCase);
return false;
});
if (element) {
element.setAttribute(ATTRIBUTE.PROCESSED, 'true');
Expand Down
9 changes: 8 additions & 1 deletion src/types/index.ts
Expand Up @@ -23,13 +23,20 @@ export interface PaperListBox extends HTMLElement {
_updateAttrForSelected: () => void;
}

export enum Match {
TEXT = 'text',
DATA_PANEL = 'data-panel',
HREF = 'href'
}

export interface ConfigItem {
item: string;
match?: `${Match}`;
exact?: boolean;
name?: string;
order?: number;
bottom?: boolean;
hide?: boolean;
exact?: boolean;
href?: string;
target?: '_self' | '_blank';
icon?: string;
Expand Down