Allow picking users (#2768)

* Allow picking users

* Update ha-user-badge.ts
This commit is contained in:
Paulus Schoutsen 2019-02-16 11:58:07 -08:00 committed by GitHub
parent 2d3d4db4dd
commit c7796e9557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 393 additions and 179 deletions

View File

@ -6,7 +6,6 @@ import {
PropertyValues,
property,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/paper-item/paper-icon-item";
@ -14,27 +13,12 @@ import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import "./ha-icon";
import "../components/user/ha-user-badge";
import isComponentLoaded from "../common/config/is_component_loaded";
import { HomeAssistant, Panel } from "../types";
import { fireEvent } from "../common/dom/fire_event";
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 computePanels = (hass: HomeAssistant) => {
@ -93,22 +77,13 @@ class HaSidebar extends LitElement {
return html``;
}
const initials = hass.user ? computeInitials(hass.user.name) : "";
return html`
<app-toolbar>
<div main-title>Home Assistant</div>
${hass.user
? html`
<a
href="/profile"
class="${classMap({
"profile-badge": true,
long: initials.length > 2,
})}"
>
<paper-ripple></paper-ripple>
${initials}
<a href="/profile">
<ha-user-badge user=${hass.user}></ha-user-badge>
</a>
`
: ""}
@ -344,23 +319,6 @@ class HaSidebar extends LitElement {
.dev-tools a {
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%;
}
`;
}
}

View 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;
}
}

View 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);

View File

@ -1,5 +1,26 @@
import { HomeAssistant } from "../types";
export interface AuthProvider {
name: string;
id: 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",
});

View File

@ -3,12 +3,17 @@ import {
Connection,
getCollection,
} from "home-assistant-js-websocket";
import { User } from "../types";
import { CurrentUser } from "../types";
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 = (
conn: Connection,
onChange: (user: User) => void
onChange: (user: CurrentUser) => void
) => userCollection(conn).subscribe(onChange);

View File

