mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 04:16:34 +00:00
Better disabled/error handling on config/helpers
page (#22237)
* Add a way to fix/remove broken helpers * more disabled/sources fixes * Update src/translations/en.json Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com> * Update ha-config-helpers.ts --------- Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
This commit is contained in:
parent
9e002f7940
commit
e1830470b6
@ -3,19 +3,23 @@ import { ResizeController } from "@lit-labs/observers/resize-controller";
|
||||
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
||||
import {
|
||||
mdiAlertCircle,
|
||||
mdiCancel,
|
||||
mdiChevronRight,
|
||||
mdiCog,
|
||||
mdiDotsVertical,
|
||||
mdiMenuDown,
|
||||
mdiPencilOff,
|
||||
mdiProgressHelper,
|
||||
mdiPlus,
|
||||
mdiTag,
|
||||
mdiTrashCan,
|
||||
} from "@mdi/js";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { debounce } from "../../../common/util/debounce";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||
@ -54,7 +58,11 @@ import {
|
||||
subscribeCategoryRegistry,
|
||||
} from "../../../data/category_registry";
|
||||
import type { ConfigEntry } from "../../../data/config_entries";
|
||||
import { subscribeConfigEntries } from "../../../data/config_entries";
|
||||
import {
|
||||
ERROR_STATES,
|
||||
deleteConfigEntry,
|
||||
subscribeConfigEntries,
|
||||
} from "../../../data/config_entries";
|
||||
import { getConfigFlowHandlers } from "../../../data/config_flow";
|
||||
import { fullEntitiesContext } from "../../../data/context";
|
||||
import type {
|
||||
@ -97,6 +105,7 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
|
||||
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
import { renderConfigEntryError } from "../integrations/ha-config-integration-page";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import { isHelperDomain } from "./const";
|
||||
import { showHelperDetailDialog } from "./show-dialog-helper-detail";
|
||||
@ -220,6 +229,12 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
callback: (entries) => entries[0]?.contentRect.width,
|
||||
});
|
||||
|
||||
private _debouncedFetchEntitySources = debounce(
|
||||
() => this._fetchEntitySources(),
|
||||
500,
|
||||
false
|
||||
);
|
||||
|
||||
public hassSubscribe() {
|
||||
return [
|
||||
subscribeConfigEntries(
|
||||
@ -236,6 +251,14 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
} else if (message.type === "updated") {
|
||||
newEntries[message.entry.entry_id] = message.entry;
|
||||
}
|
||||
if (
|
||||
this._entitySource &&
|
||||
this._configEntries &&
|
||||
message.entry.state === "loaded" &&
|
||||
this._configEntries[message.entry.entry_id]?.state !== "loaded"
|
||||
) {
|
||||
this._debouncedFetchEntitySources();
|
||||
}
|
||||
});
|
||||
this._configEntries = newEntries;
|
||||
},
|
||||
@ -352,6 +375,19 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
.hass=${this.hass}
|
||||
narrow
|
||||
.items=${[
|
||||
...(helper.configEntry &&
|
||||
ERROR_STATES.includes(helper.configEntry.state)
|
||||
? [
|
||||
{
|
||||
path: mdiAlertCircle,
|
||||
label: this.hass.localize(
|
||||
"ui.panel.config.helpers.picker.error_information"
|
||||
),
|
||||
warning: true,
|
||||
action: () => this._showError(helper),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
path: mdiCog,
|
||||
label: this.hass.localize(
|
||||
@ -366,6 +402,19 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
),
|
||||
action: () => this._editCategory(helper),
|
||||
},
|
||||
...(helper.configEntry &&
|
||||
helper.editable &&
|
||||
ERROR_STATES.includes(helper.configEntry.state) &&
|
||||
helper.entity === undefined
|
||||
? [
|
||||
{
|
||||
path: mdiTrashCan,
|
||||
label: this.hass.localize("ui.common.delete"),
|
||||
warning: true,
|
||||
action: () => this._deleteEntry(helper),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]}
|
||||
>
|
||||
</ha-icon-overflow-menu>
|
||||
@ -417,17 +466,27 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
};
|
||||
});
|
||||
|
||||
const entries = Object.values(configEntriesCopy).map((configEntry) => ({
|
||||
id: configEntry.entry_id,
|
||||
entity_id: "",
|
||||
icon: mdiAlertCircle,
|
||||
name: configEntry.title || "",
|
||||
editable: true,
|
||||
type: configEntry.domain,
|
||||
configEntry,
|
||||
entity: undefined,
|
||||
selectable: false,
|
||||
}));
|
||||
const entries = Object.values(configEntriesCopy).map((configEntry) => {
|
||||
const entityEntry = Object.values(entityEntries).find(
|
||||
(entry) => entry.config_entry_id === configEntry.entry_id
|
||||
);
|
||||
const entityIsDisabled = !!entityEntry?.disabled_by;
|
||||
return {
|
||||
id: entityIsDisabled ? entityEntry.entity_id : configEntry.entry_id,
|
||||
entity_id: entityIsDisabled ? entityEntry.entity_id : "",
|
||||
icon: entityIsDisabled
|
||||
? mdiCancel
|
||||
: configEntry.state === "setup_in_progress"
|
||||
? mdiProgressHelper
|
||||
: mdiAlertCircle,
|
||||
name: configEntry.title || "",
|
||||
editable: true,
|
||||
type: configEntry.domain,
|
||||
configEntry,
|
||||
entity: undefined,
|
||||
selectable: entityIsDisabled,
|
||||
};
|
||||
});
|
||||
|
||||
return [...states, ...entries]
|
||||
.filter((item) =>
|
||||
@ -1081,6 +1140,34 @@ ${rejected
|
||||
}
|
||||
}
|
||||
|
||||
private _showError(helper: HelperItem) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.errors.config.configuration_error"),
|
||||
text: renderConfigEntryError(this.hass, helper.configEntry!),
|
||||
warning: true,
|
||||
});
|
||||
}
|
||||
|
||||
private async _deleteEntry(helper: HelperItem) {
|
||||
const confirmed = await showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.delete_confirm_title",
|
||||
{ title: helper.configEntry!.title }
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.delete_confirm_text"
|
||||
),
|
||||
confirmText: this.hass!.localize("ui.common.delete"),
|
||||
dismissText: this.hass!.localize("ui.common.cancel"),
|
||||
destructive: true,
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
deleteConfigEntry(this.hass, helper.id);
|
||||
}
|
||||
|
||||
private _openSettings(helper: HelperItem) {
|
||||
if (helper.entity) {
|
||||
showMoreInfoDialog(this, {
|
||||
|
@ -106,6 +106,38 @@ import { fileDownload } from "../../../util/file_download";
|
||||
import type { DataEntryFlowProgressExtended } from "./ha-config-integrations";
|
||||
import { showAddIntegrationDialog } from "./show-add-integration-dialog";
|
||||
|
||||
export const renderConfigEntryError = (
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry
|
||||
): TemplateResult => {
|
||||
if (entry.reason) {
|
||||
if (entry.error_reason_translation_key) {
|
||||
const lokalisePromExc = hass
|
||||
.loadBackendTranslation("exceptions", entry.domain)
|
||||
.then(
|
||||
(localize) =>
|
||||
localize(
|
||||
`component.${entry.domain}.exceptions.${entry.error_reason_translation_key}.message`,
|
||||
entry.error_reason_translation_placeholders ?? undefined
|
||||
) || entry.reason
|
||||
);
|
||||
return html`${until(lokalisePromExc)}`;
|
||||
}
|
||||
const lokalisePromError = hass
|
||||
.loadBackendTranslation("config", entry.domain)
|
||||
.then(
|
||||
(localize) =>
|
||||
localize(`component.${entry.domain}.config.error.${entry.reason}`) ||
|
||||
entry.reason
|
||||
);
|
||||
return html`${until(lokalisePromError, entry.reason)}`;
|
||||
}
|
||||
return html`
|
||||
<br />
|
||||
${hass.localize("ui.panel.config.integrations.config_entry.check_the_logs")}
|
||||
`;
|
||||
};
|
||||
|
||||
@customElement("ha-config-integration-page")
|
||||
class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@ -618,37 +650,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
|
||||
stateText = [
|
||||
`ui.panel.config.integrations.config_entry.state.${item.state}`,
|
||||
];
|
||||
if (item.reason) {
|
||||
if (item.error_reason_translation_key) {
|
||||
const lokalisePromExc = this.hass
|
||||
.loadBackendTranslation("exceptions", item.domain)
|
||||
.then(
|
||||
(localize) =>
|
||||
localize(
|
||||
`component.${item.domain}.exceptions.${item.error_reason_translation_key}.message`,
|
||||
item.error_reason_translation_placeholders ?? undefined
|
||||
) || item.reason
|
||||
);
|
||||
stateTextExtra = html`${until(lokalisePromExc)}`;
|
||||
} else {
|
||||
const lokalisePromError = this.hass
|
||||
.loadBackendTranslation("config", item.domain)
|
||||
.then(
|
||||
(localize) =>
|
||||
localize(
|
||||
`component.${item.domain}.config.error.${item.reason}`
|
||||
) || item.reason
|
||||
);
|
||||
stateTextExtra = html`${until(lokalisePromError, item.reason)}`;
|
||||
}
|
||||
} else {
|
||||
stateTextExtra = html`
|
||||
<br />
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.check_the_logs"
|
||||
)}
|
||||
`;
|
||||
}
|
||||
stateTextExtra = renderConfigEntryError(this.hass, item);
|
||||
}
|
||||
|
||||
const devices = this._getConfigEntryDevices(item);
|
||||
|
@ -2343,7 +2343,8 @@
|
||||
},
|
||||
"create_helper": "Create helper",
|
||||
"no_helpers": "Looks like you don't have any helpers yet!",
|
||||
"search": "Search {number} helpers"
|
||||
"search": "Search {number} helpers",
|
||||
"error_information": "Error information"
|
||||
},
|
||||
"dialog": {
|
||||
"create": "Create",
|
||||
|
Loading…
x
Reference in New Issue
Block a user