mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 16:26:43 +00:00
Use subscribe for todo items (#18776)
This commit is contained in:
parent
db68c7faa9
commit
ffb19b31a5
@ -47,15 +47,25 @@ export interface TodoItems {
|
|||||||
|
|
||||||
export const fetchItems = async (
|
export const fetchItems = async (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entityId: string
|
entity_id: string
|
||||||
): Promise<TodoItem[]> => {
|
): Promise<TodoItem[]> => {
|
||||||
const result = await hass.callWS<TodoItems>({
|
const result = await hass.callWS<TodoItems>({
|
||||||
type: "todo/item/list",
|
type: "todo/item/list",
|
||||||
entity_id: entityId,
|
entity_id,
|
||||||
});
|
});
|
||||||
return result.items;
|
return result.items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const subscribeItems = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_id: string,
|
||||||
|
callback: (item) => void
|
||||||
|
) =>
|
||||||
|
hass.connection.subscribeMessage<any>(callback, {
|
||||||
|
type: "todo/item/subscribe",
|
||||||
|
entity_id,
|
||||||
|
});
|
||||||
|
|
||||||
export const updateItem = (
|
export const updateItem = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_id: string,
|
entity_id: string,
|
||||||
|
@ -24,36 +24,32 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
|
|||||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-checkbox";
|
import "../../../components/ha-checkbox";
|
||||||
|
import "../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-list-item";
|
import "../../../components/ha-list-item";
|
||||||
import "../../../components/ha-select";
|
import "../../../components/ha-select";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import "../../../components/ha-icon-button";
|
|
||||||
import "../../../components/ha-textfield";
|
import "../../../components/ha-textfield";
|
||||||
import type { HaTextField } from "../../../components/ha-textfield";
|
import type { HaTextField } from "../../../components/ha-textfield";
|
||||||
|
import { isUnavailableState } from "../../../data/entity";
|
||||||
import {
|
import {
|
||||||
TodoItem,
|
TodoItem,
|
||||||
TodoItemStatus,
|
TodoItemStatus,
|
||||||
TodoListEntityFeature,
|
TodoListEntityFeature,
|
||||||
createItem,
|
createItem,
|
||||||
deleteItems,
|
deleteItems,
|
||||||
fetchItems,
|
|
||||||
moveItem,
|
moveItem,
|
||||||
|
subscribeItems,
|
||||||
updateItem,
|
updateItem,
|
||||||
} from "../../../data/todo";
|
} from "../../../data/todo";
|
||||||
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
|
||||||
import type { SortableInstance } from "../../../resources/sortable";
|
import type { SortableInstance } from "../../../resources/sortable";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { findEntities } from "../common/find-entities";
|
import { findEntities } from "../common/find-entities";
|
||||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { TodoListCardConfig } from "./types";
|
import { TodoListCardConfig } from "./types";
|
||||||
import { isUnavailableState } from "../../../data/entity";
|
|
||||||
|
|
||||||
@customElement("hui-todo-list-card")
|
@customElement("hui-todo-list-card")
|
||||||
export class HuiTodoListCard
|
export class HuiTodoListCard extends LitElement implements LovelaceCard {
|
||||||
extends SubscribeMixin(LitElement)
|
|
||||||
implements LovelaceCard
|
|
||||||
{
|
|
||||||
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
await import("../editor/config-elements/hui-todo-list-editor");
|
await import("../editor/config-elements/hui-todo-list-editor");
|
||||||
return document.createElement("hui-todo-list-card-editor");
|
return document.createElement("hui-todo-list-card-editor");
|
||||||
@ -87,10 +83,24 @@ export class HuiTodoListCard
|
|||||||
|
|
||||||
@state() private _reordering = false;
|
@state() private _reordering = false;
|
||||||
|
|
||||||
|
private _unsubItems?: Promise<UnsubscribeFunc>;
|
||||||
|
|
||||||
private _sortable?: SortableInstance;
|
private _sortable?: SortableInstance;
|
||||||
|
|
||||||
@query("#unchecked") private _uncheckedContainer?: HTMLElement;
|
@query("#unchecked") private _uncheckedContainer?: HTMLElement;
|
||||||
|
|
||||||
|
connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this.hasUpdated) {
|
||||||
|
this._subscribeItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._unsubItems?.then((unsub) => unsub());
|
||||||
|
}
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return (this._config ? (this._config.title ? 2 : 0) : 0) + 3;
|
return (this._config ? (this._config.title ? 2 : 0) : 0) + 3;
|
||||||
}
|
}
|
||||||
@ -132,26 +142,13 @@ export class HuiTodoListCard
|
|||||||
if (!this._entityId) {
|
if (!this._entityId) {
|
||||||
this._entityId = this.getEntityId();
|
this._entityId = this.getEntityId();
|
||||||
}
|
}
|
||||||
this._fetchData();
|
this._subscribeItems();
|
||||||
} else if (changedProperties.has("_entityId") || !this._items) {
|
} else if (changedProperties.has("_entityId") || !this._items) {
|
||||||
this._items = undefined;
|
this._items = undefined;
|
||||||
this._fetchData();
|
this._subscribeItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public hassSubscribe(): Promise<UnsubscribeFunc>[] {
|
|
||||||
return [
|
|
||||||
this.hass!.connection.subscribeEvents(() => {
|
|
||||||
if (
|
|
||||||
this._entityId &&
|
|
||||||
this.hass!.entities[this._entityId]?.platform === "shopping_list"
|
|
||||||
) {
|
|
||||||
this._fetchData();
|
|
||||||
}
|
|
||||||
}, "shopping_list_updated"),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
if (!this._config || !this.hass) {
|
if (!this._config || !this.hass) {
|
||||||
@ -169,15 +166,6 @@ export class HuiTodoListCard
|
|||||||
) {
|
) {
|
||||||
applyThemesOnElement(this, this.hass.themes, this._config.theme);
|
applyThemesOnElement(this, this.hass.themes, this._config.theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
this._entityId &&
|
|
||||||
oldHass &&
|
|
||||||
oldHass.states[this._entityId] !== this.hass.states[this._entityId] &&
|
|
||||||
this.hass.entities[this._entityId]?.platform !== "shopping_list"
|
|
||||||
) {
|
|
||||||
this._fetchData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@ -392,14 +380,20 @@ export class HuiTodoListCard
|
|||||||
return entityStateObj && supportsFeature(entityStateObj, feature);
|
return entityStateObj && supportsFeature(entityStateObj, feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchData(): Promise<void> {
|
private async _subscribeItems(): Promise<void> {
|
||||||
|
if (this._unsubItems) {
|
||||||
|
this._unsubItems.then((unsub) => unsub());
|
||||||
|
this._unsubItems = undefined;
|
||||||
|
}
|
||||||
if (!this.hass || !this._entityId) {
|
if (!this.hass || !this._entityId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(this._entityId in this.hass.states)) {
|
if (!(this._entityId in this.hass.states)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._items = await fetchItems(this.hass!, this._entityId!);
|
this._unsubItems = subscribeItems(this.hass!, this._entityId, (update) => {
|
||||||
|
this._items = update.items;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getItem(itemId: string) {
|
private _getItem(itemId: string) {
|
||||||
@ -416,7 +410,7 @@ export class HuiTodoListCard
|
|||||||
status: ev.target.checked
|
status: ev.target.checked
|
||||||
? TodoItemStatus.Completed
|
? TodoItemStatus.Completed
|
||||||
: TodoItemStatus.NeedsAction,
|
: TodoItemStatus.NeedsAction,
|
||||||
}).finally(() => this._fetchData());
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _saveEdit(ev): void {
|
private _saveEdit(ev): void {
|
||||||
@ -429,13 +423,11 @@ export class HuiTodoListCard
|
|||||||
updateItem(this.hass!, this._entityId!, {
|
updateItem(this.hass!, this._entityId!, {
|
||||||
...item,
|
...item,
|
||||||
summary: ev.target.value,
|
summary: ev.target.value,
|
||||||
}).finally(() => this._fetchData());
|
});
|
||||||
} else if (
|
} else if (
|
||||||
this.todoListSupportsFeature(TodoListEntityFeature.DELETE_TODO_ITEM)
|
this.todoListSupportsFeature(TodoListEntityFeature.DELETE_TODO_ITEM)
|
||||||
) {
|
) {
|
||||||
deleteItems(this.hass!, this._entityId!, [ev.target.itemId]).finally(() =>
|
deleteItems(this.hass!, this._entityId!, [ev.target.itemId]);
|
||||||
this._fetchData()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
@ -447,9 +439,7 @@ export class HuiTodoListCard
|
|||||||
}
|
}
|
||||||
const checkedItems = this._getCheckedItems(this._items);
|
const checkedItems = this._getCheckedItems(this._items);
|
||||||
const uids = checkedItems.map((item: TodoItem) => item.uid);
|
const uids = checkedItems.map((item: TodoItem) => item.uid);
|
||||||
deleteItems(this.hass!, this._entityId!, uids).finally(() =>
|
deleteItems(this.hass!, this._entityId!, uids);
|
||||||
this._fetchData()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _newItem(): HaTextField {
|
private get _newItem(): HaTextField {
|
||||||
@ -459,9 +449,7 @@ export class HuiTodoListCard
|
|||||||
private _addItem(ev): void {
|
private _addItem(ev): void {
|
||||||
const newItem = this._newItem;
|
const newItem = this._newItem;
|
||||||
if (newItem.value!.length > 0) {
|
if (newItem.value!.length > 0) {
|
||||||
createItem(this.hass!, this._entityId!, newItem.value!).finally(() =>
|
createItem(this.hass!, this._entityId!, newItem.value!);
|
||||||
this._fetchData()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newItem.value = "";
|
newItem.value = "";
|
||||||
@ -475,9 +463,7 @@ export class HuiTodoListCard
|
|||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deleteItems(this.hass!, this._entityId!, [item.uid]).finally(() =>
|
deleteItems(this.hass!, this._entityId!, [item.uid]);
|
||||||
this._fetchData()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addKeyPress(ev): void {
|
private _addKeyPress(ev): void {
|
||||||
@ -552,12 +538,7 @@ export class HuiTodoListCard
|
|||||||
}
|
}
|
||||||
this._items = [...this._items!];
|
this._items = [...this._items!];
|
||||||
|
|
||||||
await moveItem(
|
await moveItem(this.hass!, this._entityId!, item.uid, prevItem?.uid);
|
||||||
this.hass!,
|
|
||||||
this._entityId!,
|
|
||||||
item.uid,
|
|
||||||
prevItem?.uid
|
|
||||||
).finally(() => this._fetchData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user