Handle errors in multi select (#20494)
This commit is contained in:
parent
c96968e476
commit
ab49aca815
|
@ -0,0 +1,9 @@
|
|||
export const hasRejectedItems = <T = any>(results: PromiseSettledResult<T>[]) =>
|
||||
results.some((result) => result.status === "rejected");
|
||||
|
||||
export const rejectedItems = <T = any>(
|
||||
results: PromiseSettledResult<T>[]
|
||||
): PromiseRejectedResult[] =>
|
||||
results.filter(
|
||||
(result) => result.status === "rejected"
|
||||
) as PromiseRejectedResult[];
|
|
@ -105,6 +105,10 @@ import { showCategoryRegistryDetailDialog } from "../category/show-dialog-catego
|
|||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import { showNewAutomationDialog } from "./show-dialog-new-automation";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
|
||||
type AutomationItem = AutomationEntity & {
|
||||
name: string;
|
||||
|
@ -196,6 +200,7 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
|||
labels: (labels || []).map(
|
||||
(lbl) => labelReg!.find((label) => label.label_id === lbl)!
|
||||
),
|
||||
selectable: entityRegEntry !== undefined,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -1112,7 +1117,20 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkLabel(ev) {
|
||||
|
@ -1135,7 +1153,20 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkEnable() {
|
||||
|
@ -1143,7 +1174,20 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
|||
this._selected.forEach((entityId) => {
|
||||
promises.push(turnOnOffEntity(this.hass, entityId, true));
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkDisable() {
|
||||
|
@ -1151,7 +1195,20 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
|
|||
this._selected.forEach((entityId) => {
|
||||
promises.push(turnOnOffEntity(this.hass, entityId, false));
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _bulkCreateCategory() {
|
||||
|
|
|
@ -69,6 +69,11 @@ import { configSections } from "../ha-panel-config";
|
|||
import "../integrations/ha-integration-overflow-menu";
|
||||
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
import { showAlertDialog } from "../../lovelace/custom-card-helpers";
|
||||
|
||||
interface DeviceRowData extends DeviceRegistryEntry {
|
||||
device?: DeviceRowData;
|
||||
|
@ -824,7 +829,20 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _bulkCreateLabel() {
|
||||
|
|
|
@ -90,6 +90,10 @@ import {
|
|||
EntitySources,
|
||||
fetchEntitySourcesWithCache,
|
||||
} from "../../../data/entity_sources";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
|
||||
export interface StateEntity
|
||||
extends Omit<EntityRegistryEntry, "id" | "unique_id"> {
|
||||
|
@ -957,19 +961,41 @@ ${
|
|||
confirm: async () => {
|
||||
let require_restart = false;
|
||||
let reload_delay = 0;
|
||||
await Promise.all(
|
||||
const result = await Promise.allSettled(
|
||||
this._selected.map(async (entity) => {
|
||||
const result = await updateEntityRegistryEntry(this.hass, entity, {
|
||||
disabled_by: null,
|
||||
});
|
||||
if (result.require_restart) {
|
||||
const updateResult = await updateEntityRegistryEntry(
|
||||
this.hass,
|
||||
entity,
|
||||
{
|
||||
disabled_by: null,
|
||||
}
|
||||
);
|
||||
if (updateResult.require_restart) {
|
||||
require_restart = true;
|
||||
}
|
||||
if (result.reload_delay) {
|
||||
reload_delay = Math.max(reload_delay, result.reload_delay);
|
||||
if (updateResult.reload_delay) {
|
||||
reload_delay = Math.max(reload_delay, updateResult.reload_delay);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.common.multiselect.failed",
|
||||
{
|
||||
number: rejected.length,
|
||||
}
|
||||
),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
|
||||
this._clearSelection();
|
||||
// If restart is required by any entity, show a dialog.
|
||||
// Otherwise, show a dialog explaining that some patience is needed
|
||||
|
@ -1068,7 +1094,20 @@ ${
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _bulkCreateLabel() {
|
||||
|
|
|
@ -32,6 +32,10 @@ import {
|
|||
LocalizeKeys,
|
||||
} from "../../../common/translations/localize";
|
||||
import { extractSearchParam } from "../../../common/url/search-params";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
|
@ -801,7 +805,20 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkLabel(ev) {
|
||||
|
@ -824,7 +841,20 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _handleSelectionChanged(
|
||||
|
|
|
@ -95,6 +95,10 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
|
|||
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
|
||||
type SceneItem = SceneEntity & {
|
||||
name: string;
|
||||
|
@ -178,6 +182,7 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
|||
labels: (labels || []).map(
|
||||
(lbl) => labelReg!.find((label) => label.label_id === lbl)!
|
||||
),
|
||||
selectable: entityRegEntry !== undefined,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -798,7 +803,20 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkLabel(ev) {
|
||||
|
@ -821,7 +839,20 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _editCategory(scene: any) {
|
||||
|
|
|
@ -97,6 +97,10 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor
|
|||
import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
hasRejectedItems,
|
||||
rejectedItems,
|
||||
} from "../../../common/util/promise-all-settled-results";
|
||||
|
||||
type ScriptItem = ScriptEntity & {
|
||||
name: string;
|
||||
|
@ -185,6 +189,7 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
|||
labels: (labels || []).map(
|
||||
(lbl) => labelReg!.find((label) => label.label_id === lbl)!
|
||||
),
|
||||
selectable: entityRegEntry !== undefined,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -867,7 +872,20 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleBulkLabel(ev) {
|
||||
|
@ -890,7 +908,20 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
|||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
const result = await Promise.allSettled(promises);
|
||||
if (hasRejectedItems(result)) {
|
||||
const rejected = rejectedItems(result);
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.config.common.multiselect.failed", {
|
||||
number: rejected.length,
|
||||
}),
|
||||
text: html`<pre>
|
||||
${rejected
|
||||
.map((r) => r.reason.message || r.reason.code || r.reason)
|
||||
.join("\r\n")}</pre
|
||||
>`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||
|
|
|
@ -1867,6 +1867,7 @@
|
|||
"editor": {
|
||||
"confirm_unsaved": "You have unsaved changes. Are you sure you want to leave?"
|
||||
},
|
||||
"multiselect": { "failed": "Failed to update {number} items." },
|
||||
"learn_more": "Learn more"
|
||||
},
|
||||
"updates": {
|
||||
|
|
Loading…
Reference in New Issue