mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Add ignore discovery button (#4354)
* Add ignore discovery button * Add seperate list for ignored integrations * Move translations * Add zeroconf
This commit is contained in:
parent
dd17a153d2
commit
2c57ab60f1
@ -4,6 +4,8 @@ import { debounce } from "../common/util/debounce";
|
|||||||
import { getCollection, Connection } from "home-assistant-js-websocket";
|
import { getCollection, Connection } from "home-assistant-js-websocket";
|
||||||
import { LocalizeFunc } from "../common/translations/localize";
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
|
|
||||||
|
export const DISCOVERY_SOURCES = ["homekit", "ssdp", "zeroconf"];
|
||||||
|
|
||||||
export const createConfigFlow = (hass: HomeAssistant, handler: string) =>
|
export const createConfigFlow = (hass: HomeAssistant, handler: string) =>
|
||||||
hass.callApi<DataEntryFlowStep>("POST", "config/config_entries/flow", {
|
hass.callApi<DataEntryFlowStep>("POST", "config/config_entries/flow", {
|
||||||
handler,
|
handler,
|
||||||
@ -26,6 +28,9 @@ export const handleConfigFlowStep = (
|
|||||||
data
|
data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const ignoreConfigFlow = (hass: HomeAssistant, flowId: string) =>
|
||||||
|
hass.callWS({ type: "config_entries/ignore_flow", flow_id: flowId });
|
||||||
|
|
||||||
export const deleteConfigFlow = (hass: HomeAssistant, flowId: string) =>
|
export const deleteConfigFlow = (hass: HomeAssistant, flowId: string) =>
|
||||||
hass.callApi("DELETE", `config/config_entries/flow/${flowId}`);
|
hass.callApi("DELETE", `config/config_entries/flow/${flowId}`);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
|||||||
import "@polymer/paper-tooltip/paper-tooltip";
|
import "@polymer/paper-tooltip/paper-tooltip";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/iron-icon/iron-icon";
|
import "@polymer/iron-icon/iron-icon";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
|
||||||
@ -23,7 +24,11 @@ import {
|
|||||||
loadConfigFlowDialog,
|
loadConfigFlowDialog,
|
||||||
showConfigFlowDialog,
|
showConfigFlowDialog,
|
||||||
} from "../../../dialogs/config-flow/show-dialog-config-flow";
|
} from "../../../dialogs/config-flow/show-dialog-config-flow";
|
||||||
import { localizeConfigFlowTitle } from "../../../data/config_flow";
|
import {
|
||||||
|
localizeConfigFlowTitle,
|
||||||
|
ignoreConfigFlow,
|
||||||
|
DISCOVERY_SOURCES,
|
||||||
|
} from "../../../data/config_flow";
|
||||||
import {
|
import {
|
||||||
LitElement,
|
LitElement,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
@ -34,10 +39,11 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ConfigEntry } from "../../../data/config_entries";
|
import { ConfigEntry, deleteConfigEntry } from "../../../data/config_entries";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { EntityRegistryEntry } from "../../../data/entity_registry";
|
import { EntityRegistryEntry } from "../../../data/entity_registry";
|
||||||
import { DataEntryFlowProgress } from "../../../data/data_entry_flow";
|
import { DataEntryFlowProgress } from "../../../data/data_entry_flow";
|
||||||
|
import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialog-confirmation";
|
||||||
|
|
||||||
@customElement("ha-config-entries-dashboard")
|
@customElement("ha-config-entries-dashboard")
|
||||||
export class HaConfigManagerDashboard extends LitElement {
|
export class HaConfigManagerDashboard extends LitElement {
|
||||||
@ -56,6 +62,7 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
* For example, can be discovered devices that require more config.
|
* For example, can be discovered devices that require more config.
|
||||||
*/
|
*/
|
||||||
@property() private configEntriesInProgress!: DataEntryFlowProgress[];
|
@property() private configEntriesInProgress!: DataEntryFlowProgress[];
|
||||||
|
@property() private _showIgnored = false;
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
@ -67,6 +74,67 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
<hass-subpage
|
<hass-subpage
|
||||||
header=${this.hass.localize("ui.panel.config.integrations.caption")}
|
header=${this.hass.localize("ui.panel.config.integrations.caption")}
|
||||||
>
|
>
|
||||||
|
<paper-menu-button
|
||||||
|
close-on-activate
|
||||||
|
no-animations
|
||||||
|
horizontal-align="right"
|
||||||
|
horizontal-offset="-5"
|
||||||
|
slot="toolbar-icon"
|
||||||
|
>
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:dots-vertical"
|
||||||
|
slot="dropdown-trigger"
|
||||||
|
alt="menu"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
role="listbox"
|
||||||
|
selected="{{selectedItem}}"
|
||||||
|
>
|
||||||
|
<paper-item @click=${this._toggleShowIgnored}>
|
||||||
|
${this.hass.localize(
|
||||||
|
this._showIgnored
|
||||||
|
? "ui.panel.config.integrations.ignore.hide_ignored"
|
||||||
|
: "ui.panel.config.integrations.ignore.show_ignored"
|
||||||
|
)}
|
||||||
|
</paper-item>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-menu-button>
|
||||||
|
|
||||||
|
${this._showIgnored
|
||||||
|
? html`
|
||||||
|
<ha-config-section>
|
||||||
|
<span slot="header"
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.ignored"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<ha-card>
|
||||||
|
${this.configEntries
|
||||||
|
.filter((item) => item.source === "ignore")
|
||||||
|
.map(
|
||||||
|
(item: ConfigEntry) => html`
|
||||||
|
<paper-item>
|
||||||
|
<paper-item-body>
|
||||||
|
${this.hass.localize(
|
||||||
|
`component.${item.domain}.config.title`
|
||||||
|
)}
|
||||||
|
</paper-item-body>
|
||||||
|
<paper-icon-button
|
||||||
|
@click=${this._removeIgnoredIntegration}
|
||||||
|
.entry=${item}
|
||||||
|
icon="hass:delete"
|
||||||
|
aria-label=${this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.details"
|
||||||
|
)}
|
||||||
|
></paper-icon-button>
|
||||||
|
</paper-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</ha-card>
|
||||||
|
</ha-config-section>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
${this.configEntriesInProgress.length
|
${this.configEntriesInProgress.length
|
||||||
? html`
|
? html`
|
||||||
<ha-config-section>
|
<ha-config-section>
|
||||||
@ -82,9 +150,22 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
<paper-item-body>
|
<paper-item-body>
|
||||||
${localizeConfigFlowTitle(this.hass.localize, flow)}
|
${localizeConfigFlowTitle(this.hass.localize, flow)}
|
||||||
</paper-item-body>
|
</paper-item-body>
|
||||||
|
${DISCOVERY_SOURCES.includes(flow.context.source) &&
|
||||||
|
flow.context.unique_id
|
||||||
|
? html`
|
||||||
|
<mwc-button
|
||||||
|
@click=${this._ignoreFlow}
|
||||||
|
.flow=${flow}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.ignore"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<mwc-button
|
<mwc-button
|
||||||
@click=${this._continueFlow}
|
@click=${this._continueFlow}
|
||||||
data-id="${flow.flow_id}"
|
.flowId=${flow.flow_id}
|
||||||
>${this.hass.localize(
|
>${this.hass.localize(
|
||||||
"ui.panel.config.integrations.configure"
|
"ui.panel.config.integrations.configure"
|
||||||
)}</mwc-button
|
)}</mwc-button
|
||||||
@ -98,49 +179,51 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
|
|
||||||
<ha-config-section class="configured">
|
<ha-config-section class="configured">
|
||||||
<span slot="header"
|
<span slot="header">
|
||||||
>${this.hass.localize(
|
${this.hass.localize("ui.panel.config.integrations.configured")}
|
||||||
"ui.panel.config.integrations.configured"
|
</span>
|
||||||
)}</span
|
|
||||||
>
|
|
||||||
<ha-card>
|
<ha-card>
|
||||||
${this.entityRegistryEntries.length
|
${this.entityRegistryEntries.length
|
||||||
? this.configEntries.map(
|
? this.configEntries.map((item: any, idx) =>
|
||||||
(item: any, idx) => html`
|
item.source === "ignore"
|
||||||
<a
|
? ""
|
||||||
href="/config/integrations/config_entry/${item.entry_id}"
|
: html`
|
||||||
>
|
<a
|
||||||
<paper-item data-index=${idx}>
|
href="/config/integrations/config_entry/${item.entry_id}"
|
||||||
<paper-item-body two-line>
|
>
|
||||||
<div>
|
<paper-item data-index=${idx}>
|
||||||
${this.hass.localize(
|
<paper-item-body two-line>
|
||||||
`component.${item.domain}.config.title`
|
<div>
|
||||||
)}:
|
${this.hass.localize(
|
||||||
${item.title}
|
`component.${item.domain}.config.title`
|
||||||
</div>
|
)}:
|
||||||
<div secondary>
|
${item.title}
|
||||||
${this._getEntities(item).map(
|
</div>
|
||||||
(entity) => html`
|
<div secondary>
|
||||||
<span>
|
${this._getEntities(item).map(
|
||||||
<ha-state-icon
|
(entity) => html`
|
||||||
.stateObj=${entity}
|
<span>
|
||||||
></ha-state-icon>
|
<ha-state-icon
|
||||||
<paper-tooltip position="bottom"
|
.stateObj=${entity}
|
||||||
>${computeStateName(entity)}</paper-tooltip
|
></ha-state-icon>
|
||||||
>
|
<paper-tooltip position="bottom"
|
||||||
</span>
|
>${computeStateName(
|
||||||
`
|
entity
|
||||||
)}
|
)}</paper-tooltip
|
||||||
</div>
|
>
|
||||||
</paper-item-body>
|
</span>
|
||||||
<ha-icon-next
|
`
|
||||||
aria-label=${this.hass.localize(
|
)}
|
||||||
"ui.panel.config.integrations.details"
|
</div>
|
||||||
)}
|
</paper-item-body>
|
||||||
></ha-icon-next>
|
<ha-icon-next
|
||||||
</paper-item>
|
aria-label=${this.hass.localize(
|
||||||
</a>
|
"ui.panel.config.integrations.details"
|
||||||
`
|
)}
|
||||||
|
></ha-icon-next>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
`
|
||||||
)
|
)
|
||||||
: html`
|
: html`
|
||||||
<div class="config-entry-row">
|
<div class="config-entry-row">
|
||||||
@ -176,12 +259,64 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
|
|
||||||
private _continueFlow(ev: Event) {
|
private _continueFlow(ev: Event) {
|
||||||
showConfigFlowDialog(this, {
|
showConfigFlowDialog(this, {
|
||||||
continueFlowId:
|
continueFlowId: (ev.target! as any).flowId,
|
||||||
(ev.target as HTMLElement).getAttribute("data-id") || undefined,
|
|
||||||
dialogClosedCallback: () => fireEvent(this, "hass-reload-entries"),
|
dialogClosedCallback: () => fireEvent(this, "hass-reload-entries"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _ignoreFlow(ev: Event) {
|
||||||
|
const flow = (ev.target! as any).flow;
|
||||||
|
showConfirmationDialog(this, {
|
||||||
|
title: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.confirm_ignore_title",
|
||||||
|
"name",
|
||||||
|
localizeConfigFlowTitle(this.hass.localize, flow)
|
||||||
|
),
|
||||||
|
text: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.confirm_ignore"
|
||||||
|
),
|
||||||
|
confirmBtnText: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.ignore"
|
||||||
|
),
|
||||||
|
confirm: () => {
|
||||||
|
ignoreConfigFlow(this.hass, flow.flow_id);
|
||||||
|
fireEvent(this, "hass-reload-entries");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _toggleShowIgnored() {
|
||||||
|
this._showIgnored = !this._showIgnored;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _removeIgnoredIntegration(ev: Event) {
|
||||||
|
const entry = (ev.target! as any).entry;
|
||||||
|
showConfirmationDialog(this, {
|
||||||
|
title: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.confirm_delete_ignore_title",
|
||||||
|
"name",
|
||||||
|
this.hass.localize(`component.${entry.domain}.config.title`)
|
||||||
|
),
|
||||||
|
text: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.confirm_delete_ignore"
|
||||||
|
),
|
||||||
|
confirmBtnText: this.hass!.localize(
|
||||||
|
"ui.panel.config.integrations.ignore.stop_ignore"
|
||||||
|
),
|
||||||
|
confirm: async () => {
|
||||||
|
const result = await deleteConfigEntry(this.hass, entry.entry_id);
|
||||||
|
if (result.require_restart) {
|
||||||
|
alert(
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.config_entry.restart_confirm"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fireEvent(this, "hass-reload-entries");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _getEntities(configEntry: ConfigEntry): HassEntity[] {
|
private _getEntities(configEntry: ConfigEntry): HassEntity[] {
|
||||||
if (!this.entityRegistryEntries) {
|
if (!this.entityRegistryEntries) {
|
||||||
return [];
|
return [];
|
||||||
@ -203,8 +338,7 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
mwc-button {
|
mwc-button {
|
||||||
top: 3px;
|
align-self: center;
|
||||||
margin-right: -0.57em;
|
|
||||||
}
|
}
|
||||||
.config-entry-row {
|
.config-entry-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -229,6 +363,9 @@ export class HaConfigManagerDashboard extends LitElement {
|
|||||||
right: auto;
|
right: auto;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
}
|
}
|
||||||
|
.overflow {
|
||||||
|
width: 56px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ class HaConfigIntegrations extends HassRouterPage {
|
|||||||
private _loadData() {
|
private _loadData() {
|
||||||
getConfigEntries(this.hass).then((configEntries) => {
|
getConfigEntries(this.hass).then((configEntries) => {
|
||||||
this._configEntries = configEntries.sort((conf1, conf2) =>
|
this._configEntries = configEntries.sort((conf1, conf2) =>
|
||||||
compare(conf1.title, conf2.title)
|
compare(conf1.domain + conf1.title, conf2.domain + conf2.title)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (this._unsubs) {
|
if (this._unsubs) {
|
||||||
|
@ -1307,6 +1307,17 @@
|
|||||||
"none": "Nothing configured yet",
|
"none": "Nothing configured yet",
|
||||||
"integration_not_found": "Integration not found.",
|
"integration_not_found": "Integration not found.",
|
||||||
"details": "Integration details",
|
"details": "Integration details",
|
||||||
|
"ignore": {
|
||||||
|
"ignore": "Ignore",
|
||||||
|
"confirm_ignore_title": "Ignore discovery of {name}?",
|
||||||
|
"confirm_ignore": "Are you sure you don't want to setup this integration? You can undo this by clicking the 'Show ignored integrations' in the overflow menu on the top right.",
|
||||||
|
"show_ignored": "Show ignored integrations",
|
||||||
|
"hide_ignored": "Hide ignored integrations",
|
||||||
|
"ignored": "Ignored",
|
||||||
|
"confirm_delete_ignore_title": "Stop ignoring {name}?",
|
||||||
|
"confirm_delete_ignore": "This will make the integration appear in your discovered integrations again when it gets discovered. This might require a restart or take some time.",
|
||||||
|
"stop_ignore": "Stop ignoring"
|
||||||
|
},
|
||||||
"config_entry": {
|
"config_entry": {
|
||||||
"settings_button": "Edit settings for {integration}",
|
"settings_button": "Edit settings for {integration}",
|
||||||
"system_options_button": "System options for {integration}",
|
"system_options_button": "System options for {integration}",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user