mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-29 04:06:35 +00:00
Support disabling devices (#7715)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
faaef31b9f
commit
3bdab738c6
@ -156,7 +156,9 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
|||||||
areaLookup[area.area_id] = area;
|
areaLookup[area.area_id] = area;
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputDevices = [...devices];
|
let inputDevices = devices.filter(
|
||||||
|
(device) => device.id === this.value || !device.disabled_by
|
||||||
|
);
|
||||||
|
|
||||||
if (includeDomains) {
|
if (includeDomains) {
|
||||||
inputDevices = inputDevices.filter((device) => {
|
inputDevices = inputDevices.filter((device) => {
|
||||||
|
@ -17,6 +17,7 @@ export interface DeviceRegistryEntry {
|
|||||||
area_id?: string;
|
area_id?: string;
|
||||||
name_by_user?: string;
|
name_by_user?: string;
|
||||||
entry_type: "service" | null;
|
entry_type: "service" | null;
|
||||||
|
disabled_by: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeviceEntityLookup {
|
export interface DeviceEntityLookup {
|
||||||
@ -26,6 +27,7 @@ export interface DeviceEntityLookup {
|
|||||||
export interface DeviceRegistryEntryMutableParams {
|
export interface DeviceRegistryEntryMutableParams {
|
||||||
area_id?: string | null;
|
area_id?: string | null;
|
||||||
name_by_user?: string | null;
|
name_by_user?: string | null;
|
||||||
|
disabled_by?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fallbackDeviceName = (
|
export const fallbackDeviceName = (
|
||||||
|
@ -19,10 +19,11 @@ import {
|
|||||||
|
|
||||||
import { DeviceRegistryDetailDialogParams } from "./show-dialog-device-registry-detail";
|
import { DeviceRegistryDetailDialogParams } from "./show-dialog-device-registry-detail";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import type { HaSwitch } from "../../../../components/ha-switch";
|
||||||
import { PolymerChangedEvent } from "../../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../../polymer-types";
|
||||||
import { computeDeviceName } from "../../../../data/device_registry";
|
import { computeDeviceName } from "../../../../data/device_registry";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { haStyleDialog } from "../../../../resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../resources/styles";
|
||||||
|
|
||||||
@customElement("dialog-device-registry-detail")
|
@customElement("dialog-device-registry-detail")
|
||||||
class DialogDeviceRegistryDetail extends LitElement {
|
class DialogDeviceRegistryDetail extends LitElement {
|
||||||
@ -36,6 +37,8 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _areaId?: string;
|
@internalProperty() private _areaId?: string;
|
||||||
|
|
||||||
|
@internalProperty() private _disabledBy!: string | null;
|
||||||
|
|
||||||
@internalProperty() private _submitting?: boolean;
|
@internalProperty() private _submitting?: boolean;
|
||||||
|
|
||||||
public async showDialog(
|
public async showDialog(
|
||||||
@ -45,6 +48,7 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._nameByUser = this._params.device.name_by_user || "";
|
this._nameByUser = this._params.device.name_by_user || "";
|
||||||
this._areaId = this._params.device.area_id;
|
this._areaId = this._params.device.area_id;
|
||||||
|
this._disabledBy = this._params.device.disabled_by;
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +84,32 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
.value=${this._areaId}
|
.value=${this._areaId}
|
||||||
@value-changed=${this._areaPicked}
|
@value-changed=${this._areaPicked}
|
||||||
></ha-area-picker>
|
></ha-area-picker>
|
||||||
|
<div class="row">
|
||||||
|
<ha-switch
|
||||||
|
.checked=${!this._disabledBy}
|
||||||
|
@change=${this._disabledByChanged}
|
||||||
|
>
|
||||||
|
</ha-switch>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
${this.hass.localize("ui.panel.config.devices.enabled_label")}
|
||||||
|
</div>
|
||||||
|
<div class="secondary">
|
||||||
|
${this._disabledBy && this._disabledBy !== "user"
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.panel.config.devices.enabled_cause",
|
||||||
|
"cause",
|
||||||
|
this.hass.localize(
|
||||||
|
`config_entry.disabled_by.${this._disabledBy}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: ""}
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.devices.enabled_description"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
@ -109,12 +139,17 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
this._areaId = event.detail.value;
|
this._areaId = event.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _disabledByChanged(ev: Event): void {
|
||||||
|
this._disabledBy = (ev.target as HaSwitch).checked ? null : "user";
|
||||||
|
}
|
||||||
|
|
||||||
private async _updateEntry(): Promise<void> {
|
private async _updateEntry(): Promise<void> {
|
||||||
this._submitting = true;
|
this._submitting = true;
|
||||||
try {
|
try {
|
||||||
await this._params!.updateEntry({
|
await this._params!.updateEntry({
|
||||||
name_by_user: this._nameByUser.trim() || null,
|
name_by_user: this._nameByUser.trim() || null,
|
||||||
area_id: this._areaId || null,
|
area_id: this._areaId || null,
|
||||||
|
disabled_by: this._disabledBy || null,
|
||||||
});
|
});
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -128,6 +163,7 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
|
haStyle,
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
.form {
|
.form {
|
||||||
@ -139,6 +175,15 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
.error {
|
.error {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
ha-switch {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -246,6 +246,26 @@ export class HaConfigDevicePage extends LitElement {
|
|||||||
.devices=${this.devices}
|
.devices=${this.devices}
|
||||||
.device=${device}
|
.device=${device}
|
||||||
>
|
>
|
||||||
|
${
|
||||||
|
device.disabled_by
|
||||||
|
? html`
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.devices.enabled_cause",
|
||||||
|
"cause",
|
||||||
|
device.disabled_by
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions" slot="actions">
|
||||||
|
<mwc-button @click=${this._enableDevice}>
|
||||||
|
${this.hass.localize("ui.common.enable")}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: html``
|
||||||
|
}
|
||||||
${this._renderIntegrationInfo(device, integrations)}
|
${this._renderIntegrationInfo(device, integrations)}
|
||||||
</ha-device-info-card>
|
</ha-device-info-card>
|
||||||
|
|
||||||
@ -272,7 +292,12 @@ export class HaConfigDevicePage extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
@click=${this._showAutomationDialog}
|
@click=${this._showAutomationDialog}
|
||||||
title=${this.hass.localize(
|
.disabled=${device.disabled_by}
|
||||||
|
title=${device.disabled_by
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.panel.config.devices.automation.create_disabled"
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
"ui.panel.config.devices.automation.create"
|
"ui.panel.config.devices.automation.create"
|
||||||
)}
|
)}
|
||||||
icon="hass:plus-circle"
|
icon="hass:plus-circle"
|
||||||
@ -342,9 +367,16 @@ export class HaConfigDevicePage extends LitElement {
|
|||||||
|
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
@click=${this._createScene}
|
@click=${this._createScene}
|
||||||
title=${this.hass.localize(
|
.disabled=${device.disabled_by}
|
||||||
|
title=${
|
||||||
|
device.disabled_by
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.panel.config.devices.scene.create_disabled"
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
"ui.panel.config.devices.scene.create"
|
"ui.panel.config.devices.scene.create"
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
icon="hass:plus-circle"
|
icon="hass:plus-circle"
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
</h1>
|
</h1>
|
||||||
@ -415,7 +447,12 @@ export class HaConfigDevicePage extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
@click=${this._showScriptDialog}
|
@click=${this._showScriptDialog}
|
||||||
title=${this.hass.localize(
|
.disabled=${device.disabled_by}
|
||||||
|
title=${device.disabled_by
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.panel.config.devices.script.create_disabled"
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
"ui.panel.config.devices.script.create"
|
"ui.panel.config.devices.script.create"
|
||||||
)}
|
)}
|
||||||
icon="hass:plus-circle"
|
icon="hass:plus-circle"
|
||||||
@ -632,6 +669,12 @@ export class HaConfigDevicePage extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _enableDevice(): Promise<void> {
|
||||||
|
await updateDeviceRegistryEntry(this.hass, this.deviceId, {
|
||||||
|
disabled_by: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResult {
|
||||||
return css`
|
return css`
|
||||||
.container {
|
.container {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { mdiPlus } from "@mdi/js";
|
import { mdiPlus, mdiFilterVariant } from "@mdi/js";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -7,7 +10,9 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
|
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
|
||||||
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||||
@ -18,6 +23,7 @@ import {
|
|||||||
RowClickedEvent,
|
RowClickedEvent,
|
||||||
} from "../../../components/data-table/ha-data-table";
|
} from "../../../components/data-table/ha-data-table";
|
||||||
import "../../../components/entity/ha-battery-icon";
|
import "../../../components/entity/ha-battery-icon";
|
||||||
|
import "../../../components/ha-button-menu";
|
||||||
import { AreaRegistryEntry } from "../../../data/area_registry";
|
import { AreaRegistryEntry } from "../../../data/area_registry";
|
||||||
import { ConfigEntry } from "../../../data/config_entries";
|
import { ConfigEntry } from "../../../data/config_entries";
|
||||||
import {
|
import {
|
||||||
@ -34,6 +40,7 @@ import { domainToName } from "../../../data/integration";
|
|||||||
import "../../../layouts/hass-tabs-subpage-data-table";
|
import "../../../layouts/hass-tabs-subpage-data-table";
|
||||||
import { HomeAssistant, Route } from "../../../types";
|
import { HomeAssistant, Route } from "../../../types";
|
||||||
import { configSections } from "../ha-panel-config";
|
import { configSections } from "../ha-panel-config";
|
||||||
|
import { haStyle } from "../../../resources/styles";
|
||||||
|
|
||||||
interface DeviceRowData extends DeviceRegistryEntry {
|
interface DeviceRowData extends DeviceRegistryEntry {
|
||||||
device?: DeviceRowData;
|
device?: DeviceRowData;
|
||||||
@ -64,6 +71,12 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
window.location.search
|
window.location.search
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@internalProperty() private _showDisabled = false;
|
||||||
|
|
||||||
|
@internalProperty() private _filter = "";
|
||||||
|
|
||||||
|
@internalProperty() private _numHiddenDevices = 0;
|
||||||
|
|
||||||
private _activeFilters = memoizeOne(
|
private _activeFilters = memoizeOne(
|
||||||
(
|
(
|
||||||
entries: ConfigEntry[],
|
entries: ConfigEntry[],
|
||||||
@ -74,6 +87,10 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
filters.forEach((value, key) => {
|
filters.forEach((value, key) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "config_entry": {
|
case "config_entry": {
|
||||||
|
// If we are requested to show the devices for a given config entry,
|
||||||
|
// also show the disabled ones by default.
|
||||||
|
this._showDisabled = true;
|
||||||
|
|
||||||
const configEntry = entries.find(
|
const configEntry = entries.find(
|
||||||
(entry) => entry.entry_id === value
|
(entry) => entry.entry_id === value
|
||||||
);
|
);
|
||||||
@ -105,6 +122,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
entities: EntityRegistryEntry[],
|
entities: EntityRegistryEntry[],
|
||||||
areas: AreaRegistryEntry[],
|
areas: AreaRegistryEntry[],
|
||||||
filters: URLSearchParams,
|
filters: URLSearchParams,
|
||||||
|
showDisabled: boolean,
|
||||||
localize: LocalizeFunc
|
localize: LocalizeFunc
|
||||||
) => {
|
) => {
|
||||||
// Some older installations might have devices pointing at invalid entryIDs
|
// Some older installations might have devices pointing at invalid entryIDs
|
||||||
@ -117,6 +135,9 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
deviceLookup[device.id] = device;
|
deviceLookup[device.id] = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If nothing gets filtered, this is our correct count of devices
|
||||||
|
let startLength = outputDevices.length;
|
||||||
|
|
||||||
const deviceEntityLookup: DeviceEntityLookup = {};
|
const deviceEntityLookup: DeviceEntityLookup = {};
|
||||||
for (const entity of entities) {
|
for (const entity of entities) {
|
||||||
if (!entity.device_id) {
|
if (!entity.device_id) {
|
||||||
@ -145,6 +166,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
outputDevices = outputDevices.filter((device) =>
|
outputDevices = outputDevices.filter((device) =>
|
||||||
device.config_entries.includes(value)
|
device.config_entries.includes(value)
|
||||||
);
|
);
|
||||||
|
startLength = outputDevices.length;
|
||||||
const configEntry = entries.find((entry) => entry.entry_id === value);
|
const configEntry = entries.find((entry) => entry.entry_id === value);
|
||||||
if (configEntry) {
|
if (configEntry) {
|
||||||
filterDomains.push(configEntry.domain);
|
filterDomains.push(configEntry.domain);
|
||||||
@ -152,6 +174,10 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!showDisabled) {
|
||||||
|
outputDevices = outputDevices.filter((device) => !device.disabled_by);
|
||||||
|
}
|
||||||
|
|
||||||
outputDevices = outputDevices.map((device) => {
|
outputDevices = outputDevices.map((device) => {
|
||||||
return {
|
return {
|
||||||
...device,
|
...device,
|
||||||
@ -182,6 +208,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._numHiddenDevices = startLength - outputDevices.length;
|
||||||
return { devicesOutput: outputDevices, filteredDomains: filterDomains };
|
return { devicesOutput: outputDevices, filteredDomains: filterDomains };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -298,9 +325,119 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
this.entities,
|
this.entities,
|
||||||
this.areas,
|
this.areas,
|
||||||
this._searchParms,
|
this._searchParms,
|
||||||
|
this._showDisabled,
|
||||||
this.hass.localize
|
this.hass.localize
|
||||||
);
|
);
|
||||||
const includeZHAFab = filteredDomains.includes("zha");
|
const includeZHAFab = filteredDomains.includes("zha");
|
||||||
|
const activeFilters = this._activeFilters(
|
||||||
|
this.entries,
|
||||||
|
this._searchParms,
|
||||||
|
this.hass.localize
|
||||||
|
);
|
||||||
|
|
||||||
|
const headerToolbar = html`
|
||||||
|
<search-input
|
||||||
|
no-label-float
|
||||||
|
no-underline
|
||||||
|
@value-changed=${this._handleSearchChange}
|
||||||
|
.filter=${this._filter}
|
||||||
|
.label=${this.hass.localize("ui.panel.config.devices.picker.search")}
|
||||||
|
></search-input
|
||||||
|
>${activeFilters
|
||||||
|
? html`<div class="active-filters">
|
||||||
|
${this.narrow
|
||||||
|
? html` <div>
|
||||||
|
<ha-icon icon="hass:filter-variant"></ha-icon>
|
||||||
|
<paper-tooltip animation-delay="0" position="left">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.filtering.filtering_by"
|
||||||
|
)}
|
||||||
|
${activeFilters.join(", ")}
|
||||||
|
${this._numHiddenDevices
|
||||||
|
? "(" +
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||||
|
"number",
|
||||||
|
this._numHiddenDevices
|
||||||
|
) +
|
||||||
|
")"
|
||||||
|
: ""}
|
||||||
|
</paper-tooltip>
|
||||||
|
</div>`
|
||||||
|
: `${this.hass.localize(
|
||||||
|
"ui.panel.config.filtering.filtering_by"
|
||||||
|
)} ${activeFilters.join(", ")}
|
||||||
|
${
|
||||||
|
this._numHiddenDevices
|
||||||
|
? "(" +
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||||
|
"number",
|
||||||
|
this._numHiddenDevices
|
||||||
|
) +
|
||||||
|
")"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
<mwc-button @click=${this._clearFilter}
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.filtering.clear"
|
||||||
|
)}</mwc-button
|
||||||
|
>
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
${this._numHiddenDevices && !activeFilters
|
||||||
|
? html`<div class="active-filters">
|
||||||
|
${this.narrow
|
||||||
|
? html` <div>
|
||||||
|
<ha-icon icon="hass:filter-variant"></ha-icon>
|
||||||
|
<paper-tooltip animation-delay="0" position="left">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||||
|
"number",
|
||||||
|
this._numHiddenDevices
|
||||||
|
)}
|
||||||
|
</paper-tooltip>
|
||||||
|
</div>`
|
||||||
|
: `${this.hass.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||||
|
"number",
|
||||||
|
this._numHiddenDevices
|
||||||
|
)}`}
|
||||||
|
<mwc-button @click=${this._showAll}
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.show_all"
|
||||||
|
)}</mwc-button
|
||||||
|
>
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
<ha-button-menu corner="BOTTOM_START" multi>
|
||||||
|
<mwc-icon-button
|
||||||
|
slot="trigger"
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.filter"
|
||||||
|
)}
|
||||||
|
.title=${this.hass!.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.filter"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiFilterVariant}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
|
<mwc-list-item
|
||||||
|
@request-selected="${this._showDisabledChanged}"
|
||||||
|
graphic="control"
|
||||||
|
.selected=${this._showDisabled}
|
||||||
|
>
|
||||||
|
<ha-checkbox
|
||||||
|
slot="graphic"
|
||||||
|
.checked=${this._showDisabled}
|
||||||
|
></ha-checkbox>
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.config.devices.picker.filter.show_disabled"
|
||||||
|
)}
|
||||||
|
</mwc-list-item>
|
||||||
|
</ha-button-menu>
|
||||||
|
`;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage-data-table
|
<hass-tabs-subpage-data-table
|
||||||
@ -313,11 +450,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.columns=${this._columns(this.narrow)}
|
.columns=${this._columns(this.narrow)}
|
||||||
.data=${devicesOutput}
|
.data=${devicesOutput}
|
||||||
.activeFilters=${this._activeFilters(
|
.filter=${this._filter}
|
||||||
this.entries,
|
|
||||||
this._searchParms,
|
|
||||||
this.hass.localize
|
|
||||||
)}
|
|
||||||
@row-click=${this._handleRowClicked}
|
@row-click=${this._handleRowClicked}
|
||||||
clickable
|
clickable
|
||||||
.hasFab=${includeZHAFab}
|
.hasFab=${includeZHAFab}
|
||||||
@ -333,6 +466,15 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
</ha-fab>
|
</ha-fab>
|
||||||
</a>`
|
</a>`
|
||||||
: html``}
|
: html``}
|
||||||
|
<div
|
||||||
|
class=${classMap({
|
||||||
|
"search-toolbar": this.narrow,
|
||||||
|
"table-header": !this.narrow,
|
||||||
|
})}
|
||||||
|
slot="header"
|
||||||
|
>
|
||||||
|
${headerToolbar}
|
||||||
|
</div>
|
||||||
</hass-tabs-subpage-data-table>
|
</hass-tabs-subpage-data-table>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -363,6 +505,136 @@ export class HaConfigDeviceDashboard extends LitElement {
|
|||||||
const deviceId = ev.detail.id;
|
const deviceId = ev.detail.id;
|
||||||
navigate(this, `/config/devices/device/${deviceId}`);
|
navigate(this, `/config/devices/device/${deviceId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _showDisabledChanged(ev: CustomEvent<RequestSelectedDetail>) {
|
||||||
|
if (ev.detail.source !== "property") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._showDisabled = ev.detail.selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleSearchChange(ev: CustomEvent) {
|
||||||
|
this._filter = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _clearFilter() {
|
||||||
|
navigate(this, window.location.pathname, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showAll() {
|
||||||
|
this._showDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
css`
|
||||||
|
hass-loading-screen {
|
||||||
|
--app-header-background-color: var(--sidebar-background-color);
|
||||||
|
--app-header-text-color: var(--sidebar-text-color);
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-family: var(--paper-font-headline_-_font-family);
|
||||||
|
-webkit-font-smoothing: var(
|
||||||
|
--paper-font-headline_-_-webkit-font-smoothing
|
||||||
|
);
|
||||||
|
font-size: var(--paper-font-headline_-_font-size);
|
||||||
|
font-weight: var(--paper-font-headline_-_font-weight);
|
||||||
|
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||||
|
line-height: var(--paper-font-headline_-_line-height);
|
||||||
|
opacity: var(--dark-primary-opacity);
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-family: var(--paper-font-subhead_-_font-family);
|
||||||
|
-webkit-font-smoothing: var(
|
||||||
|
--paper-font-subhead_-_-webkit-font-smoothing
|
||||||
|
);
|
||||||
|
font-weight: var(--paper-font-subhead_-_font-weight);
|
||||||
|
line-height: var(--paper-font-subhead_-_line-height);
|
||||||
|
}
|
||||||
|
ha-data-table {
|
||||||
|
width: 100%;
|
||||||
|
--data-table-border-width: 0;
|
||||||
|
}
|
||||||
|
:host(:not([narrow])) ha-data-table {
|
||||||
|
height: calc(100vh - 1px - var(--header-height));
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
ha-button-menu {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12);
|
||||||
|
}
|
||||||
|
search-input {
|
||||||
|
margin-left: 16px;
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
.search-toolbar search-input {
|
||||||
|
margin-left: 8px;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
.search-toolbar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.search-toolbar ha-button-menu {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
.selected-txt {
|
||||||
|
font-weight: bold;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
.table-header .selected-txt {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.search-toolbar .selected-txt {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.header-btns > mwc-button,
|
||||||
|
.header-btns > ha-icon-button {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
.active-filters {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 2px 2px 8px;
|
||||||
|
margin-left: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.active-filters ha-icon {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
.active-filters mwc-button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.active-filters::before {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
opacity: 0.12;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1755,11 +1755,15 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
"no_devices": "No devices",
|
"no_devices": "No devices",
|
||||||
|
"enabled_label": "Enable device",
|
||||||
|
"enabled_cause": "Disabled by {cause}.",
|
||||||
|
"enabled_description": "Disabled devices will not be shown and entities belonging to the device will be disabled and not added to Home Assistant.",
|
||||||
"automation": {
|
"automation": {
|
||||||
"automations": "Automations",
|
"automations": "Automations",
|
||||||
"no_automations": "No automations",
|
"no_automations": "No automations",
|
||||||
"unknown_automation": "Unknown automation",
|
"unknown_automation": "Unknown automation",
|
||||||
"create": "Create automation with device",
|
"create": "Create automation with device",
|
||||||
|
"create_disable": "Can't create automation with disabled device",
|
||||||
"triggers": {
|
"triggers": {
|
||||||
"caption": "Do something when...",
|
"caption": "Do something when...",
|
||||||
"no_triggers": "No triggers",
|
"no_triggers": "No triggers",
|
||||||
@ -1780,12 +1784,14 @@
|
|||||||
"script": {
|
"script": {
|
||||||
"scripts": "Scripts",
|
"scripts": "Scripts",
|
||||||
"no_scripts": "No scripts",
|
"no_scripts": "No scripts",
|
||||||
"create": "Create script with device"
|
"create": "Create script with device",
|
||||||
|
"create_disable": "Can't create script with disabled device"
|
||||||
},
|
},
|
||||||
"scene": {
|
"scene": {
|
||||||
"scenes": "Scenes",
|
"scenes": "Scenes",
|
||||||
"no_scenes": "No scenes",
|
"no_scenes": "No scenes",
|
||||||
"create": "Create scene with device"
|
"create": "Create scene with device",
|
||||||
|
"create_disable": "Can't create scene with disabled device"
|
||||||
},
|
},
|
||||||
"cant_edit": "You can only edit items that are created in the UI.",
|
"cant_edit": "You can only edit items that are created in the UI.",
|
||||||
"device_not_found": "Device not found.",
|
"device_not_found": "Device not found.",
|
||||||
@ -1811,7 +1817,16 @@
|
|||||||
"no_area": "No area"
|
"no_area": "No area"
|
||||||
},
|
},
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"confirm_delete": "Are you sure you want to delete this device?"
|
"confirm_delete": "Are you sure you want to delete this device?",
|
||||||
|
"picker": {
|
||||||
|
"search": "Search devices",
|
||||||
|
"filter": {
|
||||||
|
"filter": "Filter",
|
||||||
|
"show_disabled": "Show disabled devices",
|
||||||
|
"hidden_devices": "{number} hidden {number, plural,\n one {device}\n other {devices}\n}",
|
||||||
|
"show_all": "Show all"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"entities": {
|
"entities": {
|
||||||
"caption": "Entities",
|
"caption": "Entities",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user