235 lines
6.8 KiB
TypeScript
235 lines
6.8 KiB
TypeScript
import { mdiDelete, mdiHelpCircle, mdiPlus } from "@mdi/js";
|
|
import { LitElement, PropertyValues, html, nothing } from "lit";
|
|
import { customElement, property, state } from "lit/decorators";
|
|
import memoizeOne from "memoize-one";
|
|
import { computeCssColor } from "../../../common/color/compute-color";
|
|
import { LocalizeFunc } from "../../../common/translations/localize";
|
|
import {
|
|
DataTableColumnContainer,
|
|
RowClickedEvent,
|
|
} from "../../../components/data-table/ha-data-table";
|
|
import "../../../components/ha-fab";
|
|
import "../../../components/ha-icon-button";
|
|
import "../../../components/ha-relative-time";
|
|
import "../../../components/ha-icon-overflow-menu";
|
|
import {
|
|
LabelRegistryEntry,
|
|
LabelRegistryEntryMutableParams,
|
|
createLabelRegistryEntry,
|
|
deleteLabelRegistryEntry,
|
|
fetchLabelRegistry,
|
|
updateLabelRegistryEntry,
|
|
} from "../../../data/label_registry";
|
|
import {
|
|
showAlertDialog,
|
|
showConfirmationDialog,
|
|
} from "../../../dialogs/generic/show-dialog-box";
|
|
import "../../../layouts/hass-tabs-subpage-data-table";
|
|
import { HomeAssistant, Route } from "../../../types";
|
|
import { configSections } from "../ha-panel-config";
|
|
import { showLabelDetailDialog } from "./show-dialog-label-detail";
|
|
|
|
@customElement("ha-config-labels")
|
|
export class HaConfigLabels extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@property({ type: Boolean }) public isWide = false;
|
|
|
|
@property({ type: Boolean }) public narrow = false;
|
|
|
|
@property({ attribute: false }) public route!: Route;
|
|
|
|
@state() private _labels: LabelRegistryEntry[] = [];
|
|
|
|
private _columns = memoizeOne((localize: LocalizeFunc) => {
|
|
const columns: DataTableColumnContainer<LabelRegistryEntry> = {
|
|
icon: {
|
|
title: "",
|
|
label: localize("ui.panel.config.labels.headers.icon"),
|
|
type: "icon",
|
|
template: (label) =>
|
|
label.icon ? html`<ha-icon .icon=${label.icon}></ha-icon>` : nothing,
|
|
},
|
|
color: {
|
|
title: "",
|
|
label: localize("ui.panel.config.labels.headers.color"),
|
|
type: "icon",
|
|
template: (label) =>
|
|
label.color
|
|
? html`<div
|
|
style="
|
|
background-color: ${computeCssColor(label.color)};
|
|
border-radius: 10px;
|
|
width: 20px;
|
|
height: 20px;"
|
|
></div>`
|
|
: nothing,
|
|
},
|
|
name: {
|
|
title: localize("ui.panel.config.labels.headers.name"),
|
|
main: true,
|
|
sortable: true,
|
|
filterable: true,
|
|
grows: true,
|
|
},
|
|
actions: {
|
|
title: "",
|
|
width: "64px",
|
|
type: "overflow-menu",
|
|
template: (label) => html`
|
|
<ha-icon-overflow-menu
|
|
.hass=${this.hass}
|
|
narrow
|
|
.items=${[
|
|
{
|
|
label: this.hass.localize("ui.common.delete"),
|
|
path: mdiDelete,
|
|
action: () => this._removeLabel(label),
|
|
warning: true,
|
|
},
|
|
]}
|
|
>
|
|
</ha-icon-overflow-menu>
|
|
`,
|
|
},
|
|
};
|
|
return columns;
|
|
});
|
|
|
|
private _data = memoizeOne(
|
|
(labels: LabelRegistryEntry[]): LabelRegistryEntry[] =>
|
|
labels.map((label) => ({
|
|
...label,
|
|
}))
|
|
);
|
|
|
|
protected firstUpdated(changedProperties: PropertyValues) {
|
|
super.firstUpdated(changedProperties);
|
|
this._fetchLabels();
|
|
}
|
|
|
|
protected render() {
|
|
return html`
|
|
<hass-tabs-subpage-data-table
|
|
.hass=${this.hass}
|
|
.narrow=${this.narrow}
|
|
back-path="/config"
|
|
.route=${this.route}
|
|
.tabs=${configSections.areas}
|
|
.columns=${this._columns(this.hass.localize)}
|
|
.data=${this._data(this._labels)}
|
|
.noDataText=${this.hass.localize("ui.panel.config.labels.no_labels")}
|
|
hasFab
|
|
@row-click=${this._editLabel}
|
|
clickable
|
|
id="label_id"
|
|
>
|
|
<ha-icon-button
|
|
slot="toolbar-icon"
|
|
@click=${this._showHelp}
|
|
.label=${this.hass.localize("ui.common.help")}
|
|
.path=${mdiHelpCircle}
|
|
></ha-icon-button>
|
|
<ha-fab
|
|
slot="fab"
|
|
.label=${this.hass.localize("ui.panel.config.labels.add_label")}
|
|
extended
|
|
@click=${this._addLabel}
|
|
>
|
|
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
|
</ha-fab>
|
|
</hass-tabs-subpage-data-table>
|
|
`;
|
|
}
|
|
|
|
private _editLabel(ev: CustomEvent<RowClickedEvent>) {
|
|
const label = this._labels.find((lbl) => lbl.label_id === ev.detail.id);
|
|
this._openDialog(label);
|
|
}
|
|
|
|
private _showHelp() {
|
|
showAlertDialog(this, {
|
|
title: this.hass.localize("ui.panel.config.labels.caption"),
|
|
text: html`
|
|
${this.hass.localize("ui.panel.config.labels.introduction")}
|
|
<p>${this.hass.localize("ui.panel.config.labels.introduction2")}</p>
|
|
`,
|
|
});
|
|
}
|
|
|
|
private async _fetchLabels() {
|
|
this._labels = await fetchLabelRegistry(this.hass.connection);
|
|
}
|
|
|
|
private _addLabel() {
|
|
this._openDialog();
|
|
}
|
|
|
|
private _openDialog(entry?: LabelRegistryEntry) {
|
|
showLabelDetailDialog(this, {
|
|
entry,
|
|
createEntry: (values) => this._createLabel(values),
|
|
updateEntry: entry
|
|
? (values) => this._updateLabel(entry, values)
|
|
: undefined,
|
|
removeEntry: entry ? () => this._removeLabel(entry) : undefined,
|
|
});
|
|
}
|
|
|
|
private async _createLabel(
|
|
values: LabelRegistryEntryMutableParams
|
|
): Promise<LabelRegistryEntry> {
|
|
const newTag = await createLabelRegistryEntry(this.hass, values);
|
|
this._labels = [...this._labels, newTag];
|
|
return newTag;
|
|
}
|
|
|
|
private async _updateLabel(
|
|
selectedLabel: LabelRegistryEntry,
|
|
values: Partial<LabelRegistryEntryMutableParams>
|
|
): Promise<LabelRegistryEntry> {
|
|
const updated = await updateLabelRegistryEntry(
|
|
this.hass,
|
|
selectedLabel.label_id,
|
|
values
|
|
);
|
|
this._labels = this._labels.map((label) =>
|
|
label.label_id === selectedLabel.label_id ? updated : label
|
|
);
|
|
return updated;
|
|
}
|
|
|
|
private async _removeLabel(selectedLabel: LabelRegistryEntry) {
|
|
if (
|
|
!(await showConfirmationDialog(this, {
|
|
title: this.hass!.localize(
|
|
"ui.panel.config.labels.confirm_remove_title"
|
|
),
|
|
text: this.hass.localize("ui.panel.config.labels.confirm_remove", {
|
|
label: selectedLabel.name || selectedLabel.label_id,
|
|
}),
|
|
dismissText: this.hass!.localize("ui.common.cancel"),
|
|
confirmText: this.hass!.localize("ui.common.remove"),
|
|
destructive: true,
|
|
}))
|
|
) {
|
|
return false;
|
|
}
|
|
try {
|
|
await deleteLabelRegistryEntry(this.hass, selectedLabel.label_id);
|
|
this._labels = this._labels.filter(
|
|
(label) => label.label_id !== selectedLabel.label_id
|
|
);
|
|
return true;
|
|
} catch (err: any) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ha-config-labels": HaConfigLabels;
|
|
}
|
|
}
|