ha-frontend/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts

211 lines
6.1 KiB
TypeScript

import { mdiPlus } from "@mdi/js";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { computeDomain } from "../../../../common/entity/compute_domain";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import type { DataTableRowData } from "../../../../components/data-table/ha-data-table";
import "../../../../components/ha-fab";
import "../../../../components/ha-svg-icon";
import type { HomeAssistant } from "../../../../types";
import { computeUnusedEntities } from "../../common/compute-unused-entities";
import type { Lovelace } from "../../types";
import "../card-editor/hui-entity-picker-table";
import { showSuggestCardDialog } from "../card-editor/show-suggest-card-dialog";
import { showSelectViewDialog } from "../select-view/show-select-view-dialog";
import { LovelaceConfig } from "../../../../data/lovelace/config/types";
import {
computeCards,
computeSection,
} from "../../common/generate-lovelace-config";
@customElement("hui-unused-entities")
export class HuiUnusedEntities extends LitElement {
@property({ attribute: false }) public lovelace!: Lovelace;
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow = false;
@state() private _unusedEntities: string[] = [];
@state() private _selectedEntities: string[] = [];
private get _config(): LovelaceConfig {
return this.lovelace.config;
}
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (changedProperties.has("lovelace")) {
this._getUnusedEntities();
}
}
protected render() {
if (!this.hass || !this.lovelace) {
return nothing;
}
if (this.lovelace.mode === "storage" && this.lovelace.editMode === false) {
return nothing;
}
return html`
<div class="container">
${!this.narrow
? html`
<ha-card
header=${this.hass.localize(
"ui.panel.lovelace.unused_entities.title"
)}
>
<div class="card-content">
${this.hass.localize(
"ui.panel.lovelace.unused_entities.available_entities"
)}
${this.lovelace.mode === "storage"
? html`
<br />${this.hass.localize(
"ui.panel.lovelace.unused_entities.select_to_add"
)}
`
: ""}
</div>
</ha-card>
`
: ""}
<hui-entity-picker-table
.hass=${this.hass}
.narrow=${this.narrow}
.entities=${this._unusedEntities.map((entity) => {
const stateObj = this.hass!.states[entity];
return {
icon: "",
entity_id: entity,
stateObj,
name: stateObj ? computeStateName(stateObj) : "Unavailable",
domain: computeDomain(entity),
last_changed: stateObj?.last_changed,
};
}) as DataTableRowData[]}
@selected-changed=${this._handleSelectedChanged}
></hui-entity-picker-table>
</div>
<div
class="fab ${classMap({
selected: this._selectedEntities.length,
})}"
>
<ha-fab
.label=${this.hass.localize("ui.panel.lovelace.editor.edit_card.add")}
extended
@click=${this._addToLovelaceView}
>
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
</ha-fab>
</div>
`;
}
private _getUnusedEntities(): void {
if (!this.hass || !this.lovelace) {
return;
}
this._selectedEntities = [];
const unusedEntities = computeUnusedEntities(this.hass, this._config!);
this._unusedEntities = [...unusedEntities].sort();
}
private _handleSelectedChanged(ev: CustomEvent): void {
this._selectedEntities = ev.detail.selectedEntities;
}
private _addToLovelaceView(): void {
const cardConfig = computeCards(
this.hass.states,
this._selectedEntities,
{}
);
const sectionConfig = computeSection(this._selectedEntities, {});
if (this.lovelace.config.views.length === 1) {
showSuggestCardDialog(this, {
lovelaceConfig: this.lovelace.config!,
saveConfig: this.lovelace.saveConfig,
path: [0],
entities: this._selectedEntities,
cardConfig,
sectionConfig,
});
return;
}
showSelectViewDialog(this, {
lovelaceConfig: this.lovelace.config,
allowDashboardChange: false,
viewSelectedCallback: (_urlPath, _selectedDashConfig, viewIndex) => {
showSuggestCardDialog(this, {
lovelaceConfig: this.lovelace.config!,
saveConfig: this.lovelace.saveConfig,
path: [viewIndex],
entities: this._selectedEntities,
cardConfig,
sectionConfig,
});
},
});
}
static get styles(): CSSResultGroup {
return css`
:host {
background: var(--lovelace-background);
overflow: hidden;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
ha-card {
--ha-card-box-shadow: none;
--ha-card-border-radius: 0;
}
hui-entity-picker-table {
flex-grow: 1;
}
.fab {
position: sticky;
float: var(--float-end);
right: calc(16px + env(safe-area-inset-right));
bottom: calc(16px + env(safe-area-inset-bottom));
inset-inline-end: calc(16px + env(safe-area-inset-right));
inset-inline-start: initial;
z-index: 1;
}
ha-fab {
position: relative;
bottom: calc(-80px - env(safe-area-inset-bottom));
transition: bottom 0.3s;
}
.fab.selected ha-fab {
bottom: 0;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-unused-entities": HuiUnusedEntities;
}
}