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

Add picker for badges #21436

Merged
merged 4 commits into from
Jul 19, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions src/data/lovelace/config/badge.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { Condition } from "../../../panels/lovelace/common/validate-condition";

export interface LovelaceBadgeConfig {
type?: string;
type: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will still be a lot of configs around that won't have a type, we should deal with those so changing this type might not be wise?

[key: string]: any;
visibility?: Condition[];
}

export const defaultBadgeConfig = (entity_id: string): LovelaceBadgeConfig => ({
type: "entity",
entity: entity_id,
});
export const ensureBadgeConfig = (
config: Partial<LovelaceBadgeConfig> | string
): LovelaceBadgeConfig => {
if (typeof config === "string") {
return {
type: "entity",
entity: config,
};
}
if ("type" in config && config.type) {
return config as LovelaceBadgeConfig;
}
return {
type: "entity",
...config,
};
};
2 changes: 1 addition & 1 deletion src/data/lovelace/config/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface LovelaceBaseViewConfig {

export interface LovelaceViewConfig extends LovelaceBaseViewConfig {
type?: string;
badges?: (string | LovelaceBadgeConfig)[]; // Badge can be just an entity_id
badges?: (string | Partial<LovelaceBadgeConfig>)[]; // Badge can be just an entity_id or without type
cards?: LovelaceCardConfig[];
sections?: LovelaceSectionRawConfig[];
}
Expand Down
5 changes: 4 additions & 1 deletion src/panels/lovelace/badges/hui-entity-filter-badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ export class HuiEntityFilterBadge
const element = document.createElement("hui-badge");
element.hass = this.hass;
element.preview = this.preview;
element.config = badgeConfig;
element.config = {
type: "entity",
...badgeConfig,
};
element.load();
this._elements.push(element);
}
Expand Down
19 changes: 19 additions & 0 deletions src/panels/lovelace/common/generate-lovelace-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import {
} from "../cards/types";
import { EntityConfig } from "../entity-rows/types";
import { ButtonsHeaderFooterConfig } from "../header-footer/types";
import { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
import { EntityBadgeConfig } from "../badges/types";

const HIDE_DOMAIN = new Set([
"automation",
Expand Down Expand Up @@ -310,6 +312,23 @@ export const computeCards = (
];
};

export const computeBadges = (
_states: HassEntities,
entityIds: string[]
): LovelaceBadgeConfig[] => {
const badges: LovelaceBadgeConfig[] = [];

for (const entityId of entityIds) {
const config: EntityBadgeConfig = {
type: "entity",
entity: entityId,
};

badges.push(config);
}
return badges;
};

const computeDefaultViewStates = (
entities: HassEntities,
entityEntries: HomeAssistant["entities"]
Expand Down
41 changes: 35 additions & 6 deletions src/panels/lovelace/components/hui-badge-edit-mode.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import {
mdiContentCopy,
mdiContentCut,
mdiContentDuplicate,
mdiDelete,
mdiDotsVertical,
mdiPencil,
} from "@mdi/js";
import deepClone from "deep-clone-simple";
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
Expand All @@ -25,6 +28,7 @@ import {
parseLovelaceCardPath,
} from "../editor/lovelace-path";
import { Lovelace } from "../types";
import { ensureBadgeConfig } from "../../../data/lovelace/config/badge";

@customElement("hui-badge-edit-mode")
export class HuiBadgeEditMode extends LitElement {
Expand All @@ -46,7 +50,7 @@ export class HuiBadgeEditMode extends LitElement {
public _focused: boolean = false;

@storage({
key: "lovelaceClipboard",
key: "dashboardBadgeClipboard",
state: false,
subscribe: false,
storage: "sessionStorage",
Expand Down Expand Up @@ -134,6 +138,14 @@ export class HuiBadgeEditMode extends LitElement {
"ui.panel.lovelace.editor.edit_card.duplicate"
)}
</ha-list-item>
<ha-list-item graphic="icon">
<ha-svg-icon slot="graphic" .path=${mdiContentCopy}></ha-svg-icon>
${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")}
</ha-list-item>
<ha-list-item graphic="icon">
<ha-svg-icon slot="graphic" .path=${mdiContentCut}></ha-svg-icon>
${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")}
</ha-list-item>
<li divider role="separator"></li>
<ha-list-item graphic="icon" class="warning">
${this.hass.localize("ui.panel.lovelace.editor.edit_card.delete")}
Expand All @@ -159,18 +171,35 @@ export class HuiBadgeEditMode extends LitElement {
private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
this._duplicateCard();
this._duplicateBadge();
break;
case 1:
this._deleteCard();
this._copyBadge();
break;
case 2:
this._cutBadge();
break;
case 3:
this._deleteBadge();
break;
}
}

private _duplicateCard(): void {
private _cutBadge(): void {
this._copyBadge();
this._deleteBadge();
}

private _copyBadge(): void {
const { cardIndex } = parseLovelaceCardPath(this.path!);
const cardConfig = this._badges[cardIndex];
this._clipboard = deepClone(cardConfig);
}

private _duplicateBadge(): void {
const { cardIndex } = parseLovelaceCardPath(this.path!);
const containerPath = getLovelaceContainerPath(this.path!);
const badgeConfig = this._badges![cardIndex];
const badgeConfig = ensureBadgeConfig(this._badges![cardIndex]);
showEditBadgeDialog(this, {
lovelaceConfig: this.lovelace!.config,
saveConfig: this.lovelace!.saveConfig,
Expand All @@ -191,7 +220,7 @@ export class HuiBadgeEditMode extends LitElement {
fireEvent(this, "ll-edit-badge", { path: this.path! });
}

private _deleteCard(): void {
private _deleteBadge(): void {
fireEvent(this, "ll-delete-badge", { path: this.path! });
}

Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/components/hui-card-edit-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class HuiCardEditMode extends LitElement {
public _focused: boolean = false;

@storage({
key: "lovelaceClipboard",
key: "dashboardCardClipboard",
state: false,
subscribe: false,
storage: "sessionStorage",
Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/components/hui-card-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class HuiCardOptions extends LitElement {
@property({ type: Boolean }) public hidePosition = false;

@storage({
key: "lovelaceClipboard",
key: "dashboardCardClipboard",
state: false,
subscribe: false,
storage: "sessionStorage",
Expand Down
12 changes: 12 additions & 0 deletions src/panels/lovelace/create-element/create-badge-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ import "../badges/hui-state-label-badge";
import {
createLovelaceElement,
getLovelaceElementClass,
tryCreateLovelaceElement,
} from "./create-element-base";

const ALWAYS_LOADED_TYPES = new Set(["error", "state-label", "entity"]);
const LAZY_LOAD_TYPES = {
"entity-filter": () => import("../badges/hui-entity-filter-badge"),
};

// This will not return an error card but will throw the error
export const tryCreateBadgeElement = (config: LovelaceBadgeConfig) =>
tryCreateLovelaceElement(
"badge",
config,
ALWAYS_LOADED_TYPES,
LAZY_LOAD_TYPES,
undefined,
undefined
);

export const createBadgeElement = (config: LovelaceBadgeConfig) =>
createLovelaceElement(
"badge",
Expand Down
Loading
Loading