@ -10,7 +10,7 @@ import {
customElement,
} from "lit-element";
import "../components/ha-menu-button";
import { haStyle } from "../resources/ha-style";
import { haStyle } from "../resources/styles";
@customElement("hass-loading-screen")
class HassLoadingScreen extends LitElement {

View File

@ -10,7 +10,7 @@ import {
customElement,
CSSResult,
} from "lit-element";
import { haStyle } from "../resources/ha-style";
import { haStyle } from "../resources/styles";
@customElement("hass-subpage")
class HassSubpage extends LitElement {

View File

@ -12,7 +12,7 @@ import "@polymer/paper-input/paper-input";
import { AreaRegistryDetailDialogParams } from "./show-dialog-area-registry-detail";
import { PolymerChangedEvent } from "../../../polymer-types";
import { haStyleDialog } from "../../../resources/ha-style";
import { haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { AreaRegistryEntryMutableParams } from "../../../data/area_registry";

View File

@ -21,7 +21,7 @@ import Automation from "../js/automation";
import unmountPreact from "../../../common/preact/unmount";
import computeStateName from "../../../common/entity/compute_state_name";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { AutomationEntity, AutomationConfig } from "../../../data/automation";
import { navigate } from "../../../common/navigate";

View File

@ -18,7 +18,7 @@ import { PaperInputElement } from "@polymer/paper-input/paper-input";
import { HomeAssistant } 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";

View File

@ -12,7 +12,7 @@ import "@polymer/paper-input/paper-input";
import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail";
import { PolymerChangedEvent } from "../../../polymer-types";
import { haStyleDialog } from "../../../resources/ha-style";
import { haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import computeDomain from "../../../common/entity/compute_domain";
import { HassEntity } from "home-assistant-js-websocket";

View File

@ -9,29 +9,37 @@ import {
import "@polymer/paper-dialog/paper-dialog";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import "@polymer/paper-input/paper-input";
import "@material/mwc-button";
import "../../../components/entity/ha-entities-picker";
import "../../../components/user/ha-user-picker";
import { PersonDetailDialogParams } from "./show-dialog-person-detail";
import { PolymerChangedEvent } from "../../../polymer-types";
import { haStyleDialog } from "../../../resources/ha-style";
import { haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { PersonMutableParams } from "../../../data/person";
class DialogPersonDetail extends LitElement {
@property() public hass!: HomeAssistant;
@property() private _name!: string;
@property() private _userId?: string;
@property() private _deviceTrackers!: string[];
@property() private _error?: string;
@property() private _params?: PersonDetailDialogParams;
@property() private _submitting?: boolean;
@property() private _submitting: boolean = false;
public async showDialog(params: PersonDetailDialogParams): Promise<void> {
this._params = params;
this._error = undefined;
this._name = this._params.entry ? this._params.entry.name : "";
this._deviceTrackers = this._params.entry
? this._params.entry.device_trackers || []
: [];
if (this._params.entry) {
this._name = this._params.entry.name || "";
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;
}
@ -61,6 +69,13 @@ class DialogPersonDetail extends LitElement {
error-message="Name is required"
.invalid=${nameInvalid}
></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>
${this.hass.localize(
"ui.panel.config.person.detail.device_tracker_intro"
@ -108,6 +123,11 @@ class DialogPersonDetail extends LitElement {
this._name = ev.detail.value;
}
private _userChanged(ev: PolymerChangedEvent<string>) {
this._error = undefined;
this._userId = ev.detail.value;
}
private _deviceTrackersChanged(ev: PolymerChangedEvent<string[]>) {
this._error = undefined;
this._deviceTrackers = ev.detail.value;
@ -119,8 +139,7 @@ class DialogPersonDetail extends LitElement {
const values: PersonMutableParams = {
name: this._name.trim(),
device_trackers: this._deviceTrackers,
// Temp, we will add this in a future PR.
user_id: null,
user_id: this._userId || null,
};
if (this._params!.entry) {
await this._params!.updateEntry(values);
@ -129,7 +148,7 @@ class DialogPersonDetail extends LitElement {
}
this._params = undefined;
} catch (err) {
this._error = err;
this._error = err ? err.message : "Unknown error";
} finally {
this._submitting = false;
}
@ -162,6 +181,9 @@ class DialogPersonDetail extends LitElement {
.form {
padding-bottom: 24px;
}
ha-user-picker {
margin-top: 16px;
}
mwc-button.warning {
margin-right: auto;
}

View File

@ -27,12 +27,14 @@ import {
showPersonDetailDialog,
loadPersonDetailDialog,
} from "./show-dialog-person-detail";
import { User, fetchUsers } from "../../../data/auth";
class HaConfigPerson extends LitElement {
public hass?: HomeAssistant;
public isWide?: boolean;
private _storageItems?: Person[];
private _configItems?: Person[];
private _usersLoad?: Promise<User[]>;
static get properties(): PropertyDeclarations {
return {
@ -62,7 +64,7 @@ class HaConfigPerson extends LitElement {
${this._configItems.length > 0
? html`
<p>
Note: people configured via configuration.yaml cannot be
Note: persons configured via configuration.yaml cannot be
edited via the UI.
</p>
`
@ -81,7 +83,7 @@ class HaConfigPerson extends LitElement {
${this._storageItems.length === 0
? html`
<div class="empty">
Looks like you have no people yet!
Looks like you have not created any persons yet.
<mwc-button @click=${this._createPerson}>
CREATE PERSON</mwc-button
>
@ -91,7 +93,7 @@ class HaConfigPerson extends LitElement {
</paper-card>
${this._configItems.length > 0
? html`
<paper-card heading="Configuration.yaml people">
<paper-card heading="Configuration.yaml persons">
${this._configItems.map((entry) => {
return html`
<paper-item>
@ -123,6 +125,7 @@ class HaConfigPerson extends LitElement {
}
private async _fetchData() {
this._usersLoad = fetchUsers(this.hass!);
const personData = await fetchPersons(this.hass!);
this._storageItems = personData.storage.sort((ent1, ent2) =>
@ -142,9 +145,27 @@ class HaConfigPerson extends LitElement {
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, {
entry,
users: this._allowedUsers(users, entry),
createEntry: async (values) => {
const created = await createPerson(this.hass!, values);
this._storageItems = this._storageItems!.concat(created).sort(
@ -191,6 +212,7 @@ All devices in this area will become unassigned.`)
}
.empty {
text-align: center;
padding: 8px;
}
paper-item {
padding-top: 4px;

View File

@ -1,8 +1,10 @@
import { fireEvent } from "../../../common/dom/fire_event";
import { Person, PersonMutableParams } from "../../../data/person";
import { User } from "../../../data/auth";
export interface PersonDetailDialogParams {
entry?: Person;
users: User[];
createEntry: (values: PersonMutableParams) => Promise<unknown>;
updateEntry: (updates: Partial<PersonMutableParams>) => Promise<unknown>;
removeEntry: () => Promise<boolean>;

View File

@ -115,4 +115,4 @@ class HaUserPicker extends EventsMixin(
}
}
customElements.define("ha-user-picker", HaUserPicker);
customElements.define("ha-config-user-picker", HaUserPicker);

View File

@ -6,9 +6,10 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
import NavigateMixin from "../../../mixins/navigate-mixin";
import "./ha-user-picker";
import "./ha-config-user-picker";
import "./ha-user-editor";
import { fireEvent } from "../../../common/dom/fire_event";
import { fetchUsers } from "../../../data/auth";
/*
* @appliesMixin NavigateMixin
@ -23,7 +24,10 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
></app-route>
<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
is="dom-if"
@ -93,9 +97,7 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
}
async _loadData() {
this._users = await this.hass.callWS({
type: "config/auth/list",
});
this._users = await fetchUsers(this.hass);
}
}

View File

@ -12,7 +12,7 @@ import { HassEntity } from "home-assistant-js-websocket";
import { HASSDomEvent } from "../../../common/dom/fire_event";
import { Cluster } from "../../../data/zha";
import "../../../layouts/ha-app-layout";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { ZHAClusterSelectedParams, ZHANodeSelectedParams } from "./types";
import "./zha-cluster-attributes";

View File

@ -20,7 +20,7 @@ import {
readAttributeValue,
ZHADevice,
} from "../../../data/zha";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../ha-config-section";
import {

View File

@ -16,7 +16,7 @@ import {
fetchCommandsForCluster,
ZHADevice,
} from "../../../data/zha";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../ha-config-section";
import {

View File

@ -12,7 +12,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/buttons/ha-call-service-button";
import "../../../components/ha-service-description";
import { Cluster, fetchClustersForZhaNode, ZHADevice } from "../../../data/zha";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../ha-config-section";
import { ItemSelectedEvent } from "./types";

View File

@ -13,7 +13,7 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import { fireEvent } from "../../../common/dom/fire_event";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../../../components/entity/state-badge";

View File

@ -11,7 +11,7 @@ import "@polymer/paper-card/paper-card";
import "@polymer/paper-icon-button/paper-icon-button";
import "../../../components/buttons/ha-call-service-button";
import "../../../components/ha-service-description";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../ha-config-section";

View File

@ -15,7 +15,7 @@ import "@polymer/paper-listbox/paper-listbox";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/buttons/ha-call-service-button";
import "../../../components/ha-service-description";
import { haStyle } from "../../../resources/ha-style";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import "../ha-config-section";
import { ItemSelectedEvent, NodeServiceData } from "./types";

View File

@ -11,7 +11,7 @@ import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
import { PolymerChangedEvent } from "../../polymer-types";
import { haStyleDialog } from "../../resources/ha-style";
import { haStyleDialog } from "../../resources/styles";
class DialogSystemLogDetail extends LitElement {
private _params?: SystemLogDetailDialogParams;

View File

@ -12,7 +12,7 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
import "../../components/ha-menu-button";
import { HomeAssistant } from "../../types";
import { haStyle } from "../../resources/ha-style";
import { haStyle } from "../../resources/styles";
import "./system-log-card";
import "./error-log-card";

View File

@ -9,7 +9,7 @@ import {
import "@polymer/paper-dialog/paper-dialog";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import { haStyleDialog } from "../../../../resources/ha-style";
import { haStyleDialog } from "../../../../resources/styles";
import "./hui-card-picker";
import { HomeAssistant } from "../../../../types";

View File

@ -10,7 +10,7 @@ import {
import { classMap } from "lit-html/directives/class-map";
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-dialog/paper-dialog";

View File

@ -14,7 +14,7 @@ import "@polymer/paper-dialog/paper-dialog";
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
import "@material/mwc-button";
import { haStyleDialog } from "../../../resources/ha-style";
import { haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";

View File

@ -14,7 +14,7 @@ import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
import "@material/mwc-button";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import { haStyleDialog } from "../../../../resources/ha-style";
import { haStyleDialog } from "../../../../resources/styles";
import "./hui-lovelace-editor";
import { HomeAssistant } from "../../../../types";

View File

@ -18,7 +18,7 @@ import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
import "@material/mwc-button";
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 "./hui-view-editor";

View File

@ -13,7 +13,7 @@ import { struct } from "./common/structs/struct";
import { Lovelace } from "./types";
import "../../components/ha-icon";
import { haStyle } from "../../resources/ha-style";
import { haStyle } from "../../resources/styles";
import "./components/hui-yaml-editor";
// This is not a duplicate import, one is for types, one is for element.
// tslint:disable-next-line

View File

@ -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 { Lovelace } from "./types";
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";
// CSS and JS should only be imported once. Modules and HTML are safe.

View File

@ -1,93 +1,6 @@
import "@polymer/paper-styles/paper-styles";
import "@polymer/polymer/polymer-legacy";
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;
}
}
`;
import { haStyle, haStyleDialog } from "./styles";
const documentContainer = document.createElement("template");
documentContainer.setAttribute("style", "display: none;");

88
src/resources/styles.ts Normal file
View 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;
}
}
`;

View File

@ -54,7 +54,7 @@ export interface MFAModule {
enabled: boolean;
}
export interface User {
export interface CurrentUser {
id: string;
is_owner: boolean;
name: string;
@ -130,7 +130,7 @@ export interface HomeAssistant {
dockedSidebar: boolean;
moreInfoEntityId: string;
user: User;
user: CurrentUser;
callService: (
domain: string,
service: string,