ha-frontend/src/panels/lovelace/editor/conditions/types/ha-card-condition-user.ts

123 lines
3.4 KiB
TypeScript

import "@material/mwc-list";
import { LitElement, PropertyValues, css, html } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { array, assert, literal, object, string } from "superstruct";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { stringCompare } from "../../../../../common/string/compare";
import "../../../../../components/ha-check-list-item";
import "../../../../../components/ha-switch";
import "../../../../../components/user/ha-user-badge";
import { User, fetchUsers } from "../../../../../data/user";
import type { HomeAssistant } from "../../../../../types";
import { LovelaceUserCondition } from "../../../common/conditions/types";
const userConditionStruct = object({
condition: literal("user"),
users: array(string()),
});
@customElement("ha-card-condition-user")
export class HaCardConditionUser extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public condition!: LovelaceUserCondition;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig(): LovelaceUserCondition {
return { condition: "user", users: [] };
}
@state() private _users: User[] = [];
protected static validateUIConfig(condition: LovelaceUserCondition) {
return assert(condition, userConditionStruct);
}
private _sortedUsers = memoizeOne((users: User[]) =>
users.sort((a, b) =>
stringCompare(a.name, b.name, this.hass.locale.language)
)
);
protected async firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this._fetchUsers();
}
private async _fetchUsers() {
const users = await fetchUsers(this.hass);
this._users = users.filter((user) => !user.system_generated);
}
protected render() {
const selectedUsers = this.condition.users ?? [];
return html`
<mwc-list>
${this._sortedUsers(this._users).map(
(user) => html`
<ha-check-list-item
graphic="avatar"
hasMeta
.userId=${user.id}
.selected=${selectedUsers.includes(user.id)}
@request-selected=${this._userChanged}
>
<ha-user-badge
slot="graphic"
.hass=${this.hass}
.user=${user}
></ha-user-badge>
<span>${user.name}</span>
</ha-check-list-item>
`
)}
</mwc-list>
`;
}
private _userChanged(ev) {
ev.stopPropagation();
const selectedUsers = this.condition.users ?? [];
const userId = ev.currentTarget.userId as string;
const checked = ev.detail.selected as boolean;
if (checked === selectedUsers.includes(userId)) {
return;
}
let users = selectedUsers;
if (checked) {
users = [...users, userId];
} else {
users = users.filter((user) => user !== userId);
}
const condition: LovelaceUserCondition = {
...this.condition,
users,
};
fireEvent(this, "value-changed", { value: condition });
}
static get styles() {
return css`
:host {
display: block;
}
mwc-list {
--mdc-list-vertical-padding: 0;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-card-condition-user": HaCardConditionUser;
}
}