mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Allow picking users (#2768)
* Allow picking users * Update ha-user-badge.ts
This commit is contained in:
parent
2d3d4db4dd
commit
c7796e9557
@ -6,7 +6,6 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
property,
|
property,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
@ -14,27 +13,12 @@ import "@polymer/paper-item/paper-item";
|
|||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
|
|
||||||
|
import "../components/user/ha-user-badge";
|
||||||
import isComponentLoaded from "../common/config/is_component_loaded";
|
import isComponentLoaded from "../common/config/is_component_loaded";
|
||||||
import { HomeAssistant, Panel } from "../types";
|
import { HomeAssistant, Panel } from "../types";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { DEFAULT_PANEL } from "../common/const";
|
import { DEFAULT_PANEL } from "../common/const";
|
||||||
|
|
||||||
const computeInitials = (name: string) => {
|
|
||||||
if (!name) {
|
|
||||||
return "user";
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
name
|
|
||||||
.trim()
|
|
||||||
// Split by space and take first 3 words
|
|
||||||
.split(" ")
|
|
||||||
.slice(0, 3)
|
|
||||||
// Of each word, take first letter
|
|
||||||
.map((s) => s.substr(0, 1))
|
|
||||||
.join("")
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const computeUrl = (urlPath) => `/${urlPath}`;
|
const computeUrl = (urlPath) => `/${urlPath}`;
|
||||||
|
|
||||||
const computePanels = (hass: HomeAssistant) => {
|
const computePanels = (hass: HomeAssistant) => {
|
||||||
@ -93,22 +77,13 @@ class HaSidebar extends LitElement {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initials = hass.user ? computeInitials(hass.user.name) : "";
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<app-toolbar>
|
<app-toolbar>
|
||||||
<div main-title>Home Assistant</div>
|
<div main-title>Home Assistant</div>
|
||||||
${hass.user
|
${hass.user
|
||||||
? html`
|
? html`
|
||||||
<a
|
<a href="/profile">
|
||||||
href="/profile"
|
<ha-user-badge user=${hass.user}></ha-user-badge>
|
||||||
class="${classMap({
|
|
||||||
"profile-badge": true,
|
|
||||||
long: initials.length > 2,
|
|
||||||
})}"
|
|
||||||
>
|
|
||||||
<paper-ripple></paper-ripple>
|
|
||||||
${initials}
|
|
||||||
</a>
|
</a>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -344,23 +319,6 @@ class HaSidebar extends LitElement {
|
|||||||
.dev-tools a {
|
.dev-tools a {
|
||||||
color: var(--sidebar-icon-color);
|
color: var(--sidebar-icon-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-badge {
|
|
||||||
/* for ripple */
|
|
||||||
position: relative;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
border-radius: 50%;
|
|
||||||
text-align: center;
|
|
||||||
background-color: var(--light-primary-color);
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-badge.long {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
77
src/components/user/ha-user-badge.ts
Normal file
77
src/components/user/ha-user-badge.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
html,
|
||||||
|
property,
|
||||||
|
customElement,
|
||||||
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
import { User } from "../../data/auth";
|
||||||
|
import { CurrentUser } from "../../types";
|
||||||
|
|
||||||
|
const computeInitials = (name: string) => {
|
||||||
|
if (!name) {
|
||||||
|
return "user";
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
name
|
||||||
|
.trim()
|
||||||
|
// Split by space and take first 3 words
|
||||||
|
.split(" ")
|
||||||
|
.slice(0, 3)
|
||||||
|
// Of each word, take first letter
|
||||||
|
.map((s) => s.substr(0, 1))
|
||||||
|
.join("")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("ha-user-badge")
|
||||||
|
class StateBadge extends LitElement {
|
||||||
|
@property() public user?: User | CurrentUser;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
const user = this.user;
|
||||||
|
|
||||||
|
const initials = user ? computeInitials(user.name) : "?";
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class="${classMap({
|
||||||
|
"profile-badge": true,
|
||||||
|
long: initials.length > 2,
|
||||||
|
})}"
|
||||||
|
>
|
||||||
|
${initials}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
.profile-badge {
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
text-align: center;
|
||||||
|
background-color: var(--light-primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-badge.long {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-user-badge": StateBadge;
|
||||||
|
}
|
||||||
|
}
|
104
src/components/user/ha-user-picker.ts
Normal file
104
src/components/user/ha-user-picker.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { User, fetchUsers } from "../../data/auth";
|
||||||
|
import compare from "../../common/string/compare";
|
||||||
|
|
||||||
|
class HaEntityPicker extends LitElement {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
@property() public label?: string;
|
||||||
|
@property() public value?: string;
|
||||||
|
@property() public users?: User[];
|
||||||
|
|
||||||
|
private _sortedUsers = memoizeOne((users?: User[]) => {
|
||||||
|
if (!users || users.length === 1) {
|
||||||
|
return users || [];
|
||||||
|
}
|
||||||
|
const sorted = [...users];
|
||||||
|
sorted.sort((a, b) => compare(a.name, b.name));
|
||||||
|
return sorted;
|
||||||
|
});
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
<paper-dropdown-menu-light .label=${this.label}>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
.selected=${this._value}
|
||||||
|
attr-for-selected="data-user-id"
|
||||||
|
@iron-select=${this._userChanged}
|
||||||
|
>
|
||||||
|
<paper-icon-item data-user-id="">
|
||||||
|
No user
|
||||||
|
</paper-icon-item>
|
||||||
|
${this._sortedUsers(this.users).map(
|
||||||
|
(user) => html`
|
||||||
|
<paper-icon-item data-user-id=${user.id}>
|
||||||
|
<ha-user-badge .user=${user} slot="item-icon"></ha-user-badge>
|
||||||
|
${user.name}
|
||||||
|
</paper-icon-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu-light>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _value() {
|
||||||
|
return this.value || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
if (this.users === undefined) {
|
||||||
|
fetchUsers(this.hass!).then((users) => {
|
||||||
|
this.users = users;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _userChanged(ev) {
|
||||||
|
const newValue = ev.detail.item.dataset.userId;
|
||||||
|
|
||||||
|
if (newValue !== this._value) {
|
||||||
|
this.value = ev.detail.value;
|
||||||
|
setTimeout(() => {
|
||||||
|
fireEvent(this, "value-changed", { value: newValue });
|
||||||
|
fireEvent(this, "change");
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
paper-dropdown-menu-light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
paper-listbox {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
paper-icon-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("ha-user-picker", HaEntityPicker);
|
@ -1,5 +1,26 @@
|
|||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
export interface AuthProvider {
|
export interface AuthProvider {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Credential {
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
is_owner: boolean;
|
||||||
|
is_active: boolean;
|
||||||
|
system_generated: boolean;
|
||||||
|
group_ids: string[];
|
||||||
|
credentials: Credential[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchUsers = async (hass: HomeAssistant) =>
|
||||||
|
hass.callWS<User[]>({
|
||||||
|
type: "config/auth/list",
|
||||||
|
});
|
||||||
|
@ -3,12 +3,17 @@ import {
|
|||||||
Connection,
|
Connection,
|
||||||
getCollection,
|
getCollection,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { User } from "../types";
|
import { CurrentUser } from "../types";
|
||||||
|
|
||||||
export const userCollection = (conn: Connection) =>
|
export const userCollection = (conn: Connection) =>
|
||||||
getCollection(conn, "_usr", () => getUser(conn) as Promise<User>, undefined);
|
getCollection(
|
||||||
|
conn,
|
||||||
|
"_usr",
|
||||||
|
() => getUser(conn) as Promise<CurrentUser>,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
export const subscribeUser = (
|
export const subscribeUser = (
|
||||||
conn: Connection,
|
conn: Connection,
|
||||||
onChange: (user: User) => void
|
onChange: (user: CurrentUser) => void
|
||||||
) => userCollection(conn).subscribe(onChange);
|
) => userCollection(conn).subscribe(onChange);
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "../components/ha-menu-button";
|
import "../components/ha-menu-button";
|
||||||
import { haStyle } from "../resources/ha-style";
|
import { haStyle } from "../resources/styles";
|
||||||
|
|
||||||
@customElement("hass-loading-screen")
|
@customElement("hass-loading-screen")
|
||||||
class HassLoadingScreen extends LitElement {
|
class HassLoadingScreen extends LitElement {
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { haStyle } from "../resources/ha-style";
|
import { haStyle } from "../resources/styles";
|
||||||
|
|
||||||
@customElement("hass-subpage")
|
@customElement("hass-subpage")
|
||||||
class HassSubpage extends LitElement {
|
class HassSubpage extends LitElement {
|
||||||
|
@ -12,7 +12,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
|
|
||||||
import { AreaRegistryDetailDialogParams } from "./show-dialog-area-registry-detail";
|
import { AreaRegistryDetailDialogParams } from "./show-dialog-area-registry-detail";
|
||||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import { haStyleDialog } from "../../../resources/ha-style";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { AreaRegistryEntryMutableParams } from "../../../data/area_registry";
|
import { AreaRegistryEntryMutableParams } from "../../../data/area_registry";
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import Automation from "../js/automation";
|
|||||||
import unmountPreact from "../../../common/preact/unmount";
|
import unmountPreact from "../../../common/preact/unmount";
|
||||||
import computeStateName from "../../../common/entity/compute_state_name";
|
import computeStateName from "../../../common/entity/compute_state_name";
|
||||||
|
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { AutomationEntity, AutomationConfig } from "../../../data/automation";
|
import { AutomationEntity, AutomationConfig } from "../../../data/automation";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
|
@ -18,7 +18,7 @@ import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { WebhookDialogParams } from "./types";
|
import { WebhookDialogParams } from "./types";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
|
|
||||||
const inputLabel = "Public URL – Click to copy to clipboard";
|
const inputLabel = "Public URL – Click to copy to clipboard";
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
|
|
||||||
import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail";
|
import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail";
|
||||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import { haStyleDialog } from "../../../resources/ha-style";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import computeDomain from "../../../common/entity/compute_domain";
|
import computeDomain from "../../../common/entity/compute_domain";
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
@ -9,29 +9,37 @@ import {
|
|||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@material/mwc-button";
|
||||||
|
|
||||||
import "../../../components/entity/ha-entities-picker";
|
import "../../../components/entity/ha-entities-picker";
|
||||||
|
import "../../../components/user/ha-user-picker";
|
||||||
import { PersonDetailDialogParams } from "./show-dialog-person-detail";
|
import { PersonDetailDialogParams } from "./show-dialog-person-detail";
|
||||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import { haStyleDialog } from "../../../resources/ha-style";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { PersonMutableParams } from "../../../data/person";
|
import { PersonMutableParams } from "../../../data/person";
|
||||||
|
|
||||||
class DialogPersonDetail extends LitElement {
|
class DialogPersonDetail extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
@property() private _name!: string;
|
@property() private _name!: string;
|
||||||
|
@property() private _userId?: string;
|
||||||
@property() private _deviceTrackers!: string[];
|
@property() private _deviceTrackers!: string[];
|
||||||
@property() private _error?: string;
|
@property() private _error?: string;
|
||||||
@property() private _params?: PersonDetailDialogParams;
|
@property() private _params?: PersonDetailDialogParams;
|
||||||
@property() private _submitting?: boolean;
|
@property() private _submitting: boolean = false;
|
||||||
|
|
||||||
public async showDialog(params: PersonDetailDialogParams): Promise<void> {
|
public async showDialog(params: PersonDetailDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._name = this._params.entry ? this._params.entry.name : "";
|
if (this._params.entry) {
|
||||||
this._deviceTrackers = this._params.entry
|
this._name = this._params.entry.name || "";
|
||||||
? this._params.entry.device_trackers || []
|
this._userId = this._params.entry.user_id || undefined;
|
||||||
: [];
|
this._deviceTrackers = this._params.entry.device_trackers || [];
|
||||||
|
} else {
|
||||||
|
this._name = "";
|
||||||
|
this._userId = undefined;
|
||||||
|
this._deviceTrackers = [];
|
||||||
|
}
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +69,13 @@ class DialogPersonDetail extends LitElement {
|
|||||||
error-message="Name is required"
|
error-message="Name is required"
|
||||||
.invalid=${nameInvalid}
|
.invalid=${nameInvalid}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
|
<ha-user-picker
|
||||||
|
label="Linked User"
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this._userId}
|
||||||
|
.users=${this._params.users}
|
||||||
|
@value-changed=${this._userChanged}
|
||||||
|
></ha-user-picker>
|
||||||
<p>
|
<p>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.person.detail.device_tracker_intro"
|
"ui.panel.config.person.detail.device_tracker_intro"
|
||||||
@ -108,6 +123,11 @@ class DialogPersonDetail extends LitElement {
|
|||||||
this._name = ev.detail.value;
|
this._name = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _userChanged(ev: PolymerChangedEvent<string>) {
|
||||||
|
this._error = undefined;
|
||||||
|
this._userId = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
private _deviceTrackersChanged(ev: PolymerChangedEvent<string[]>) {
|
private _deviceTrackersChanged(ev: PolymerChangedEvent<string[]>) {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._deviceTrackers = ev.detail.value;
|
this._deviceTrackers = ev.detail.value;
|
||||||
@ -119,8 +139,7 @@ class DialogPersonDetail extends LitElement {
|
|||||||
const values: PersonMutableParams = {
|
const values: PersonMutableParams = {
|
||||||
name: this._name.trim(),
|
name: this._name.trim(),
|
||||||
device_trackers: this._deviceTrackers,
|
device_trackers: this._deviceTrackers,
|
||||||
// Temp, we will add this in a future PR.
|
user_id: this._userId || null,
|
||||||
user_id: null,
|
|
||||||
};
|
};
|
||||||
if (this._params!.entry) {
|
if (this._params!.entry) {
|
||||||
await this._params!.updateEntry(values);
|
await this._params!.updateEntry(values);
|
||||||
@ -129,7 +148,7 @@ class DialogPersonDetail extends LitElement {
|
|||||||
}
|
}
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._error = err;
|
this._error = err ? err.message : "Unknown error";
|
||||||
} finally {
|
} finally {
|
||||||
this._submitting = false;
|
this._submitting = false;
|
||||||
}
|
}
|
||||||
@ -162,6 +181,9 @@ class DialogPersonDetail extends LitElement {
|
|||||||
.form {
|
.form {
|
||||||
padding-bottom: 24px;
|
padding-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
ha-user-picker {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
mwc-button.warning {
|
mwc-button.warning {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,14 @@ import {
|
|||||||
showPersonDetailDialog,
|
showPersonDetailDialog,
|
||||||
loadPersonDetailDialog,
|
loadPersonDetailDialog,
|
||||||
} from "./show-dialog-person-detail";
|
} from "./show-dialog-person-detail";
|
||||||
|
import { User, fetchUsers } from "../../../data/auth";
|
||||||
|
|
||||||
class HaConfigPerson extends LitElement {
|
class HaConfigPerson extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
||||||
public isWide?: boolean;
|
public isWide?: boolean;
|
||||||
private _storageItems?: Person[];
|
private _storageItems?: Person[];
|
||||||
private _configItems?: Person[];
|
private _configItems?: Person[];
|
||||||
|
private _usersLoad?: Promise<User[]>;
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
static get properties(): PropertyDeclarations {
|
||||||
return {
|
return {
|
||||||
@ -62,7 +64,7 @@ class HaConfigPerson extends LitElement {
|
|||||||
${this._configItems.length > 0
|
${this._configItems.length > 0
|
||||||
? html`
|
? html`
|
||||||
<p>
|
<p>
|
||||||
Note: people configured via configuration.yaml cannot be
|
Note: persons configured via configuration.yaml cannot be
|
||||||
edited via the UI.
|
edited via the UI.
|
||||||
</p>
|
</p>
|
||||||
`
|
`
|
||||||
@ -81,7 +83,7 @@ class HaConfigPerson extends LitElement {
|
|||||||
${this._storageItems.length === 0
|
${this._storageItems.length === 0
|
||||||
? html`
|
? html`
|
||||||
<div class="empty">
|
<div class="empty">
|
||||||
Looks like you have no people yet!
|
Looks like you have not created any persons yet.
|
||||||
<mwc-button @click=${this._createPerson}>
|
<mwc-button @click=${this._createPerson}>
|
||||||
CREATE PERSON</mwc-button
|
CREATE PERSON</mwc-button
|
||||||
>
|
>
|
||||||
@ -91,7 +93,7 @@ class HaConfigPerson extends LitElement {
|
|||||||
</paper-card>
|
</paper-card>
|
||||||
${this._configItems.length > 0
|
${this._configItems.length > 0
|
||||||
? html`
|
? html`
|
||||||
<paper-card heading="Configuration.yaml people">
|
<paper-card heading="Configuration.yaml persons">
|
||||||
${this._configItems.map((entry) => {
|
${this._configItems.map((entry) => {
|
||||||
return html`
|
return html`
|
||||||
<paper-item>
|
<paper-item>
|
||||||
@ -123,6 +125,7 @@ class HaConfigPerson extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchData() {
|
private async _fetchData() {
|
||||||
|
this._usersLoad = fetchUsers(this.hass!);
|
||||||
const personData = await fetchPersons(this.hass!);
|
const personData = await fetchPersons(this.hass!);
|
||||||
|
|
||||||
this._storageItems = personData.storage.sort((ent1, ent2) =>
|
this._storageItems = personData.storage.sort((ent1, ent2) =>
|
||||||
@ -142,9 +145,27 @@ class HaConfigPerson extends LitElement {
|
|||||||
this._openDialog(entry);
|
this._openDialog(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _openDialog(entry?: Person) {
|
private _allowedUsers(users: User[], currentPerson?: Person) {
|
||||||
|
const used = new Set();
|
||||||
|
for (const coll of [this._configItems, this._storageItems]) {
|
||||||
|
for (const pers of coll!) {
|
||||||
|
if (pers.user_id) {
|
||||||
|
used.add(pers.user_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const currentUserId = currentPerson ? currentPerson.user_id : undefined;
|
||||||
|
return users.filter(
|
||||||
|
(user) => user.id === currentUserId || !used.has(user.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _openDialog(entry?: Person) {
|
||||||
|
const users = await this._usersLoad!;
|
||||||
|
|
||||||
showPersonDetailDialog(this, {
|
showPersonDetailDialog(this, {
|
||||||
entry,
|
entry,
|
||||||
|
users: this._allowedUsers(users, entry),
|
||||||
createEntry: async (values) => {
|
createEntry: async (values) => {
|
||||||
const created = await createPerson(this.hass!, values);
|
const created = await createPerson(this.hass!, values);
|
||||||
this._storageItems = this._storageItems!.concat(created).sort(
|
this._storageItems = this._storageItems!.concat(created).sort(
|
||||||
@ -191,6 +212,7 @@ All devices in this area will become unassigned.`)
|
|||||||
}
|
}
|
||||||
.empty {
|
.empty {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 8px;
|
||||||
}
|
}
|
||||||
paper-item {
|
paper-item {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { Person, PersonMutableParams } from "../../../data/person";
|
import { Person, PersonMutableParams } from "../../../data/person";
|
||||||
|
import { User } from "../../../data/auth";
|
||||||
|
|
||||||
export interface PersonDetailDialogParams {
|
export interface PersonDetailDialogParams {
|
||||||
entry?: Person;
|
entry?: Person;
|
||||||
|
users: User[];
|
||||||
createEntry: (values: PersonMutableParams) => Promise<unknown>;
|
createEntry: (values: PersonMutableParams) => Promise<unknown>;
|
||||||
updateEntry: (updates: Partial<PersonMutableParams>) => Promise<unknown>;
|
updateEntry: (updates: Partial<PersonMutableParams>) => Promise<unknown>;
|
||||||
removeEntry: () => Promise<boolean>;
|
removeEntry: () => Promise<boolean>;
|
||||||
|
@ -115,4 +115,4 @@ class HaUserPicker extends EventsMixin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-user-picker", HaUserPicker);
|
customElements.define("ha-config-user-picker", HaUserPicker);
|
@ -6,9 +6,10 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|||||||
|
|
||||||
import NavigateMixin from "../../../mixins/navigate-mixin";
|
import NavigateMixin from "../../../mixins/navigate-mixin";
|
||||||
|
|
||||||
import "./ha-user-picker";
|
import "./ha-config-user-picker";
|
||||||
import "./ha-user-editor";
|
import "./ha-user-editor";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { fetchUsers } from "../../../data/auth";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin NavigateMixin
|
* @appliesMixin NavigateMixin
|
||||||
@ -23,7 +24,10 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
|||||||
></app-route>
|
></app-route>
|
||||||
|
|
||||||
<template is="dom-if" if='[[_equals(_routeData.user, "picker")]]'>
|
<template is="dom-if" if='[[_equals(_routeData.user, "picker")]]'>
|
||||||
<ha-user-picker hass="[[hass]]" users="[[_users]]"></ha-user-picker>
|
<ha-config-user-picker
|
||||||
|
hass="[[hass]]"
|
||||||
|
users="[[_users]]"
|
||||||
|
></ha-config-user-picker>
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template
|
||||||
is="dom-if"
|
is="dom-if"
|
||||||
@ -93,9 +97,7 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _loadData() {
|
async _loadData() {
|
||||||
this._users = await this.hass.callWS({
|
this._users = await fetchUsers(this.hass);
|
||||||
type: "config/auth/list",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import { Cluster } from "../../../data/zha";
|
import { Cluster } from "../../../data/zha";
|
||||||
import "../../../layouts/ha-app-layout";
|
import "../../../layouts/ha-app-layout";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { ZHAClusterSelectedParams, ZHANodeSelectedParams } from "./types";
|
import { ZHAClusterSelectedParams, ZHANodeSelectedParams } from "./types";
|
||||||
import "./zha-cluster-attributes";
|
import "./zha-cluster-attributes";
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
readAttributeValue,
|
readAttributeValue,
|
||||||
ZHADevice,
|
ZHADevice,
|
||||||
} from "../../../data/zha";
|
} from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import {
|
import {
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
fetchCommandsForCluster,
|
fetchCommandsForCluster,
|
||||||
ZHADevice,
|
ZHADevice,
|
||||||
} from "../../../data/zha";
|
} from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import {
|
import {
|
||||||
|
@ -12,7 +12,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../components/ha-service-description";
|
import "../../../components/ha-service-description";
|
||||||
import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha";
|
import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import { ItemSelectedEvent } from "./types";
|
import { ItemSelectedEvent } from "./types";
|
||||||
|
@ -13,7 +13,7 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
|||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
import "../../../components/entity/state-badge";
|
import "../../../components/entity/state-badge";
|
||||||
|
@ -11,7 +11,7 @@ import "@polymer/paper-card/paper-card";
|
|||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../components/ha-service-description";
|
import "../../../components/ha-service-description";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import "@polymer/paper-listbox/paper-listbox";
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../components/ha-service-description";
|
import "../../../components/ha-service-description";
|
||||||
import { haStyle } from "../../../resources/ha-style";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import { ItemSelectedEvent, NodeServiceData } from "./types";
|
import { ItemSelectedEvent, NodeServiceData } from "./types";
|
||||||
|
@ -11,7 +11,7 @@ import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
|||||||
|
|
||||||
import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
|
import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
|
||||||
import { PolymerChangedEvent } from "../../polymer-types";
|
import { PolymerChangedEvent } from "../../polymer-types";
|
||||||
import { haStyleDialog } from "../../resources/ha-style";
|
import { haStyleDialog } from "../../resources/styles";
|
||||||
|
|
||||||
class DialogSystemLogDetail extends LitElement {
|
class DialogSystemLogDetail extends LitElement {
|
||||||
private _params?: SystemLogDetailDialogParams;
|
private _params?: SystemLogDetailDialogParams;
|
||||||
|
@ -12,7 +12,7 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|||||||
import "../../components/ha-menu-button";
|
import "../../components/ha-menu-button";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { haStyle } from "../../resources/ha-style";
|
import { haStyle } from "../../resources/styles";
|
||||||
|
|
||||||
import "./system-log-card";
|
import "./system-log-card";
|
||||||
import "./error-log-card";
|
import "./error-log-card";
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
|
||||||
import { haStyleDialog } from "../../../../resources/ha-style";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
|
||||||
import "./hui-card-picker";
|
import "./hui-card-picker";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
|
|
||||||
import { haStyleDialog } from "../../../../resources/ha-style";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "@polymer/paper-dialog/paper-dialog";
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
|
@ -14,7 +14,7 @@ import "@polymer/paper-dialog/paper-dialog";
|
|||||||
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
|
|
||||||
import { haStyleDialog } from "../../../resources/ha-style";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
|
||||||
import { haStyleDialog } from "../../../../resources/ha-style";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
|
||||||
import "./hui-lovelace-editor";
|
import "./hui-lovelace-editor";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
@ -18,7 +18,7 @@ import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
|
||||||
import { haStyleDialog } from "../../../../resources/ha-style";
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
|
||||||
import "../../components/hui-entity-editor";
|
import "../../components/hui-entity-editor";
|
||||||
import "./hui-view-editor";
|
import "./hui-view-editor";
|
||||||
|
@ -13,7 +13,7 @@ import { struct } from "./common/structs/struct";
|
|||||||
import { Lovelace } from "./types";
|
import { Lovelace } from "./types";
|
||||||
|
|
||||||
import "../../components/ha-icon";
|
import "../../components/ha-icon";
|
||||||
import { haStyle } from "../../resources/ha-style";
|
import { haStyle } from "../../resources/styles";
|
||||||
import "./components/hui-yaml-editor";
|
import "./components/hui-yaml-editor";
|
||||||
// This is not a duplicate import, one is for types, one is for element.
|
// This is not a duplicate import, one is for types, one is for element.
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
|
@ -48,7 +48,7 @@ import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
|||||||
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
||||||
import { Lovelace } from "./types";
|
import { Lovelace } from "./types";
|
||||||
import { afterNextRender } from "../../common/util/render-status";
|
import { afterNextRender } from "../../common/util/render-status";
|
||||||
import { haStyle } from "../../resources/ha-style";
|
import { haStyle } from "../../resources/styles";
|
||||||
import { computeRTL, computeRTLDirection } from "../../common/util/compute_rtl";
|
import { computeRTL, computeRTLDirection } from "../../common/util/compute_rtl";
|
||||||
|
|
||||||
// CSS and JS should only be imported once. Modules and HTML are safe.
|
// CSS and JS should only be imported once. Modules and HTML are safe.
|
||||||
|
@ -1,93 +1,6 @@
|
|||||||
import "@polymer/paper-styles/paper-styles";
|
import "@polymer/paper-styles/paper-styles";
|
||||||
import "@polymer/polymer/polymer-legacy";
|
import "@polymer/polymer/polymer-legacy";
|
||||||
import { css } from "lit-element";
|
import { haStyle, haStyleDialog } from "./styles";
|
||||||
|
|
||||||
export const haStyle = css`
|
|
||||||
:host {
|
|
||||||
@apply --paper-font-body1;
|
|
||||||
}
|
|
||||||
|
|
||||||
app-header-layout,
|
|
||||||
ha-app-layout {
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
app-header,
|
|
||||||
app-toolbar {
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--text-primary-color, white);
|
|
||||||
}
|
|
||||||
|
|
||||||
app-toolbar ha-menu-button + [main-title],
|
|
||||||
app-toolbar paper-icon-button + [main-title] {
|
|
||||||
margin-left: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
@apply --paper-font-title;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.link {
|
|
||||||
background: none;
|
|
||||||
color: inherit;
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
font: inherit;
|
|
||||||
text-align: left;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-actions a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-actions .warning {
|
|
||||||
--mdc-theme-primary: var(--google-red-500);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const haStyleDialog = css`
|
|
||||||
/* prevent clipping of positioned elements */
|
|
||||||
paper-dialog-scrollable {
|
|
||||||
--paper-dialog-scrollable: {
|
|
||||||
-webkit-overflow-scrolling: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* force smooth scrolling for iOS 10 */
|
|
||||||
paper-dialog-scrollable.can-scroll {
|
|
||||||
--paper-dialog-scrollable: {
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.paper-dialog-buttons {
|
|
||||||
align-items: flex-end;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paper-dialog-buttons .warning {
|
|
||||||
--mdc-theme-primary: var(--google-red-500);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
|
||||||
paper-dialog {
|
|
||||||
margin: 0;
|
|
||||||
width: 100% !important;
|
|
||||||
max-height: calc(100% - 64px);
|
|
||||||
|
|
||||||
position: fixed !important;
|
|
||||||
bottom: 0px;
|
|
||||||
left: 0px;
|
|
||||||
right: 0px;
|
|
||||||
overflow: scroll;
|
|
||||||
border-bottom-left-radius: 0px;
|
|
||||||
border-bottom-right-radius: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const documentContainer = document.createElement("template");
|
const documentContainer = document.createElement("template");
|
||||||
documentContainer.setAttribute("style", "display: none;");
|
documentContainer.setAttribute("style", "display: none;");
|
||||||
|
88
src/resources/styles.ts
Normal file
88
src/resources/styles.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { css } from "lit-element";
|
||||||
|
|
||||||
|
export const haStyle = css`
|
||||||
|
:host {
|
||||||
|
@apply --paper-font-body1;
|
||||||
|
}
|
||||||
|
|
||||||
|
app-header-layout,
|
||||||
|
ha-app-layout {
|
||||||
|
background-color: var(--primary-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
app-header,
|
||||||
|
app-toolbar {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--text-primary-color, white);
|
||||||
|
}
|
||||||
|
|
||||||
|
app-toolbar ha-menu-button + [main-title],
|
||||||
|
app-toolbar paper-icon-button + [main-title] {
|
||||||
|
margin-left: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
@apply --paper-font-title;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.link {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions .warning {
|
||||||
|
--mdc-theme-primary: var(--google-red-500);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const haStyleDialog = css`
|
||||||
|
/* prevent clipping of positioned elements */
|
||||||
|
paper-dialog-scrollable {
|
||||||
|
--paper-dialog-scrollable: {
|
||||||
|
-webkit-overflow-scrolling: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force smooth scrolling for iOS 10 */
|
||||||
|
paper-dialog-scrollable.can-scroll {
|
||||||
|
--paper-dialog-scrollable: {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paper-dialog-buttons {
|
||||||
|
align-items: flex-end;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paper-dialog-buttons .warning {
|
||||||
|
--mdc-theme-primary: var(--google-red-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
paper-dialog {
|
||||||
|
margin: 0;
|
||||||
|
width: 100% !important;
|
||||||
|
max-height: calc(100% - 64px);
|
||||||
|
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
overflow: scroll;
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
@ -54,7 +54,7 @@ export interface MFAModule {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface CurrentUser {
|
||||||
id: string;
|
id: string;
|
||||||
is_owner: boolean;
|
is_owner: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
@ -130,7 +130,7 @@ export interface HomeAssistant {
|
|||||||
|
|
||||||
dockedSidebar: boolean;
|
dockedSidebar: boolean;
|
||||||
moreInfoEntityId: string;
|
moreInfoEntityId: string;
|
||||||
user: User;
|
user: CurrentUser;
|
||||||
callService: (
|
callService: (
|
||||||
domain: string,
|
domain: string,
|
||||||
service: string,
|
service: string,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user