mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-02 05:57:54 +00:00
Merge pull request #7174 from home-assistant/dev
This commit is contained in:
commit
6ef3d091e1
@ -93,6 +93,8 @@ export class HaEntityPicker extends LitElement {
|
|||||||
|
|
||||||
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public hideClearIcon = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) private _opened = false;
|
@property({ type: Boolean }) private _opened = false;
|
||||||
|
|
||||||
@query("vaadin-combo-box-light") private _comboBox!: HTMLElement;
|
@query("vaadin-combo-box-light") private _comboBox!: HTMLElement;
|
||||||
@ -204,7 +206,7 @@ export class HaEntityPicker extends LitElement {
|
|||||||
autocorrect="off"
|
autocorrect="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
>
|
>
|
||||||
${this.value
|
${this.value && !this.hideClearIcon
|
||||||
? html`
|
? html`
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
aria-label=${this.hass.localize(
|
aria-label=${this.hass.localize(
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { nextRender } from "../common/util/render-status";
|
import { nextRender } from "../common/util/render-status";
|
||||||
|
import { getExternalConfig } from "../external_app/external_config";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
type HLSModule = typeof import("hls.js");
|
type HLSModule = typeof import("hls.js");
|
||||||
@ -93,39 +94,49 @@ class HaHLSPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _getUseExoPlayer(): Promise<boolean> {
|
private async _getUseExoPlayer(): Promise<boolean> {
|
||||||
return false;
|
if (!this.hass!.auth.external || !this.allowExoPlayer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const externalConfig = await getExternalConfig(this.hass!.auth.external);
|
||||||
|
return externalConfig && externalConfig.hasExoPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _startHls(): Promise<void> {
|
private async _startHls(): Promise<void> {
|
||||||
let hls: any;
|
|
||||||
const videoEl = this._videoEl;
|
const videoEl = this._videoEl;
|
||||||
this._useExoPlayer = await this._getUseExoPlayer();
|
const playlist_url = this.url.replace("master_playlist", "playlist");
|
||||||
if (!this._useExoPlayer) {
|
const useExoPlayerPromise = this._getUseExoPlayer();
|
||||||
hls = ((await import(/* webpackChunkName: "hls.js" */ "hls.js")) as any)
|
const masterPlaylistPromise = fetch(this.url);
|
||||||
.default as HLSModule;
|
|
||||||
let hlsSupported = hls.isSupported();
|
|
||||||
|
|
||||||
if (!hlsSupported) {
|
const hls = ((await import(
|
||||||
hlsSupported =
|
/* webpackChunkName: "hls.js" */ "hls.js"
|
||||||
videoEl.canPlayType("application/vnd.apple.mpegurl") !== "";
|
)) as any).default as HLSModule;
|
||||||
}
|
let hlsSupported = hls.isSupported();
|
||||||
|
|
||||||
if (!hlsSupported) {
|
if (!hlsSupported) {
|
||||||
this._videoEl.innerHTML = this.hass.localize(
|
hlsSupported =
|
||||||
"ui.components.media-browser.video_not_supported"
|
videoEl.canPlayType("application/vnd.apple.mpegurl") !== "";
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = this.url;
|
if (!hlsSupported) {
|
||||||
|
this._videoEl.innerHTML = this.hass.localize(
|
||||||
|
"ui.components.media-browser.video_not_supported"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._useExoPlayer = await useExoPlayerPromise;
|
||||||
|
let hevcRegexp: RegExp;
|
||||||
|
let masterPlaylist: string;
|
||||||
if (this._useExoPlayer) {
|
if (this._useExoPlayer) {
|
||||||
this._renderHLSExoPlayer(url);
|
hevcRegexp = /CODECS=".*?((hev1)|(hvc1))\..*?"/;
|
||||||
|
masterPlaylist = await (await masterPlaylistPromise).text();
|
||||||
|
}
|
||||||
|
if (this._useExoPlayer && hevcRegexp!.test(masterPlaylist!)) {
|
||||||
|
this._renderHLSExoPlayer(playlist_url);
|
||||||
} else if (hls.isSupported()) {
|
} else if (hls.isSupported()) {
|
||||||
this._renderHLSPolyfill(videoEl, hls, url);
|
this._renderHLSPolyfill(videoEl, hls, playlist_url);
|
||||||
} else {
|
} else {
|
||||||
this._renderHLSNative(videoEl, url);
|
this._renderHLSNative(videoEl, playlist_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,7 @@ interface DeprecatedIcon {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mdiDeprecatedIcons: DeprecatedIcon = {
|
const mdiDeprecatedIcons: DeprecatedIcon = {};
|
||||||
scooter: { removeIn: "117", newName: "human-scooter" },
|
|
||||||
};
|
|
||||||
|
|
||||||
const chunks: Chunks = {};
|
const chunks: Chunks = {};
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ export interface LovelaceViewElement extends HTMLElement {
|
|||||||
index?: number;
|
index?: number;
|
||||||
cards?: Array<LovelaceCard | HuiErrorCard>;
|
cards?: Array<LovelaceCard | HuiErrorCard>;
|
||||||
badges?: LovelaceBadge[];
|
badges?: LovelaceBadge[];
|
||||||
|
setConfig(config: LovelaceViewConfig): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShowViewConfig {
|
export interface ShowViewConfig {
|
||||||
|
@ -136,6 +136,7 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
|||||||
translationKey: "ui.panel.config.users.caption",
|
translationKey: "ui.panel.config.users.caption",
|
||||||
iconPath: mdiBadgeAccountHorizontal,
|
iconPath: mdiBadgeAccountHorizontal,
|
||||||
core: true,
|
core: true,
|
||||||
|
advancedOnly: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
general: [
|
general: [
|
||||||
|
@ -22,6 +22,22 @@ import { haStyleDialog } from "../../../resources/styles";
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { documentationUrl } from "../../../util/documentation-url";
|
import { documentationUrl } from "../../../util/documentation-url";
|
||||||
import { PersonDetailDialogParams } from "./show-dialog-person-detail";
|
import { PersonDetailDialogParams } from "./show-dialog-person-detail";
|
||||||
|
import "../../../components/ha-formfield";
|
||||||
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
|
import {
|
||||||
|
User,
|
||||||
|
SYSTEM_GROUP_ID_ADMIN,
|
||||||
|
deleteUser,
|
||||||
|
SYSTEM_GROUP_ID_USER,
|
||||||
|
updateUser,
|
||||||
|
} from "../../../data/user";
|
||||||
|
import {
|
||||||
|
showAlertDialog,
|
||||||
|
showPromptDialog,
|
||||||
|
showConfirmationDialog,
|
||||||
|
} from "../../../dialogs/generic/show-dialog-box";
|
||||||
|
import { adminChangePassword } from "../../../data/auth";
|
||||||
|
import { showAddUserDialog } from "../users/show-dialog-add-user";
|
||||||
|
|
||||||
const includeDomains = ["device_tracker"];
|
const includeDomains = ["device_tracker"];
|
||||||
|
|
||||||
@ -39,6 +55,10 @@ class DialogPersonDetail extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _userId?: string;
|
@internalProperty() private _userId?: string;
|
||||||
|
|
||||||
|
@internalProperty() private _user?: User;
|
||||||
|
|
||||||
|
@internalProperty() private _isAdmin?: boolean;
|
||||||
|
|
||||||
@internalProperty() private _deviceTrackers!: string[];
|
@internalProperty() private _deviceTrackers!: string[];
|
||||||
|
|
||||||
@internalProperty() private _picture!: string | null;
|
@internalProperty() private _picture!: string | null;
|
||||||
@ -64,9 +84,15 @@ class DialogPersonDetail extends LitElement {
|
|||||||
this._userId = this._params.entry.user_id || undefined;
|
this._userId = this._params.entry.user_id || undefined;
|
||||||
this._deviceTrackers = this._params.entry.device_trackers || [];
|
this._deviceTrackers = this._params.entry.device_trackers || [];
|
||||||
this._picture = this._params.entry.picture || null;
|
this._picture = this._params.entry.picture || null;
|
||||||
|
this._user = this._userId
|
||||||
|
? this._params.users.find((user) => user.id === this._userId)
|
||||||
|
: undefined;
|
||||||
|
this._isAdmin = this._user?.group_ids.includes(SYSTEM_GROUP_ID_ADMIN);
|
||||||
} else {
|
} else {
|
||||||
this._name = "";
|
this._name = "";
|
||||||
this._userId = undefined;
|
this._userId = undefined;
|
||||||
|
this._user = undefined;
|
||||||
|
this._isAdmin = undefined;
|
||||||
this._deviceTrackers = [];
|
this._deviceTrackers = [];
|
||||||
this._picture = null;
|
this._picture = null;
|
||||||
}
|
}
|
||||||
@ -115,15 +141,37 @@ class DialogPersonDetail extends LitElement {
|
|||||||
@change=${this._pictureChanged}
|
@change=${this._pictureChanged}
|
||||||
></ha-picture-upload>
|
></ha-picture-upload>
|
||||||
|
|
||||||
<ha-user-picker
|
<ha-formfield
|
||||||
label="${this.hass!.localize(
|
.label=${this.hass!.localize(
|
||||||
"ui.panel.config.person.detail.linked_user"
|
"ui.panel.config.person.detail.allow_login"
|
||||||
)}"
|
)}
|
||||||
.hass=${this.hass}
|
>
|
||||||
.value=${this._userId}
|
<ha-switch
|
||||||
.users=${this._params.users}
|
@change=${this._allowLoginChanged}
|
||||||
@value-changed=${this._userChanged}
|
.disabled=${this._user &&
|
||||||
></ha-user-picker>
|
(this._user.id === this.hass.user?.id ||
|
||||||
|
this._user.system_generated ||
|
||||||
|
this._user.is_owner)}
|
||||||
|
.checked=${this._userId}
|
||||||
|
></ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
|
|
||||||
|
${this._user
|
||||||
|
? html`<ha-formfield
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.person.detail.admin"
|
||||||
|
)}
|
||||||
|
.dir=${computeRTLDirection(this.hass)}
|
||||||
|
>
|
||||||
|
<ha-switch
|
||||||
|
.disabled=${this._user.system_generated ||
|
||||||
|
this._user.is_owner}
|
||||||
|
.checked=${this._isAdmin}
|
||||||
|
@change=${this._adminChanged}
|
||||||
|
>
|
||||||
|
</ha-switch>
|
||||||
|
</ha-formfield>`
|
||||||
|
: ""}
|
||||||
${this._deviceTrackersAvailable(this.hass)
|
${this._deviceTrackersAvailable(this.hass)
|
||||||
? html`
|
? html`
|
||||||
<p>
|
<p>
|
||||||
@ -185,10 +233,21 @@ class DialogPersonDetail extends LitElement {
|
|||||||
slot="secondaryAction"
|
slot="secondaryAction"
|
||||||
class="warning"
|
class="warning"
|
||||||
@click="${this._deleteEntry}"
|
@click="${this._deleteEntry}"
|
||||||
.disabled=${this._submitting}
|
.disabled=${(this._user && this._user.is_owner) ||
|
||||||
|
this._submitting}
|
||||||
>
|
>
|
||||||
${this.hass!.localize("ui.panel.config.person.detail.delete")}
|
${this.hass!.localize("ui.panel.config.person.detail.delete")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
|
${this._user && this.hass.user?.is_owner
|
||||||
|
? html`<mwc-button
|
||||||
|
slot="secondaryAction"
|
||||||
|
@click=${this._changePassword}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.users.editor.change_password"
|
||||||
|
)}
|
||||||
|
</mwc-button>`
|
||||||
|
: ""}
|
||||||
`
|
`
|
||||||
: html``}
|
: html``}
|
||||||
<mwc-button
|
<mwc-button
|
||||||
@ -213,9 +272,47 @@ class DialogPersonDetail extends LitElement {
|
|||||||
this._name = ev.detail.value;
|
this._name = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _userChanged(ev: PolymerChangedEvent<string>) {
|
private async _adminChanged(ev): Promise<void> {
|
||||||
this._error = undefined;
|
this._isAdmin = ev.target.checked;
|
||||||
this._userId = ev.detail.value;
|
}
|
||||||
|
|
||||||
|
private async _allowLoginChanged(ev): Promise<void> {
|
||||||
|
const target = ev.target;
|
||||||
|
if (target.checked) {
|
||||||
|
target.checked = false;
|
||||||
|
showAddUserDialog(this, {
|
||||||
|
userAddedCallback: async (user?: User) => {
|
||||||
|
if (user) {
|
||||||
|
target.checked = true;
|
||||||
|
this._user = user;
|
||||||
|
this._userId = user.id;
|
||||||
|
this._isAdmin = user.group_ids.includes(SYSTEM_GROUP_ID_ADMIN);
|
||||||
|
this._params?.refreshUsers();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: this._name,
|
||||||
|
});
|
||||||
|
} else if (this._userId) {
|
||||||
|
if (
|
||||||
|
!(await showConfirmationDialog(this, {
|
||||||
|
text: this.hass!.localize(
|
||||||
|
"ui.panel.config.person.detail.confirm_delete_user",
|
||||||
|
"name",
|
||||||
|
this._name
|
||||||
|
),
|
||||||
|
confirmText: this.hass!.localize(
|
||||||
|
"ui.panel.config.person.detail.delete"
|
||||||
|
),
|
||||||
|
dismissText: this.hass!.localize("ui.common.cancel"),
|
||||||
|
}))
|
||||||
|
) {
|
||||||
|
target.checked = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await deleteUser(this.hass, this._userId);
|
||||||
|
this._params?.refreshUsers();
|
||||||
|
this._userId = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _deviceTrackersChanged(ev: PolymerChangedEvent<string[]>) {
|
private _deviceTrackersChanged(ev: PolymerChangedEvent<string[]>) {
|
||||||
@ -228,9 +325,70 @@ class DialogPersonDetail extends LitElement {
|
|||||||
this._picture = (ev.target as HaPictureUpload).value;
|
this._picture = (ev.target as HaPictureUpload).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _changePassword() {
|
||||||
|
if (!this._user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const credential = this._user.credentials.find(
|
||||||
|
(cred) => cred.type === "homeassistant"
|
||||||
|
);
|
||||||
|
if (!credential) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: "No Home Assistant credentials found.",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newPassword = await showPromptDialog(this, {
|
||||||
|
title: this.hass.localize("ui.panel.config.users.editor.change_password"),
|
||||||
|
inputType: "password",
|
||||||
|
inputLabel: this.hass.localize(
|
||||||
|
"ui.panel.config.users.editor.new_password"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
if (!newPassword) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const confirmPassword = await showPromptDialog(this, {
|
||||||
|
title: this.hass.localize("ui.panel.config.users.editor.change_password"),
|
||||||
|
inputType: "password",
|
||||||
|
inputLabel: this.hass.localize(
|
||||||
|
"ui.panel.config.users.add_user.password_confirm"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
if (!confirmPassword) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newPassword !== confirmPassword) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.users.add_user.password_not_match"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await adminChangePassword(this.hass, this._user.id, newPassword);
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.users.editor.password_changed"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async _updateEntry() {
|
private async _updateEntry() {
|
||||||
this._submitting = true;
|
this._submitting = true;
|
||||||
try {
|
try {
|
||||||
|
if (
|
||||||
|
(this._userId && this._name !== this._params!.entry?.name) ||
|
||||||
|
this._isAdmin !== this._user?.group_ids.includes(SYSTEM_GROUP_ID_ADMIN)
|
||||||
|
) {
|
||||||
|
await updateUser(this.hass!, this._userId!, {
|
||||||
|
name: this._name.trim(),
|
||||||
|
group_ids: [
|
||||||
|
this._isAdmin ? SYSTEM_GROUP_ID_ADMIN : SYSTEM_GROUP_ID_USER,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this._params?.refreshUsers();
|
||||||
|
}
|
||||||
const values: PersonMutableParams = {
|
const values: PersonMutableParams = {
|
||||||
name: this._name.trim(),
|
name: this._name.trim(),
|
||||||
device_trackers: this._deviceTrackers,
|
device_trackers: this._deviceTrackers,
|
||||||
@ -254,6 +412,9 @@ class DialogPersonDetail extends LitElement {
|
|||||||
this._submitting = true;
|
this._submitting = true;
|
||||||
try {
|
try {
|
||||||
if (await this._params!.removeEntry()) {
|
if (await this._params!.removeEntry()) {
|
||||||
|
if (this._params!.entry!.user_id) {
|
||||||
|
deleteUser(this.hass, this._params!.entry!.user_id);
|
||||||
|
}
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -275,6 +436,10 @@ class DialogPersonDetail extends LitElement {
|
|||||||
ha-picture-upload {
|
ha-picture-upload {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
ha-formfield {
|
||||||
|
display: block;
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
ha-user-picker {
|
ha-user-picker {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { mdiPlus } from "@mdi/js";
|
import { mdiPlus } from "@mdi/js";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
import "@material/mwc-fab";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
@ -223,6 +224,9 @@ class HaConfigPerson extends LitElement {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
refreshUsers: () => {
|
||||||
|
this._usersLoad = fetchUsers(this.hass!);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { User } from "../../../data/user";
|
|||||||
export interface PersonDetailDialogParams {
|
export interface PersonDetailDialogParams {
|
||||||
entry?: Person;
|
entry?: Person;
|
||||||
users: User[];
|
users: User[];
|
||||||
|
refreshUsers: () => void;
|
||||||
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>;
|
||||||
|
@ -50,15 +50,24 @@ export class DialogAddUser extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _isAdmin?: boolean;
|
@internalProperty() private _isAdmin?: boolean;
|
||||||
|
|
||||||
|
@internalProperty() private _allowChangeName = true;
|
||||||
|
|
||||||
public showDialog(params: AddUserDialogParams) {
|
public showDialog(params: AddUserDialogParams) {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._name = "";
|
this._name = this._params.name || "";
|
||||||
this._username = "";
|
this._username = "";
|
||||||
this._password = "";
|
this._password = "";
|
||||||
this._passwordConfirm = "";
|
this._passwordConfirm = "";
|
||||||
this._isAdmin = false;
|
this._isAdmin = false;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._loading = false;
|
this._loading = false;
|
||||||
|
|
||||||
|
if (this._params.name) {
|
||||||
|
this._allowChangeName = false;
|
||||||
|
this._maybePopulateUsername();
|
||||||
|
} else {
|
||||||
|
this._allowChangeName = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProperties: PropertyValues) {
|
protected firstUpdated(changedProperties: PropertyValues) {
|
||||||
@ -84,19 +93,22 @@ export class DialogAddUser extends LitElement {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
||||||
<paper-input
|
${this._allowChangeName
|
||||||
class="name"
|
? html` <paper-input
|
||||||
name="name"
|
class="name"
|
||||||
.label=${this.hass.localize("ui.panel.config.users.add_user.name")}
|
name="name"
|
||||||
.value=${this._name}
|
.label=${this.hass.localize(
|
||||||
required
|
"ui.panel.config.users.add_user.name"
|
||||||
auto-validate
|
)}
|
||||||
autocapitalize="on"
|
.value=${this._name}
|
||||||
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
required
|
||||||
@value-changed=${this._handleValueChanged}
|
auto-validate
|
||||||
@blur=${this._maybePopulateUsername}
|
autocapitalize="on"
|
||||||
></paper-input>
|
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
||||||
|
@value-changed=${this._handleValueChanged}
|
||||||
|
@blur=${this._maybePopulateUsername}
|
||||||
|
></paper-input>`
|
||||||
|
: ""}
|
||||||
<paper-input
|
<paper-input
|
||||||
class="username"
|
class="username"
|
||||||
name="username"
|
name="username"
|
||||||
|
@ -47,7 +47,7 @@ class DialogUserDetail extends LitElement {
|
|||||||
this._params = params;
|
this._params = params;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._name = params.entry.name || "";
|
this._name = params.entry.name || "";
|
||||||
this._isAdmin = params.entry.group_ids[0] === SYSTEM_GROUP_ID_ADMIN;
|
this._isAdmin = params.entry.group_ids.includes(SYSTEM_GROUP_ID_ADMIN);
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ class DialogUserDetail extends LitElement {
|
|||||||
.dir=${computeRTLDirection(this.hass)}
|
.dir=${computeRTLDirection(this.hass)}
|
||||||
>
|
>
|
||||||
<ha-switch
|
<ha-switch
|
||||||
.disabled=${user.system_generated}
|
.disabled=${user.system_generated || user.is_owner}
|
||||||
.checked=${this._isAdmin}
|
.checked=${this._isAdmin}
|
||||||
@change=${this._adminChanged}
|
@change=${this._adminChanged}
|
||||||
>
|
>
|
||||||
|
@ -3,6 +3,7 @@ import { User } from "../../../data/user";
|
|||||||
|
|
||||||
export interface AddUserDialogParams {
|
export interface AddUserDialogParams {
|
||||||
userAddedCallback: (user: User) => void;
|
userAddedCallback: (user: User) => void;
|
||||||
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loadAddUserDialog = () =>
|
export const loadAddUserDialog = () =>
|
||||||
|
@ -244,8 +244,7 @@ class HaLogbook extends LitElement {
|
|||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-top: 1px solid
|
border-top: 1px solid var(--divider-color);
|
||||||
var(--mdc-dialog-scroll-divider-color, rgba(0, 0, 0, 0.12));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry.no-entity,
|
.entry.no-entity,
|
||||||
|
@ -3,8 +3,8 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
|
||||||
internalProperty,
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
@ -13,19 +13,23 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
|
|||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { computeCardSize } from "../common/compute-card-size";
|
||||||
import { findEntities } from "../common/find-entites";
|
import { findEntities } from "../common/find-entites";
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import "../components/hui-entities-toggle";
|
import "../components/hui-entities-toggle";
|
||||||
import { createHeaderFooterElement } from "../create-element/create-header-footer-element";
|
import { createHeaderFooterElement } from "../create-element/create-header-footer-element";
|
||||||
import { createRowElement } from "../create-element/create-row-element";
|
import { createRowElement } from "../create-element/create-row-element";
|
||||||
import { LovelaceRow } from "../entity-rows/types";
|
import {
|
||||||
|
EntityConfig,
|
||||||
|
LovelaceRow,
|
||||||
|
LovelaceRowConfig,
|
||||||
|
} from "../entity-rows/types";
|
||||||
import {
|
import {
|
||||||
LovelaceCard,
|
LovelaceCard,
|
||||||
LovelaceCardEditor,
|
LovelaceCardEditor,
|
||||||
LovelaceHeaderFooter,
|
LovelaceHeaderFooter,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
|
import { EntitiesCardConfig } from "./types";
|
||||||
import { computeCardSize } from "../common/compute-card-size";
|
|
||||||
|
|
||||||
@customElement("hui-entities-card")
|
@customElement("hui-entities-card")
|
||||||
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||||
@ -57,7 +61,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
private _hass?: HomeAssistant;
|
private _hass?: HomeAssistant;
|
||||||
|
|
||||||
private _configEntities?: EntitiesCardEntityConfig[];
|
private _configEntities?: LovelaceRowConfig[];
|
||||||
|
|
||||||
private _showHeaderToggle?: boolean;
|
private _showHeaderToggle?: boolean;
|
||||||
|
|
||||||
@ -115,7 +119,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
// Default value is show toggle if we can at least toggle 2 entities.
|
// Default value is show toggle if we can at least toggle 2 entities.
|
||||||
let toggleable = 0;
|
let toggleable = 0;
|
||||||
for (const rowConf of entities) {
|
for (const rowConf of entities) {
|
||||||
if (!rowConf.entity) {
|
if (!("entity" in rowConf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
toggleable += Number(DOMAINS_TOGGLE.has(computeDomain(rowConf.entity)));
|
toggleable += Number(DOMAINS_TOGGLE.has(computeDomain(rowConf.entity)));
|
||||||
@ -188,7 +192,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
? html`
|
? html`
|
||||||
<ha-icon
|
<ha-icon
|
||||||
class="icon"
|
class="icon"
|
||||||
.icon="${this._config.icon}"
|
.icon=${this._config.icon}
|
||||||
></ha-icon>
|
></ha-icon>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -198,10 +202,10 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
? html``
|
? html``
|
||||||
: html`
|
: html`
|
||||||
<hui-entities-toggle
|
<hui-entities-toggle
|
||||||
.hass="${this._hass}"
|
.hass=${this._hass}
|
||||||
.entities="${this._configEntities!.map(
|
.entities=${(this._configEntities!.filter(
|
||||||
(conf) => conf.entity
|
(conf) => "type" in conf
|
||||||
)}"
|
) as EntityConfig[]).map((conf) => conf.entity)}
|
||||||
></hui-entities-toggle>
|
></hui-entities-toggle>
|
||||||
`}
|
`}
|
||||||
</div>
|
</div>
|
||||||
@ -285,20 +289,20 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderEntity(entityConf: EntitiesCardEntityConfig): TemplateResult {
|
private renderEntity(entityConf: LovelaceRowConfig): TemplateResult {
|
||||||
const element = createRowElement(
|
const element = createRowElement(
|
||||||
this._config!.state_color
|
!("type" in entityConf) && this._config!.state_color
|
||||||
? {
|
? ({
|
||||||
state_color: true,
|
state_color: true,
|
||||||
...entityConf,
|
...(entityConf as EntityConfig),
|
||||||
}
|
} as EntityConfig)
|
||||||
: entityConf
|
: entityConf
|
||||||
);
|
);
|
||||||
if (this._hass) {
|
if (this._hass) {
|
||||||
element.hass = this._hass;
|
element.hass = this._hass;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html` <div>${element}</div> `;
|
return html`<div>${element}</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,11 @@ import { FullCalendarView } from "../../../types";
|
|||||||
import { Condition } from "../common/validate-condition";
|
import { Condition } from "../common/validate-condition";
|
||||||
import { HuiImage } from "../components/hui-image";
|
import { HuiImage } from "../components/hui-image";
|
||||||
import { LovelaceElementConfig } from "../elements/types";
|
import { LovelaceElementConfig } from "../elements/types";
|
||||||
import { EntityConfig, EntityFilterEntityConfig } from "../entity-rows/types";
|
import {
|
||||||
|
EntityConfig,
|
||||||
|
EntityFilterEntityConfig,
|
||||||
|
LovelaceRowConfig,
|
||||||
|
} from "../entity-rows/types";
|
||||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
|
|
||||||
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
|
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
|
||||||
@ -60,7 +64,7 @@ export interface EntitiesCardConfig extends LovelaceCardConfig {
|
|||||||
type: "entities";
|
type: "entities";
|
||||||
show_header_toggle?: boolean;
|
show_header_toggle?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
entities: Array<EntitiesCardEntityConfig | string>;
|
entities: Array<LovelaceRowConfig | string>;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
header?: LovelaceHeaderFooterConfig;
|
header?: LovelaceHeaderFooterConfig;
|
||||||
|
@ -56,6 +56,7 @@ export function hasConfigOrEntitiesChanged(
|
|||||||
|
|
||||||
return entities.some(
|
return entities.some(
|
||||||
(entity) =>
|
(entity) =>
|
||||||
|
"entity" in entity &&
|
||||||
oldHass.states[entity.entity] !== element.hass!.states[entity.entity]
|
oldHass.states[entity.entity] !== element.hass!.states[entity.entity]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
// Parse array of entity objects from config
|
// Parse array of entity objects from config
|
||||||
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
|
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
|
||||||
|
|
||||||
export const processConfigEntities = <T extends EntityConfig>(
|
export const processConfigEntities = <
|
||||||
|
T extends EntityConfig | LovelaceRowConfig
|
||||||
|
>(
|
||||||
entities: Array<T | string>
|
entities: Array<T | string>
|
||||||
): T[] => {
|
): T[] => {
|
||||||
if (!entities || !Array.isArray(entities)) {
|
if (!entities || !Array.isArray(entities)) {
|
||||||
@ -24,7 +26,7 @@ export const processConfigEntities = <T extends EntityConfig>(
|
|||||||
if (typeof entityConf === "string") {
|
if (typeof entityConf === "string") {
|
||||||
config = { entity: entityConf } as T;
|
config = { entity: entityConf } as T;
|
||||||
} else if (typeof entityConf === "object" && !Array.isArray(entityConf)) {
|
} else if (typeof entityConf === "object" && !Array.isArray(entityConf)) {
|
||||||
if (!entityConf.entity) {
|
if (!("entity" in entityConf)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Entity object at position ${index} is missing entity field.`
|
`Entity object at position ${index} is missing entity field.`
|
||||||
);
|
);
|
||||||
@ -34,9 +36,11 @@ export const processConfigEntities = <T extends EntityConfig>(
|
|||||||
throw new Error(`Invalid entity specified at position ${index}.`);
|
throw new Error(`Invalid entity specified at position ${index}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidEntityId(config.entity)) {
|
if (!isValidEntityId((config as EntityConfig).entity!)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid entity ID at position ${index}: ${config.entity}`
|
`Invalid entity ID at position ${index}: ${
|
||||||
|
(config as EntityConfig).entity
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
LovelaceCard,
|
LovelaceCard,
|
||||||
LovelaceCardConstructor,
|
LovelaceCardConstructor,
|
||||||
LovelaceHeaderFooter,
|
LovelaceHeaderFooter,
|
||||||
|
LovelaceRowConstructor,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
|
|
||||||
const TIMEOUT = 2000;
|
const TIMEOUT = 2000;
|
||||||
@ -39,7 +40,7 @@ interface CreateElementConfigTypes {
|
|||||||
row: {
|
row: {
|
||||||
config: LovelaceRowConfig;
|
config: LovelaceRowConfig;
|
||||||
element: LovelaceRow;
|
element: LovelaceRow;
|
||||||
constructor: unknown;
|
constructor: LovelaceRowConstructor;
|
||||||
};
|
};
|
||||||
"header-footer": {
|
"header-footer": {
|
||||||
config: LovelaceHeaderFooterConfig;
|
config: LovelaceHeaderFooterConfig;
|
||||||
|
@ -4,11 +4,14 @@ import "../entity-rows/hui-script-entity-row";
|
|||||||
import "../entity-rows/hui-sensor-entity-row";
|
import "../entity-rows/hui-sensor-entity-row";
|
||||||
import "../entity-rows/hui-text-entity-row";
|
import "../entity-rows/hui-text-entity-row";
|
||||||
import "../entity-rows/hui-toggle-entity-row";
|
import "../entity-rows/hui-toggle-entity-row";
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { LovelaceRowConfig } from "../entity-rows/types";
|
||||||
import "../special-rows/hui-attribute-row";
|
import "../special-rows/hui-attribute-row";
|
||||||
import "../special-rows/hui-button-row";
|
import "../special-rows/hui-button-row";
|
||||||
import "../special-rows/hui-call-service-row";
|
import "../special-rows/hui-call-service-row";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import {
|
||||||
|
createLovelaceElement,
|
||||||
|
getLovelaceElementClass,
|
||||||
|
} from "./create-element-base";
|
||||||
|
|
||||||
const ALWAYS_LOADED_TYPES = new Set([
|
const ALWAYS_LOADED_TYPES = new Set([
|
||||||
"media-player-entity",
|
"media-player-entity",
|
||||||
@ -74,7 +77,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
|
|||||||
weather: "weather",
|
weather: "weather",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createRowElement = (config: EntityConfig) =>
|
export const createRowElement = (config: LovelaceRowConfig) =>
|
||||||
createLovelaceElement(
|
createLovelaceElement(
|
||||||
"row",
|
"row",
|
||||||
config,
|
config,
|
||||||
@ -83,3 +86,12 @@ export const createRowElement = (config: EntityConfig) =>
|
|||||||
DOMAIN_TO_ELEMENT_TYPE,
|
DOMAIN_TO_ELEMENT_TYPE,
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getRowElementClass = (type: string) => {
|
||||||
|
return getLovelaceElementClass(
|
||||||
|
type,
|
||||||
|
"row",
|
||||||
|
ALWAYS_LOADED_TYPES,
|
||||||
|
LAZY_LOAD_TYPES
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
|
import { mdiHelpCircle } from "@mdi/js";
|
||||||
import deepFreeze from "deep-freeze";
|
import deepFreeze from "deep-freeze";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultArray,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
PropertyValues,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
PropertyValues,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { mdiHelpCircle } from "@mdi/js";
|
|
||||||
|
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
|
||||||
import { haStyleDialog } from "../../../../resources/styles";
|
|
||||||
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
|
||||||
import { addCard, replaceCard } from "../config-util";
|
|
||||||
import { getCardDocumentationURL } from "../get-card-documentation-url";
|
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
|
||||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
|
||||||
|
|
||||||
import type { HomeAssistant } from "../../../../types";
|
|
||||||
import type { GUIModeChangedEvent } from "../types";
|
|
||||||
import type { ConfigChangedEvent, HuiCardEditor } from "./hui-card-editor";
|
|
||||||
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
|
||||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
|
||||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
|
import "../../../../components/ha-circular-progress";
|
||||||
|
import "../../../../components/ha-dialog";
|
||||||
|
import "../../../../components/ha-header-bar";
|
||||||
import type {
|
import type {
|
||||||
LovelaceCardConfig,
|
LovelaceCardConfig,
|
||||||
LovelaceViewConfig,
|
LovelaceViewConfig,
|
||||||
} from "../../../../data/lovelace";
|
} from "../../../../data/lovelace";
|
||||||
|
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
import "./hui-card-editor";
|
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||||
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
||||||
|
import { addCard, replaceCard } from "../config-util";
|
||||||
|
import { getCardDocumentationURL } from "../get-card-documentation-url";
|
||||||
|
import "../hui-element-editor";
|
||||||
|
import type {
|
||||||
|
ConfigChangedEvent,
|
||||||
|
HuiElementEditor,
|
||||||
|
} from "../hui-element-editor";
|
||||||
|
import type { GUIModeChangedEvent } from "../types";
|
||||||
import "./hui-card-preview";
|
import "./hui-card-preview";
|
||||||
import "../../../../components/ha-dialog";
|
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
||||||
import "../../../../components/ha-header-bar";
|
|
||||||
import "../../../../components/ha-circular-progress";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -65,7 +65,7 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
|||||||
|
|
||||||
@internalProperty() private _guiModeAvailable? = true;
|
@internalProperty() private _guiModeAvailable? = true;
|
||||||
|
|
||||||
@query("hui-card-editor") private _cardEditorEl?: HuiCardEditor;
|
@query("hui-element-editor") private _cardEditorEl?: HuiElementEditor;
|
||||||
|
|
||||||
@internalProperty() private _GUImode = true;
|
@internalProperty() private _GUImode = true;
|
||||||
|
|
||||||
@ -183,14 +183,14 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="element-editor">
|
<div class="element-editor">
|
||||||
<hui-card-editor
|
<hui-element-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.lovelace=${this._params.lovelaceConfig}
|
.lovelace=${this._params.lovelaceConfig}
|
||||||
.value=${this._cardConfig}
|
.value=${this._cardConfig}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
@editor-save=${this._save}
|
@editor-save=${this._save}
|
||||||
></hui-card-editor>
|
></hui-element-editor>
|
||||||
</div>
|
</div>
|
||||||
<div class="element-preview">
|
<div class="element-preview">
|
||||||
<hui-card-preview
|
<hui-card-preview
|
||||||
@ -364,6 +364,8 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
|||||||
@media all and (min-width: 850px) {
|
@media all and (min-width: 850px) {
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
--mdc-dialog-min-width: 845px;
|
--mdc-dialog-min-width: 845px;
|
||||||
|
--dialog-surface-top: 40px;
|
||||||
|
--mdc-dialog-max-height: calc(100% - 72px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,6 +404,9 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
|||||||
ha-dialog {
|
ha-dialog {
|
||||||
--mdc-dialog-max-width: calc(100% - 32px);
|
--mdc-dialog-max-width: calc(100% - 32px);
|
||||||
--mdc-dialog-min-width: 1000px;
|
--mdc-dialog-min-width: 1000px;
|
||||||
|
--dialog-surface-position: fixed;
|
||||||
|
--dialog-surface-top: 40px;
|
||||||
|
--mdc-dialog-max-height: calc(100% - 72px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import { html } from "lit-element";
|
import { css } from "lit-element";
|
||||||
|
|
||||||
export const configElementStyle = html`
|
export const configElementStyle = css`
|
||||||
<style>
|
ha-switch {
|
||||||
ha-switch {
|
padding: 16px 0;
|
||||||
padding: 16px 0;
|
}
|
||||||
}
|
.side-by-side {
|
||||||
.side-by-side {
|
display: flex;
|
||||||
display: flex;
|
}
|
||||||
}
|
.side-by-side > * {
|
||||||
.side-by-side > * {
|
flex: 1;
|
||||||
flex: 1;
|
padding-right: 4px;
|
||||||
padding-right: 4px;
|
}
|
||||||
}
|
.suffix {
|
||||||
.suffix {
|
margin: 0 8px;
|
||||||
margin: 0 8px;
|
}
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`;
|
`;
|
||||||
|
@ -3,14 +3,15 @@ import "@polymer/paper-item/paper-item";
|
|||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { array, assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
@ -20,7 +21,6 @@ import "../../components/hui-theme-select-editor";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { assert, object, string, optional, array } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -68,7 +68,6 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
|||||||
const states = ["arm_home", "arm_away", "arm_night", "arm_custom_bypass"];
|
const states = ["arm_home", "arm_away", "arm_night", "arm_custom_bypass"];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -128,22 +127,25 @@ export class HuiAlarmPanelCardEditor extends LitElement
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResultArray {
|
||||||
return css`
|
return [
|
||||||
.states {
|
configElementStyle,
|
||||||
display: flex;
|
css`
|
||||||
flex-direction: row;
|
.states {
|
||||||
}
|
display: flex;
|
||||||
.deleteState {
|
flex-direction: row;
|
||||||
visibility: hidden;
|
}
|
||||||
}
|
.deleteState {
|
||||||
.states:hover > .deleteState {
|
visibility: hidden;
|
||||||
visibility: visible;
|
}
|
||||||
}
|
.states:hover > .deleteState {
|
||||||
ha-icon {
|
visibility: visible;
|
||||||
padding-top: 12px;
|
}
|
||||||
}
|
ha-icon {
|
||||||
`;
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _stateRemoved(ev: EntitiesEditorEvent): void {
|
private _stateRemoved(ev: EntitiesEditorEvent): void {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -109,7 +110,6 @@ export class HuiButtonCardEditor extends LitElement
|
|||||||
const dir = computeRTLDirection(this.hass!);
|
const dir = computeRTLDirection(this.hass!);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -293,6 +293,10 @@ export class HuiButtonCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: newConfig });
|
fireEvent(this, "config-changed", { config: newConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -68,7 +69,6 @@ export class HuiCalendarCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<div class="side-by-side">
|
<div class="side-by-side">
|
||||||
<paper-input
|
<paper-input
|
||||||
@ -174,6 +174,10 @@ export class HuiCalendarCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -2,28 +2,30 @@ import "@polymer/paper-tabs";
|
|||||||
import "@polymer/paper-tabs/paper-tab";
|
import "@polymer/paper-tabs/paper-tab";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { any, array, assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import { LovelaceConfig } from "../../../../data/lovelace";
|
import { LovelaceCardConfig, LovelaceConfig } from "../../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { ConditionalCardConfig } from "../../cards/types";
|
import { ConditionalCardConfig } from "../../cards/types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import {
|
|
||||||
ConfigChangedEvent,
|
|
||||||
HuiCardEditor,
|
|
||||||
} from "../card-editor/hui-card-editor";
|
|
||||||
import "../card-editor/hui-card-picker";
|
import "../card-editor/hui-card-picker";
|
||||||
|
import "../hui-element-editor";
|
||||||
|
import type {
|
||||||
|
ConfigChangedEvent,
|
||||||
|
HuiElementEditor,
|
||||||
|
} from "../hui-element-editor";
|
||||||
import { GUIModeChangedEvent } from "../types";
|
import { GUIModeChangedEvent } from "../types";
|
||||||
import { string, any, object, optional, array, assert } from "superstruct";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
const conditionStruct = object({
|
const conditionStruct = object({
|
||||||
entity: string(),
|
entity: string(),
|
||||||
@ -51,7 +53,7 @@ export class HuiConditionalCardEditor extends LitElement
|
|||||||
|
|
||||||
@internalProperty() private _cardTab = false;
|
@internalProperty() private _cardTab = false;
|
||||||
|
|
||||||
@query("hui-card-editor") private _cardEditorEl?: HuiCardEditor;
|
@query("hui-element-editor") private _cardEditorEl?: HuiElementEditor;
|
||||||
|
|
||||||
public setConfig(config: ConditionalCardConfig): void {
|
public setConfig(config: ConditionalCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
@ -106,13 +108,13 @@ export class HuiConditionalCardEditor extends LitElement
|
|||||||
)}</mwc-button
|
)}</mwc-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<hui-card-editor
|
<hui-element-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._config.card}
|
.value=${this._config.card}
|
||||||
.lovelace=${this.lovelace}
|
.lovelace=${this.lovelace}
|
||||||
@config-changed=${this._handleCardChanged}
|
@config-changed=${this._handleCardChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-card-editor>
|
></hui-element-editor>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<hui-card-picker
|
<hui-card-picker
|
||||||
@ -227,7 +229,10 @@ export class HuiConditionalCardEditor extends LitElement
|
|||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._config = { ...this._config, card: ev.detail.config };
|
this._config = {
|
||||||
|
...this._config,
|
||||||
|
card: ev.detail.config as LovelaceCardConfig,
|
||||||
|
};
|
||||||
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
@ -292,52 +297,55 @@ export class HuiConditionalCardEditor extends LitElement
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResultArray {
|
||||||
return css`
|
return [
|
||||||
paper-tabs {
|
configElementStyle,
|
||||||
--paper-tabs-selection-bar-color: var(--primary-color);
|
css`
|
||||||
--paper-tab-ink: var(--primary-color);
|
paper-tabs {
|
||||||
border-bottom: 1px solid var(--divider-color);
|
--paper-tabs-selection-bar-color: var(--primary-color);
|
||||||
}
|
--paper-tab-ink: var(--primary-color);
|
||||||
.conditions {
|
border-bottom: 1px solid var(--divider-color);
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
.condition {
|
|
||||||
margin-top: 8px;
|
|
||||||
border: 1px solid var(--divider-color);
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
.condition .state {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
}
|
|
||||||
.condition .state paper-dropdown-menu {
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
.condition .state paper-input {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
margin-top: 8px;
|
|
||||||
border: 1px solid var(--divider-color);
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
@media (max-width: 450px) {
|
|
||||||
.card,
|
|
||||||
.condition {
|
|
||||||
margin: 8px -12px 0;
|
|
||||||
}
|
}
|
||||||
}
|
.conditions {
|
||||||
.card .card-options {
|
margin-top: 8px;
|
||||||
display: flex;
|
}
|
||||||
justify-content: flex-end;
|
.condition {
|
||||||
width: 100%;
|
margin-top: 8px;
|
||||||
}
|
border: 1px solid var(--divider-color);
|
||||||
.gui-mode-button {
|
padding: 12px;
|
||||||
margin-right: auto;
|
}
|
||||||
}
|
.condition .state {
|
||||||
`;
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
.condition .state paper-dropdown-menu {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
.condition .state paper-input {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin-top: 8px;
|
||||||
|
border: 1px solid var(--divider-color);
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
.card,
|
||||||
|
.condition {
|
||||||
|
margin: 8px -12px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card .card-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.gui-mode-button {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,14 @@ 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 {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import {
|
import {
|
||||||
@ -18,7 +21,7 @@ import {
|
|||||||
string,
|
string,
|
||||||
union,
|
union,
|
||||||
} from "superstruct";
|
} from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
import "../../../../components/entity/state-badge";
|
import "../../../../components/entity/state-badge";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
@ -26,22 +29,33 @@ import "../../../../components/ha-formfield";
|
|||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
import "../../../../components/ha-switch";
|
import "../../../../components/ha-switch";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import {
|
import { EntitiesCardConfig } from "../../cards/types";
|
||||||
EntitiesCardConfig,
|
|
||||||
EntitiesCardEntityConfig,
|
|
||||||
} from "../../cards/types";
|
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import { LovelaceRowConfig } from "../../entity-rows/types";
|
||||||
import { headerFooterConfigStructs } from "../../header-footer/types";
|
import { headerFooterConfigStructs } from "../../header-footer/types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
|
import "../hui-detail-editor-base";
|
||||||
|
import { HuiElementEditor } from "../hui-element-editor";
|
||||||
import "../hui-entities-card-row-editor";
|
import "../hui-entities-card-row-editor";
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import {
|
import {
|
||||||
EditorTarget,
|
EditorTarget,
|
||||||
entitiesConfigStruct,
|
entitiesConfigStruct,
|
||||||
EntitiesEditorEvent,
|
EntitiesEditorEvent,
|
||||||
|
GUIModeChangedEvent,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
|
interface EditRowEvent {
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"edit-row": EditRowEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
title: optional(union([string(), boolean()])),
|
title: optional(union([string(), boolean()])),
|
||||||
@ -60,7 +74,17 @@ export class HuiEntitiesCardEditor extends LitElement
|
|||||||
|
|
||||||
@internalProperty() private _config?: EntitiesCardConfig;
|
@internalProperty() private _config?: EntitiesCardConfig;
|
||||||
|
|
||||||
@internalProperty() private _configEntities?: EntitiesCardEntityConfig[];
|
@internalProperty() private _configEntities?: LovelaceRowConfig[];
|
||||||
|
|
||||||
|
@internalProperty() private _editRowConfig?: LovelaceRowConfig;
|
||||||
|
|
||||||
|
@internalProperty() private _editRowIndex?: number;
|
||||||
|
|
||||||
|
@internalProperty() private _editRowGuiModeAvailable? = true;
|
||||||
|
|
||||||
|
@internalProperty() private _editRowGuiMode? = true;
|
||||||
|
|
||||||
|
@query("hui-element-editor") private _cardEditorEl?: HuiElementEditor;
|
||||||
|
|
||||||
public setConfig(config: EntitiesCardConfig): void {
|
public setConfig(config: EntitiesCardConfig): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
@ -81,8 +105,32 @@ export class HuiEntitiesCardEditor extends LitElement
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._editRowConfig) {
|
||||||
|
return html`
|
||||||
|
<hui-detail-editor-base
|
||||||
|
.hass=${this.hass}
|
||||||
|
.guiModeAvailable=${this._editRowGuiModeAvailable}
|
||||||
|
.guiMode=${this._editRowGuiMode}
|
||||||
|
@toggle-gui-mode=${this._toggleMode}
|
||||||
|
@go-back=${this._goBack}
|
||||||
|
>
|
||||||
|
<span slot="title"
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.card.entities.entity_row_editor"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<hui-element-editor
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this._editRowConfig}
|
||||||
|
elementType="row"
|
||||||
|
@config-changed=${this._handleEntityRowConfigChanged}
|
||||||
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
|
></hui-element-editor>
|
||||||
|
</hui-detail-editor-base>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -127,11 +175,11 @@ export class HuiEntitiesCardEditor extends LitElement
|
|||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hui-entities-card-row-editor
|
<hui-entities-card-row-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.entities=${this._configEntities}
|
.entities=${this._configEntities}
|
||||||
@entities-changed=${this._valueChanged}
|
@entities-changed=${this._valueChanged}
|
||||||
|
@edit-row=${this._editRow}
|
||||||
></hui-entities-card-row-editor>
|
></hui-entities-card-row-editor>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -169,6 +217,65 @@ export class HuiEntitiesCardEditor extends LitElement
|
|||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _editRow(ev: HASSDomEvent<EditRowEvent>): void {
|
||||||
|
this._editRowIndex = ev.detail.index;
|
||||||
|
this._editRowConfig = this._configEntities![this._editRowIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
private _goBack(): void {
|
||||||
|
this._editRowIndex = undefined;
|
||||||
|
this._editRowConfig = undefined;
|
||||||
|
this._editRowGuiModeAvailable = true;
|
||||||
|
this._editRowGuiMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _toggleMode(): void {
|
||||||
|
this._cardEditorEl?.toggleMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleEntityRowConfigChanged(ev: CustomEvent): void {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const value = ev.detail.config as LovelaceRowConfig;
|
||||||
|
this._editRowGuiModeAvailable = ev.detail.guiModeAvailable;
|
||||||
|
|
||||||
|
const newConfigEntities = this._configEntities!.concat();
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
newConfigEntities.splice(this._editRowIndex!, 1);
|
||||||
|
this._goBack();
|
||||||
|
} else {
|
||||||
|
newConfigEntities[this._editRowIndex!] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._editRowConfig = value;
|
||||||
|
|
||||||
|
this._config = { ...this._config!, entities: newConfigEntities };
|
||||||
|
|
||||||
|
this._configEntities = processEditorEntities(this._config!.entities);
|
||||||
|
|
||||||
|
fireEvent(this, "config-changed", { config: this._config! });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._editRowGuiMode = ev.detail.guiMode;
|
||||||
|
this._editRowGuiModeAvailable = ev.detail.guiModeAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultArray {
|
||||||
|
return [
|
||||||
|
configElementStyle,
|
||||||
|
css`
|
||||||
|
.edit-entity-row-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -75,7 +76,6 @@ export class HuiEntityCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -186,6 +186,10 @@ export class HuiEntityCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -81,7 +81,6 @@ export class HuiGaugeCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -197,23 +196,26 @@ export class HuiGaugeCardEditor extends LitElement
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResultArray {
|
||||||
return css`
|
return [
|
||||||
.severity {
|
configElementStyle,
|
||||||
display: none;
|
css`
|
||||||
width: 100%;
|
.severity {
|
||||||
padding-left: 16px;
|
display: none;
|
||||||
flex-direction: row;
|
width: 100%;
|
||||||
flex-wrap: wrap;
|
padding-left: 16px;
|
||||||
}
|
flex-direction: row;
|
||||||
.severity > * {
|
flex-wrap: wrap;
|
||||||
flex: 1 0 30%;
|
}
|
||||||
padding-right: 4px;
|
.severity > * {
|
||||||
}
|
flex: 1 0 30%;
|
||||||
ha-switch[checked] ~ .severity {
|
padding-right: 4px;
|
||||||
display: flex;
|
}
|
||||||
}
|
ha-switch[checked] ~ .severity {
|
||||||
`;
|
display: flex;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toggleSeverity(ev: EntitiesEditorEvent): void {
|
private _toggleSeverity(ev: EntitiesEditorEvent): void {
|
||||||
|
@ -0,0 +1,173 @@
|
|||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import {
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { assert } from "superstruct";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||||
|
import { stateIcon } from "../../../../common/entity/state_icon";
|
||||||
|
import "../../../../components/ha-formfield";
|
||||||
|
import "../../../../components/ha-icon-input";
|
||||||
|
import "../../../../components/ha-switch";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import { EntitiesCardEntityConfig } from "../../cards/types";
|
||||||
|
import "../../components/hui-action-editor";
|
||||||
|
import "../../components/hui-entity-editor";
|
||||||
|
import "../../components/hui-theme-select-editor";
|
||||||
|
import { LovelaceRowEditor } from "../../types";
|
||||||
|
import {
|
||||||
|
EditorTarget,
|
||||||
|
entitiesConfigStruct,
|
||||||
|
EntitiesEditorEvent,
|
||||||
|
} from "../types";
|
||||||
|
import { configElementStyle } from "./config-elements-style";
|
||||||
|
|
||||||
|
const SecondaryInfoValues: { [key: string]: { domains?: string[] } } = {
|
||||||
|
"entity-id": {},
|
||||||
|
"last-changed": {},
|
||||||
|
"last-triggered": { domains: ["automation", "script"] },
|
||||||
|
position: { domains: ["cover"] },
|
||||||
|
"tilt-position": { domains: ["cover"] },
|
||||||
|
brightness: { domains: ["light"] },
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("hui-generic-entity-row-editor")
|
||||||
|
export class HuiGenericEntityRowEditor extends LitElement
|
||||||
|
implements LovelaceRowEditor {
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@internalProperty() private _config?: EntitiesCardEntityConfig;
|
||||||
|
|
||||||
|
public setConfig(config: EntitiesCardEntityConfig): void {
|
||||||
|
assert(config, entitiesConfigStruct);
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
get _entity(): string {
|
||||||
|
return this._config!.entity || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
get _name(): string {
|
||||||
|
return this._config!.name || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
get _icon(): string {
|
||||||
|
return this._config!.icon || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
get _secondary_info(): string {
|
||||||
|
return this._config!.secondary_info || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.hass || !this._config) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
const domain = computeDomain(this._config.entity);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="card-config">
|
||||||
|
<ha-entity-picker
|
||||||
|
allow-custom-entity
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this._config.entity}
|
||||||
|
.configValue=${"entity"}
|
||||||
|
@change=${this._valueChanged}
|
||||||
|
></ha-entity-picker>
|
||||||
|
<div class="side-by-side">
|
||||||
|
<paper-input
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.card.generic.name"
|
||||||
|
)}
|
||||||
|
.value=${this._config.name}
|
||||||
|
.configValue=${"name"}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></paper-input>
|
||||||
|
<ha-icon-input
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.card.generic.icon"
|
||||||
|
)}
|
||||||
|
.value=${this._config.icon}
|
||||||
|
.placeholder=${stateIcon(this.hass!.states[this._config.entity])}
|
||||||
|
.configValue=${"icon"}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-icon-input>
|
||||||
|
</div>
|
||||||
|
<paper-dropdown-menu .label=${"Secondary Info"}>
|
||||||
|
<paper-listbox
|
||||||
|
slot="dropdown-content"
|
||||||
|
attr-for-selected="value"
|
||||||
|
.selected=${this._config.secondary_info || "none"}
|
||||||
|
.configValue=${"secondary_info"}
|
||||||
|
@iron-select=${this._valueChanged}
|
||||||
|
>
|
||||||
|
<paper-item value=""
|
||||||
|
>${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.card.entities.secondary_info_values.none"
|
||||||
|
)}</paper-item
|
||||||
|
>
|
||||||
|
${Object.keys(SecondaryInfoValues).map((info) => {
|
||||||
|
if (
|
||||||
|
!("domains" in SecondaryInfoValues[info]) ||
|
||||||
|
("domains" in SecondaryInfoValues[info] &&
|
||||||
|
SecondaryInfoValues[info].domains!.includes(domain))
|
||||||
|
) {
|
||||||
|
return html`
|
||||||
|
<paper-item .value=${info}
|
||||||
|
>${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.entities.secondary_info_values.${info}`
|
||||||
|
)}</paper-item
|
||||||
|
>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
})}
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: EntitiesEditorEvent): void {
|
||||||
|
if (!this._config || !this.hass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = ev.target! as EditorTarget;
|
||||||
|
const value = target.value || ev.detail?.item?.value;
|
||||||
|
|
||||||
|
if (this[`_${target.configValue}`] === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.configValue) {
|
||||||
|
if (value === "" || !value) {
|
||||||
|
this._config = { ...this._config };
|
||||||
|
delete this._config[target.configValue!];
|
||||||
|
} else {
|
||||||
|
this._config = {
|
||||||
|
...this._config,
|
||||||
|
[target.configValue!]: value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-generic-entity-row-editor": HuiGenericEntityRowEditor;
|
||||||
|
}
|
||||||
|
}
|
@ -2,19 +2,31 @@ 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 {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import {
|
||||||
|
array,
|
||||||
|
assert,
|
||||||
|
boolean,
|
||||||
|
number,
|
||||||
|
object,
|
||||||
|
optional,
|
||||||
|
string,
|
||||||
|
union,
|
||||||
|
} from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
import "../../../../components/entity/state-badge";
|
import "../../../../components/entity/state-badge";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-formfield";
|
||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
import "../../../../components/ha-switch";
|
import "../../../../components/ha-switch";
|
||||||
import "../../../../components/ha-formfield";
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { ConfigEntity, GlanceCardConfig } from "../../cards/types";
|
import { ConfigEntity, GlanceCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-entity-editor";
|
import "../../components/hui-entity-editor";
|
||||||
@ -27,17 +39,6 @@ import {
|
|||||||
EntitiesEditorEvent,
|
EntitiesEditorEvent,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
|
||||||
import {
|
|
||||||
string,
|
|
||||||
union,
|
|
||||||
object,
|
|
||||||
optional,
|
|
||||||
number,
|
|
||||||
boolean,
|
|
||||||
assert,
|
|
||||||
array,
|
|
||||||
} from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -102,7 +103,6 @@ export class HuiGlanceCardEditor extends LitElement
|
|||||||
const dir = computeRTLDirection(this.hass!);
|
const dir = computeRTLDirection(this.hass!);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -234,6 +234,10 @@ export class HuiGlanceCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,31 +1,32 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import {
|
||||||
|
array,
|
||||||
|
assert,
|
||||||
|
number,
|
||||||
|
object,
|
||||||
|
optional,
|
||||||
|
string,
|
||||||
|
union,
|
||||||
|
} from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { HistoryGraphCardConfig } from "../../cards/types";
|
import { HistoryGraphCardConfig } from "../../cards/types";
|
||||||
|
import { EntityId } from "../../common/structs/is-entity-id";
|
||||||
import "../../components/hui-entity-editor";
|
import "../../components/hui-entity-editor";
|
||||||
import { EntityConfig } from "../../entity-rows/types";
|
import { EntityConfig } from "../../entity-rows/types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { processEditorEntities } from "../process-editor-entities";
|
import { processEditorEntities } from "../process-editor-entities";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import {
|
|
||||||
assert,
|
|
||||||
union,
|
|
||||||
optional,
|
|
||||||
string,
|
|
||||||
object,
|
|
||||||
array,
|
|
||||||
number,
|
|
||||||
} from "superstruct";
|
|
||||||
import { EntityId } from "../../common/structs/is-entity-id";
|
|
||||||
|
|
||||||
const entitiesConfigStruct = union([
|
const entitiesConfigStruct = union([
|
||||||
object({
|
object({
|
||||||
@ -80,7 +81,6 @@ export class HuiHistoryGraphCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -156,6 +156,10 @@ export class HuiHistoryGraphCardEditor extends LitElement
|
|||||||
|
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
@ -15,7 +17,6 @@ import "../../components/hui-theme-select-editor";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { string, object, optional, assert } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -56,7 +57,6 @@ export class HuiHumidifierCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -110,6 +110,10 @@ export class HuiHumidifierCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { IframeCardConfig } from "../../cards/types";
|
import { IframeCardConfig } from "../../cards/types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { string, assert, object, optional } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -52,7 +53,6 @@ export class HuiIframeCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -110,6 +110,10 @@ export class HuiIframeCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -84,7 +85,6 @@ export class HuiLightCardEditor extends LitElement
|
|||||||
];
|
];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -183,6 +183,10 @@ export class HuiLightCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import {
|
||||||
|
array,
|
||||||
|
assert,
|
||||||
|
boolean,
|
||||||
|
number,
|
||||||
|
object,
|
||||||
|
optional,
|
||||||
|
string,
|
||||||
|
} from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
|
import "../../../../components/ha-formfield";
|
||||||
|
import "../../../../components/ha-switch";
|
||||||
import { PolymerChangedEvent } from "../../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../../polymer-types";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { MapCardConfig } from "../../cards/types";
|
import { MapCardConfig } from "../../cards/types";
|
||||||
@ -23,19 +35,7 @@ import {
|
|||||||
entitiesConfigStruct,
|
entitiesConfigStruct,
|
||||||
EntitiesEditorEvent,
|
EntitiesEditorEvent,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import "../../../../components/ha-switch";
|
|
||||||
import "../../../../components/ha-formfield";
|
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
|
||||||
import {
|
|
||||||
string,
|
|
||||||
optional,
|
|
||||||
object,
|
|
||||||
number,
|
|
||||||
boolean,
|
|
||||||
array,
|
|
||||||
assert,
|
|
||||||
} from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -94,7 +94,6 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -216,12 +215,15 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
|
|||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResultArray {
|
||||||
return css`
|
return [
|
||||||
.geo_location_sources {
|
configElementStyle,
|
||||||
padding-left: 20px;
|
css`
|
||||||
}
|
.geo_location_sources {
|
||||||
`;
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { MarkdownCardConfig } from "../../cards/types";
|
import { MarkdownCardConfig } from "../../cards/types";
|
||||||
@ -15,7 +17,6 @@ import "../../components/hui-theme-select-editor";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { string, assert, object, optional } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -54,7 +55,6 @@ export class HuiMarkdownCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -116,6 +116,10 @@ export class HuiMarkdownCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -62,7 +63,6 @@ export class HuiPictureCardEditor extends LitElement
|
|||||||
const actions = ["navigate", "url", "call-service", "none"];
|
const actions = ["navigate", "url", "call-service", "none"];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -133,6 +133,10 @@ export class HuiPictureCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -3,6 +3,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
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 {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -108,7 +109,6 @@ export class HuiPictureEntityCardEditor extends LitElement
|
|||||||
const dir = computeRTLDirection(this.hass!);
|
const dir = computeRTLDirection(this.hass!);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -293,6 +293,10 @@ export class HuiPictureEntityCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -3,6 +3,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
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 {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -111,7 +112,6 @@ export class HuiPictureGlanceCardEditor extends LitElement
|
|||||||
const views = ["auto", "live"];
|
const views = ["auto", "live"];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -257,6 +257,10 @@ export class HuiPictureGlanceCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
@ -16,7 +18,6 @@ import "../../components/hui-theme-select-editor";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { assert, object, string, optional } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -57,7 +58,6 @@ export class HuiPlantStatusCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -113,6 +113,10 @@ export class HuiPlantStatusCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -3,6 +3,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
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 {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
@ -90,7 +91,6 @@ export class HuiSensorCardEditor extends LitElement
|
|||||||
const graphs = ["line", "none"];
|
const graphs = ["line", "none"];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -238,6 +238,10 @@ export class HuiSensorCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import "../../../../components/ha-icon-button";
|
|
||||||
import "@polymer/paper-tabs";
|
import "@polymer/paper-tabs";
|
||||||
import "@polymer/paper-tabs/paper-tab";
|
import "@polymer/paper-tabs/paper-tab";
|
||||||
import {
|
import {
|
||||||
@ -6,24 +5,26 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { any, array, assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
import { LovelaceConfig } from "../../../../data/lovelace";
|
import "../../../../components/ha-icon-button";
|
||||||
|
import { LovelaceCardConfig, LovelaceConfig } from "../../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { StackCardConfig } from "../../cards/types";
|
import { StackCardConfig } from "../../cards/types";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import {
|
|
||||||
ConfigChangedEvent,
|
|
||||||
HuiCardEditor,
|
|
||||||
} from "../card-editor/hui-card-editor";
|
|
||||||
import "../card-editor/hui-card-picker";
|
import "../card-editor/hui-card-picker";
|
||||||
|
import "../hui-element-editor";
|
||||||
|
import type {
|
||||||
|
ConfigChangedEvent,
|
||||||
|
HuiElementEditor,
|
||||||
|
} from "../hui-element-editor";
|
||||||
import { GUIModeChangedEvent } from "../types";
|
import { GUIModeChangedEvent } from "../types";
|
||||||
import { assert, object, string, array, any, optional } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -46,7 +47,7 @@ export class HuiStackCardEditor extends LitElement
|
|||||||
|
|
||||||
@internalProperty() private _guiModeAvailable? = true;
|
@internalProperty() private _guiModeAvailable? = true;
|
||||||
|
|
||||||
@query("hui-card-editor") private _cardEditorEl?: HuiCardEditor;
|
@query("hui-element-editor") private _cardEditorEl?: HuiElementEditor;
|
||||||
|
|
||||||
public setConfig(config: Readonly<StackCardConfig>): void {
|
public setConfig(config: Readonly<StackCardConfig>): void {
|
||||||
assert(config, cardConfigStruct);
|
assert(config, cardConfigStruct);
|
||||||
@ -128,13 +129,13 @@ export class HuiStackCardEditor extends LitElement
|
|||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hui-card-editor
|
<hui-element-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._config.cards[selected]}
|
.value=${this._config.cards[selected]}
|
||||||
.lovelace=${this.lovelace}
|
.lovelace=${this.lovelace}
|
||||||
@config-changed=${this._handleConfigChanged}
|
@config-changed=${this._handleConfigChanged}
|
||||||
@GUImode-changed=${this._handleGUIModeChanged}
|
@GUImode-changed=${this._handleGUIModeChanged}
|
||||||
></hui-card-editor>
|
></hui-element-editor>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<hui-card-picker
|
<hui-card-picker
|
||||||
@ -164,7 +165,7 @@ export class HuiStackCardEditor extends LitElement
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cards = [...this._config.cards];
|
const cards = [...this._config.cards];
|
||||||
cards[this._selectedCard] = ev.detail.config;
|
cards[this._selectedCard] = ev.detail.config as LovelaceCardConfig;
|
||||||
this._config = { ...this._config, cards };
|
this._config = { ...this._config, cards };
|
||||||
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
@ -15,7 +17,6 @@ import "../../components/hui-theme-select-editor";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { object, string, optional, assert } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -56,7 +57,6 @@ export class HuiThermostatCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -110,6 +110,10 @@ export class HuiThermostatCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, boolean, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import "../../../../components/ha-switch";
|
|
||||||
import "../../../../components/ha-formfield";
|
import "../../../../components/ha-formfield";
|
||||||
|
import "../../../../components/ha-switch";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { WeatherForecastCardConfig } from "../../cards/types";
|
import { WeatherForecastCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../components/hui-theme-select-editor";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
|
||||||
import { object, string, optional, boolean, assert } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -68,7 +69,6 @@ export class HuiWeatherForecastCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -151,6 +151,10 @@ export class HuiWeatherForecastCardEditor extends LitElement
|
|||||||
}
|
}
|
||||||
fireEvent(this, "config-changed", { config: this._config });
|
fireEvent(this, "config-changed", { config: this._config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
86
src/panels/lovelace/editor/hui-detail-editor-base.ts
Normal file
86
src/panels/lovelace/editor/hui-detail-editor-base.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import "@material/mwc-button";
|
||||||
|
import "@material/mwc-icon-button";
|
||||||
|
import { mdiArrowLeft } from "@mdi/js";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import "../../../components/ha-svg-icon";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"go-back": undefined;
|
||||||
|
"toggle-gui-mode": undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("hui-detail-editor-base")
|
||||||
|
export class HuiDetailEditorBase extends LitElement {
|
||||||
|
public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public guiModeAvailable? = true;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public guiMode? = true;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="header">
|
||||||
|
<div class="back-title">
|
||||||
|
<mwc-icon-button @click=${this._goBack}>
|
||||||
|
<ha-svg-icon .path=${mdiArrowLeft}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
|
<slot name="title"></slot>
|
||||||
|
</div>
|
||||||
|
<mwc-button
|
||||||
|
slot="secondaryAction"
|
||||||
|
class="gui-mode-button"
|
||||||
|
.disabled=${!this.guiModeAvailable}
|
||||||
|
@click=${this._toggleMode}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
this.guiMode
|
||||||
|
? "ui.panel.lovelace.editor.edit_card.show_code_editor"
|
||||||
|
: "ui.panel.lovelace.editor.edit_card.show_visual_editor"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _goBack(): void {
|
||||||
|
fireEvent(this, "go-back");
|
||||||
|
}
|
||||||
|
|
||||||
|
private _toggleMode(): void {
|
||||||
|
fireEvent(this, "toggle-gui-mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.back-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-detail-editor-base": HuiDetailEditorBase;
|
||||||
|
}
|
||||||
|
}
|
@ -11,26 +11,33 @@ import {
|
|||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||||
import { deepEqual } from "../../../../common/util/deep-equal";
|
import { deepEqual } from "../../../common/util/deep-equal";
|
||||||
import "../../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
import "../../../../components/ha-code-editor";
|
import "../../../components/ha-code-editor";
|
||||||
import type { HaCodeEditor } from "../../../../components/ha-code-editor";
|
import type { HaCodeEditor } from "../../../components/ha-code-editor";
|
||||||
import type {
|
import type {
|
||||||
LovelaceCardConfig,
|
LovelaceCardConfig,
|
||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
} from "../../../../data/lovelace";
|
} from "../../../data/lovelace";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { handleStructError } from "../../common/structs/handle-errors";
|
import { handleStructError } from "../common/structs/handle-errors";
|
||||||
import { getCardElementClass } from "../../create-element/create-card-element";
|
import { getCardElementClass } from "../create-element/create-card-element";
|
||||||
import type { LovelaceRowConfig } from "../../entity-rows/types";
|
import { getRowElementClass } from "../create-element/create-row-element";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceRowConfig } from "../entity-rows/types";
|
||||||
import { GUISupportError } from "../gui-support-error";
|
import type {
|
||||||
import type { GUIModeChangedEvent } from "../types";
|
LovelaceCardConstructor,
|
||||||
|
LovelaceCardEditor,
|
||||||
|
LovelaceRowConstructor,
|
||||||
|
LovelaceRowEditor,
|
||||||
|
} from "../types";
|
||||||
|
import "./config-elements/hui-generic-entity-row-editor";
|
||||||
|
import { GUISupportError } from "./gui-support-error";
|
||||||
|
import { GUIModeChangedEvent } from "./types";
|
||||||
|
|
||||||
export interface ConfigChangedEvent {
|
export interface ConfigChangedEvent {
|
||||||
config: LovelaceCardConfig;
|
config: LovelaceCardConfig | LovelaceRowConfig;
|
||||||
error?: string;
|
error?: string;
|
||||||
guiModeAvailable?: boolean;
|
guiModeAvailable?: boolean;
|
||||||
}
|
}
|
||||||
@ -47,21 +54,27 @@ declare global {
|
|||||||
|
|
||||||
export interface UIConfigChangedEvent extends Event {
|
export interface UIConfigChangedEvent extends Event {
|
||||||
detail: {
|
detail: {
|
||||||
config: LovelaceCardConfig;
|
config: LovelaceCardConfig | LovelaceRowConfig;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@customElement("hui-card-editor")
|
const GENERIC_ROW_TYPE = "generic-row";
|
||||||
export class HuiCardEditor extends LitElement {
|
|
||||||
|
@customElement("hui-element-editor")
|
||||||
|
export class HuiElementEditor extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public lovelace?: LovelaceConfig;
|
@property({ attribute: false }) public lovelace?: LovelaceConfig;
|
||||||
|
|
||||||
|
@property() public elementType: "row" | "card" = "card";
|
||||||
|
|
||||||
@internalProperty() private _yaml?: string;
|
@internalProperty() private _yaml?: string;
|
||||||
|
|
||||||
@internalProperty() private _config?: LovelaceCardConfig;
|
@internalProperty() private _config?: LovelaceCardConfig | LovelaceRowConfig;
|
||||||
|
|
||||||
@internalProperty() private _configElement?: LovelaceCardEditor;
|
@internalProperty() private _configElement?:
|
||||||
|
| LovelaceCardEditor
|
||||||
|
| LovelaceRowEditor;
|
||||||
|
|
||||||
@internalProperty() private _configElType?: string;
|
@internalProperty() private _configElType?: string;
|
||||||
|
|
||||||
@ -95,11 +108,11 @@ export class HuiCardEditor extends LitElement {
|
|||||||
this._setConfig();
|
this._setConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get value(): LovelaceCardConfig | undefined {
|
public get value(): LovelaceCardConfig | LovelaceRowConfig | undefined {
|
||||||
return this._config;
|
return this._config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public set value(config: LovelaceCardConfig | undefined) {
|
public set value(config: LovelaceCardConfig | LovelaceRowConfig | undefined) {
|
||||||
if (this._config && deepEqual(config, this._config)) {
|
if (this._config && deepEqual(config, this._config)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -220,7 +233,11 @@ export class HuiCardEditor extends LitElement {
|
|||||||
if (this._configElement && changedProperties.has("hass")) {
|
if (this._configElement && changedProperties.has("hass")) {
|
||||||
this._configElement.hass = this.hass;
|
this._configElement.hass = this.hass;
|
||||||
}
|
}
|
||||||
if (this._configElement && changedProperties.has("lovelace")) {
|
if (
|
||||||
|
this._configElement &&
|
||||||
|
"lovelace" in this._configElement &&
|
||||||
|
changedProperties.has("lovelace")
|
||||||
|
) {
|
||||||
this._configElement.lovelace = this.lovelace;
|
this._configElement.lovelace = this.lovelace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,37 +261,61 @@ export class HuiCardEditor extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardType = this.value.type;
|
let type: string;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.elementType === "row" &&
|
||||||
|
!this.value.type &&
|
||||||
|
"entity" in this.value
|
||||||
|
) {
|
||||||
|
type = GENERIC_ROW_TYPE;
|
||||||
|
} else {
|
||||||
|
type = this.value.type!;
|
||||||
|
}
|
||||||
|
|
||||||
let configElement = this._configElement;
|
let configElement = this._configElement;
|
||||||
try {
|
try {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._warnings = undefined;
|
this._warnings = undefined;
|
||||||
|
|
||||||
if (this._configElType !== cardType) {
|
if (this._configElType !== type) {
|
||||||
// If the card type has changed, we need to load a new GUI editor
|
// If the type has changed, we need to load a new GUI editor
|
||||||
if (!this.value.type) {
|
if (!type) {
|
||||||
throw new Error("No card type defined");
|
throw new Error(`No ${this.elementType} type defined`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const elClass = await getCardElementClass(cardType);
|
let elClass:
|
||||||
|
| LovelaceCardConstructor
|
||||||
|
| LovelaceRowConstructor
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
if (this.elementType === "card") {
|
||||||
|
elClass = await getCardElementClass(type);
|
||||||
|
} else if (this.elementType === "row" && type !== GENERIC_ROW_TYPE) {
|
||||||
|
elClass = await getRowElementClass(type);
|
||||||
|
}
|
||||||
|
|
||||||
this._loading = true;
|
this._loading = true;
|
||||||
// Check if a GUI editor exists
|
// Check if a GUI editor exists
|
||||||
if (elClass && elClass.getConfigElement) {
|
if (elClass && elClass.getConfigElement) {
|
||||||
configElement = await elClass.getConfigElement();
|
configElement = await elClass.getConfigElement();
|
||||||
|
} else if (this.elementType === "row" && type === GENERIC_ROW_TYPE) {
|
||||||
|
configElement = document.createElement(
|
||||||
|
"hui-generic-entity-row-editor"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
configElement = undefined;
|
configElement = undefined;
|
||||||
throw new GUISupportError(
|
throw new GUISupportError(`No visual editor available for: ${type}`);
|
||||||
`No visual editor available for: ${cardType}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._configElement = configElement;
|
this._configElement = configElement;
|
||||||
this._configElType = cardType;
|
this._configElType = type;
|
||||||
|
|
||||||
// Perform final setup
|
// Perform final setup
|
||||||
this._configElement.hass = this.hass;
|
this._configElement.hass = this.hass;
|
||||||
this._configElement.lovelace = this.lovelace;
|
if ("lovelace" in this._configElement) {
|
||||||
|
this._configElement.lovelace = this.lovelace;
|
||||||
|
}
|
||||||
this._configElement.addEventListener("config-changed", (ev) =>
|
this._configElement.addEventListener("config-changed", (ev) =>
|
||||||
this._handleUIConfigChanged(ev as UIConfigChangedEvent)
|
this._handleUIConfigChanged(ev as UIConfigChangedEvent)
|
||||||
);
|
);
|
||||||
@ -282,6 +323,7 @@ export class HuiCardEditor extends LitElement {
|
|||||||
|
|
||||||
// Setup GUI editor and check that it can handle the current config
|
// Setup GUI editor and check that it can handle the current config
|
||||||
try {
|
try {
|
||||||
|
// @ts-ignore
|
||||||
this._configElement!.setConfig(this.value);
|
this._configElement!.setConfig(this.value);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new GUISupportError(
|
throw new GUISupportError(
|
||||||
@ -340,6 +382,6 @@ export class HuiCardEditor extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"hui-card-editor": HuiCardEditor;
|
"hui-element-editor": HuiElementEditor;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { mdiClose, mdiDrag } from "@mdi/js";
|
import "@material/mwc-icon-button";
|
||||||
|
import { mdiClose, mdiDrag, mdiPencil } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
@ -19,7 +20,7 @@ import Sortable, {
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/entity/ha-entity-picker";
|
import "../../../components/entity/ha-entity-picker";
|
||||||
import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker";
|
import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker";
|
||||||
import "../../../components/ha-icon-button";
|
import "../../../components/ha-svg-icon";
|
||||||
import { sortableStyles } from "../../../resources/ha-sortable-style";
|
import { sortableStyles } from "../../../resources/ha-sortable-style";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
|
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
|
||||||
@ -85,26 +86,38 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
)}</span
|
)}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<mwc-icon-button
|
|
||||||
aria-label=${this.hass!.localize(
|
|
||||||
"ui.components.entity.entity-picker.clear"
|
|
||||||
)}
|
|
||||||
.index=${index}
|
|
||||||
@click=${this._removeSpecialRow}
|
|
||||||
>
|
|
||||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
|
||||||
</mwc-icon-button>
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
|
hideClearIcon
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${(entityConf as EntityConfig).entity}
|
.value=${(entityConf as EntityConfig).entity}
|
||||||
.index=${index}
|
.index=${index}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
`}
|
`}
|
||||||
|
<mwc-icon-button
|
||||||
|
aria-label=${this.hass!.localize(
|
||||||
|
"ui.components.entity.entity-picker.clear"
|
||||||
|
)}
|
||||||
|
class="remove-icon"
|
||||||
|
.index=${index}
|
||||||
|
@click=${this._removeRow}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
|
<mwc-icon-button
|
||||||
|
aria-label=${this.hass!.localize(
|
||||||
|
"ui.components.entity.entity-picker.edit"
|
||||||
|
)}
|
||||||
|
class="edit-icon"
|
||||||
|
.index=${index}
|
||||||
|
@click=${this._editRow}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiPencil}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})
|
})
|
||||||
@ -164,7 +177,7 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
animation: 150,
|
animation: 150,
|
||||||
fallbackClass: "sortable-fallback",
|
fallbackClass: "sortable-fallback",
|
||||||
handle: ".handle",
|
handle: ".handle",
|
||||||
onEnd: async (evt: SortableEvent) => this._entityMoved(evt),
|
onEnd: async (evt: SortableEvent) => this._rowMoved(evt),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +193,7 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
fireEvent(this, "entities-changed", { entities: newConfigEntities });
|
fireEvent(this, "entities-changed", { entities: newConfigEntities });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entityMoved(ev: SortableEvent): void {
|
private _rowMoved(ev: SortableEvent): void {
|
||||||
if (ev.oldIndex === ev.newIndex) {
|
if (ev.oldIndex === ev.newIndex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -192,7 +205,7 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
fireEvent(this, "entities-changed", { entities: newEntities });
|
fireEvent(this, "entities-changed", { entities: newEntities });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeSpecialRow(ev: CustomEvent): void {
|
private _removeRow(ev: CustomEvent): void {
|
||||||
const index = (ev.currentTarget as any).index;
|
const index = (ev.currentTarget as any).index;
|
||||||
const newConfigEntities = this.entities!.concat();
|
const newConfigEntities = this.entities!.concat();
|
||||||
|
|
||||||
@ -218,6 +231,12 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
fireEvent(this, "entities-changed", { entities: newConfigEntities });
|
fireEvent(this, "entities-changed", { entities: newConfigEntities });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _editRow(ev: CustomEvent): void {
|
||||||
|
fireEvent(this, "edit-row", {
|
||||||
|
index: (ev.currentTarget as any).index,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
sortableStyles,
|
sortableStyles,
|
||||||
@ -226,13 +245,16 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity .handle {
|
.entity .handle {
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity ha-entity-picker {
|
.entity ha-entity-picker {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.special-row {
|
.special-row {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -247,7 +269,8 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.special-row mwc-icon-button {
|
.remove-icon,
|
||||||
|
.edit-icon {
|
||||||
--mdc-icon-button-size: 36px;
|
--mdc-icon-button-size: 36px;
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
@ -35,7 +36,6 @@ export class HuiLovelaceEditor extends LitElement {
|
|||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
@ -71,6 +71,10 @@ export class HuiLovelaceEditor extends LitElement {
|
|||||||
|
|
||||||
fireEvent(this, "lovelace-config-changed", { config: newConfig });
|
fireEvent(this, "lovelace-config-changed", { config: newConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return configElementStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
any,
|
any,
|
||||||
array,
|
array,
|
||||||
boolean,
|
boolean,
|
||||||
|
number,
|
||||||
object,
|
object,
|
||||||
optional,
|
optional,
|
||||||
string,
|
string,
|
||||||
@ -13,8 +14,6 @@ import {
|
|||||||
LovelaceViewConfig,
|
LovelaceViewConfig,
|
||||||
ShowViewConfig,
|
ShowViewConfig,
|
||||||
} from "../../../data/lovelace";
|
} from "../../../data/lovelace";
|
||||||
import { EntityId } from "../common/structs/is-entity-id";
|
|
||||||
import { Icon } from "../common/structs/is-icon";
|
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
|
|
||||||
export interface YamlChangedEvent extends Event {
|
export interface YamlChangedEvent extends Event {
|
||||||
@ -51,6 +50,7 @@ export interface ConfigError {
|
|||||||
export interface EntitiesEditorEvent {
|
export interface EntitiesEditorEvent {
|
||||||
detail?: {
|
detail?: {
|
||||||
entities?: EntityConfig[];
|
entities?: EntityConfig[];
|
||||||
|
item?: any;
|
||||||
};
|
};
|
||||||
target?: EventTarget;
|
target?: EventTarget;
|
||||||
}
|
}
|
||||||
@ -95,19 +95,19 @@ const buttonEntitiesRowConfigStruct = object({
|
|||||||
|
|
||||||
const castEntitiesRowConfigStruct = object({
|
const castEntitiesRowConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
view: string(),
|
view: union([string(), number()]),
|
||||||
dashboard: optional(string()),
|
dashboard: optional(string()),
|
||||||
name: optional(string()),
|
name: optional(string()),
|
||||||
icon: optional(string()),
|
icon: optional(string()),
|
||||||
hide_if_unavailable: optional(string()),
|
hide_if_unavailable: optional(boolean()),
|
||||||
});
|
});
|
||||||
|
|
||||||
const callServiceEntitiesRowConfigStruct = object({
|
const callServiceEntitiesRowConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
name: string(),
|
name: string(),
|
||||||
|
service: string(),
|
||||||
icon: optional(string()),
|
icon: optional(string()),
|
||||||
action_name: optional(string()),
|
action_name: optional(string()),
|
||||||
service: string(),
|
|
||||||
service_data: optional(any()),
|
service_data: optional(any()),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ const buttonsEntitiesRowConfigStruct = object({
|
|||||||
image: optional(string()),
|
image: optional(string()),
|
||||||
name: optional(string()),
|
name: optional(string()),
|
||||||
}),
|
}),
|
||||||
EntityId,
|
string(),
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@ -166,9 +166,9 @@ const attributeEntitiesRowConfigStruct = object({
|
|||||||
|
|
||||||
export const entitiesConfigStruct = union([
|
export const entitiesConfigStruct = union([
|
||||||
object({
|
object({
|
||||||
entity: EntityId,
|
entity: string(),
|
||||||
name: optional(string()),
|
name: optional(string()),
|
||||||
icon: optional(Icon),
|
icon: optional(string()),
|
||||||
image: optional(string()),
|
image: optional(string()),
|
||||||
secondary_info: optional(string()),
|
secondary_info: optional(string()),
|
||||||
format: optional(string()),
|
format: optional(string()),
|
||||||
@ -177,7 +177,7 @@ export const entitiesConfigStruct = union([
|
|||||||
hold_action: optional(actionConfigStruct),
|
hold_action: optional(actionConfigStruct),
|
||||||
double_tap_action: optional(actionConfigStruct),
|
double_tap_action: optional(actionConfigStruct),
|
||||||
}),
|
}),
|
||||||
EntityId,
|
string(),
|
||||||
buttonEntitiesRowConfigStruct,
|
buttonEntitiesRowConfigStruct,
|
||||||
castEntitiesRowConfigStruct,
|
castEntitiesRowConfigStruct,
|
||||||
conditionalEntitiesRowConfigStruct,
|
conditionalEntitiesRowConfigStruct,
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResultArray,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { slugify } from "../../../../common/string/slugify";
|
import { slugify } from "../../../../common/string/slugify";
|
||||||
import "../../../../components/ha-switch";
|
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||||
import "../../../../components/ha-formfield";
|
import "../../../../components/ha-formfield";
|
||||||
import "../../../../components/ha-icon-input";
|
import "../../../../components/ha-icon-input";
|
||||||
|
import "../../../../components/ha-switch";
|
||||||
import { LovelaceViewConfig } from "../../../../data/lovelace";
|
import { LovelaceViewConfig } from "../../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../components/hui-theme-select-editor";
|
||||||
import { configElementStyle } from "../config-elements/config-elements-style";
|
import { configElementStyle } from "../config-elements/config-elements-style";
|
||||||
import { EditorTarget } from "../types";
|
import { EditorTarget } from "../types";
|
||||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@ -84,7 +84,6 @@ export class HuiViewEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${configElementStyle}
|
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
@ -182,13 +181,16 @@ export class HuiViewEditor extends LitElement {
|
|||||||
fireEvent(this, "view-config-changed", { config });
|
fireEvent(this, "view-config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResultArray {
|
||||||
return css`
|
return [
|
||||||
.panel {
|
configElementStyle,
|
||||||
color: var(--secondary-text-color);
|
css`
|
||||||
display: block;
|
.panel {
|
||||||
}
|
color: var(--secondary-text-color);
|
||||||
`;
|
display: block;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
internalProperty,
|
||||||
PropertyValues,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { domainToName } from "../../data/integration";
|
import { domainToName } from "../../data/integration";
|
||||||
@ -46,8 +45,6 @@ class LovelacePanel extends LitElement {
|
|||||||
|
|
||||||
@property() public route?: Route;
|
@property() public route?: Route;
|
||||||
|
|
||||||
@internalProperty() private _columns?: number;
|
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
private _state?: "loading" | "loaded" | "error" | "yaml-editor" = "loading";
|
private _state?: "loading" | "loaded" | "error" | "yaml-editor" = "loading";
|
||||||
|
|
||||||
@ -55,8 +52,6 @@ class LovelacePanel extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private lovelace?: Lovelace;
|
@internalProperty() private lovelace?: Lovelace;
|
||||||
|
|
||||||
private mqls?: MediaQueryList[];
|
|
||||||
|
|
||||||
private _ignoreNextUpdateEvent = false;
|
private _ignoreNextUpdateEvent = false;
|
||||||
|
|
||||||
private _fetchConfigOnConnect = false;
|
private _fetchConfigOnConnect = false;
|
||||||
@ -105,7 +100,6 @@ class LovelacePanel extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.lovelace=${this.lovelace}
|
.lovelace=${this.lovelace}
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.columns=${this._columns}
|
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
@config-refresh=${this._forceFetchConfig}
|
@config-refresh=${this._forceFetchConfig}
|
||||||
></hui-root>
|
></hui-root>
|
||||||
@ -144,25 +138,6 @@ class LovelacePanel extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
|
||||||
super.updated(changedProps);
|
|
||||||
|
|
||||||
if (changedProps.has("narrow")) {
|
|
||||||
this._updateColumns();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!changedProps.has("hass")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldHass = changedProps.get("hass") as this["hass"];
|
|
||||||
|
|
||||||
if (oldHass && this.hass!.dockedSidebar !== oldHass.dockedSidebar) {
|
|
||||||
this._updateColumns();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
this._fetchConfig(false);
|
this._fetchConfig(false);
|
||||||
if (!this._unsubUpdates) {
|
if (!this._unsubUpdates) {
|
||||||
@ -174,13 +149,6 @@ class LovelacePanel extends LitElement {
|
|||||||
this._fetchConfig(false);
|
this._fetchConfig(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._updateColumns = this._updateColumns.bind(this);
|
|
||||||
this.mqls = [300, 600, 900, 1200].map((width) => {
|
|
||||||
const mql = matchMedia(`(min-width: ${width}px)`);
|
|
||||||
mql.addListener(this._updateColumns);
|
|
||||||
return mql;
|
|
||||||
});
|
|
||||||
this._updateColumns();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _regenerateConfig() {
|
private async _regenerateConfig() {
|
||||||
@ -201,19 +169,6 @@ class LovelacePanel extends LitElement {
|
|||||||
this._state = "loaded";
|
this._state = "loaded";
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateColumns() {
|
|
||||||
const matchColumns = this.mqls!.reduce(
|
|
||||||
(cols, mql) => cols + Number(mql.matches),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
// Do -1 column if the menu is docked and open
|
|
||||||
this._columns = Math.max(
|
|
||||||
1,
|
|
||||||
matchColumns -
|
|
||||||
Number(!this.narrow && this.hass!.dockedSidebar === "docked")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _lovelaceChanged() {
|
private _lovelaceChanged() {
|
||||||
if (this._ignoreNextUpdateEvent) {
|
if (this._ignoreNextUpdateEvent) {
|
||||||
this._ignoreNextUpdateEvent = false;
|
this._ignoreNextUpdateEvent = false;
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
} from "../../data/lovelace";
|
} from "../../data/lovelace";
|
||||||
import { Constructor, HomeAssistant } from "../../types";
|
import { Constructor, HomeAssistant } from "../../types";
|
||||||
|
import { LovelaceRow, LovelaceRowConfig } from "./entity-rows/types";
|
||||||
import { LovelaceHeaderFooterConfig } from "./header-footer/types";
|
import { LovelaceHeaderFooterConfig } from "./header-footer/types";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -48,6 +49,10 @@ export interface LovelaceCardConstructor extends Constructor<LovelaceCard> {
|
|||||||
getConfigElement?: () => LovelaceCardEditor;
|
getConfigElement?: () => LovelaceCardEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LovelaceRowConstructor extends Constructor<LovelaceRow> {
|
||||||
|
getConfigElement?: () => LovelaceRowEditor;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LovelaceHeaderFooter extends HTMLElement {
|
export interface LovelaceHeaderFooter extends HTMLElement {
|
||||||
hass?: HomeAssistant;
|
hass?: HomeAssistant;
|
||||||
getCardSize(): number | Promise<number>;
|
getCardSize(): number | Promise<number>;
|
||||||
@ -60,3 +65,9 @@ export interface LovelaceCardEditor extends HTMLElement {
|
|||||||
setConfig(config: LovelaceCardConfig): void;
|
setConfig(config: LovelaceCardConfig): void;
|
||||||
refreshYamlEditor?: (focus: boolean) => void;
|
refreshYamlEditor?: (focus: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LovelaceRowEditor extends HTMLElement {
|
||||||
|
hass?: HomeAssistant;
|
||||||
|
setConfig(config: LovelaceRowConfig): void;
|
||||||
|
refreshYamlEditor?: (focus: boolean) => void;
|
||||||
|
}
|
||||||
|
@ -98,11 +98,13 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(): void {
|
protected firstUpdated(): void {
|
||||||
|
this._updateColumns = this._updateColumns.bind(this);
|
||||||
this._mqls = [300, 600, 900, 1200].map((width) => {
|
this._mqls = [300, 600, 900, 1200].map((width) => {
|
||||||
const mql = matchMedia(`(min-width: ${width}px)`);
|
const mql = matchMedia(`(min-width: ${width}px)`);
|
||||||
mql.addEventListener("change", this._updateColumns);
|
mql.addEventListener("change", this._updateColumns);
|
||||||
return mql;
|
return mql;
|
||||||
});
|
});
|
||||||
|
this._updateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues): void {
|
protected updated(changedProperties: PropertyValues): void {
|
||||||
@ -130,11 +132,14 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldLovelace = changedProperties.get("lovelace") as Lovelace;
|
const oldLovelace = changedProperties.get("lovelace") as
|
||||||
|
| Lovelace
|
||||||
|
| undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
oldLovelace?.config !== this.lovelace?.config ||
|
(changedProperties.has("lovelace") && (
|
||||||
oldLovelace?.editMode !== this.lovelace?.editMode ||
|
oldLovelace?.config !== this.lovelace?.config ||
|
||||||
|
oldLovelace?.editMode !== this.lovelace?.editMode)) ||
|
||||||
changedProperties.has("_columns")
|
changedProperties.has("_columns")
|
||||||
) {
|
) {
|
||||||
this._createColumns();
|
this._createColumns();
|
||||||
@ -237,6 +242,9 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _updateColumns() {
|
private _updateColumns() {
|
||||||
|
if (!this._mqls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const matchColumns = this._mqls!.reduce(
|
const matchColumns = this._mqls!.reduce(
|
||||||
(cols, mql) => cols + Number(mql.matches),
|
(cols, mql) => cols + Number(mql.matches),
|
||||||
0
|
0
|
||||||
@ -260,6 +268,8 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
@ -288,11 +298,6 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 500px) {
|
||||||
:host {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column > * {
|
.column > * {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
@ -57,7 +57,13 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldLovelace = changedProperties.get("lovelace") as Lovelace;
|
if (!changedProperties.has("lovelace")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldLovelace = changedProperties.get("lovelace") as
|
||||||
|
| Lovelace
|
||||||
|
| undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
oldLovelace?.config !== this.lovelace?.config ||
|
oldLovelace?.config !== this.lovelace?.config ||
|
||||||
|
@ -86,6 +86,7 @@ export const derivedStyles = {
|
|||||||
"mdc-radio-disabled-color": "var(--disabled-text-color)",
|
"mdc-radio-disabled-color": "var(--disabled-text-color)",
|
||||||
"mdc-tab-text-label-color-default": "var(--primary-text-color)",
|
"mdc-tab-text-label-color-default": "var(--primary-text-color)",
|
||||||
"mdc-button-disabled-ink-color": "var(--disabled-text-color)",
|
"mdc-button-disabled-ink-color": "var(--disabled-text-color)",
|
||||||
|
"mdc-dialog-scroll-divider-color": "var(--divider-color)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const haStyle = css`
|
export const haStyle = css`
|
||||||
|
@ -1656,7 +1656,10 @@
|
|||||||
"device_tracker_pick": "Pick device to track",
|
"device_tracker_pick": "Pick device to track",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"create": "Create",
|
"create": "Create",
|
||||||
"update": "Update"
|
"update": "Update",
|
||||||
|
"confirm_delete_user": "Are you sure you want to delete the user account for {name}? You can still track the user, but the person will no longer be able to login.",
|
||||||
|
"admin": "[%key:ui::panel::config::users::editor::admin%]",
|
||||||
|
"allow_login": "Allow person to login"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zone": {
|
"zone": {
|
||||||
@ -1676,7 +1679,7 @@
|
|||||||
"new_zone": "New Zone",
|
"new_zone": "New Zone",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"icon": "Icon",
|
"icon": "Icon",
|
||||||
"icon_error_msg": "Icon should be in the format prefix:iconname, for example: mdi:home",
|
"icon_error_msg": "Icon should be in the format ''prefix:iconname'', for example: ''mdi:home''",
|
||||||
"radius": "Radius",
|
"radius": "Radius",
|
||||||
"latitude": "Latitude",
|
"latitude": "Latitude",
|
||||||
"longitude": "Longitude",
|
"longitude": "Longitude",
|
||||||
@ -2328,6 +2331,16 @@
|
|||||||
"description": "The Entities card is the most common type of card. It groups items together into lists.",
|
"description": "The Entities card is the most common type of card. It groups items together into lists.",
|
||||||
"special_row": "special row",
|
"special_row": "special row",
|
||||||
"edit_special_row": "Edit row using the code editor",
|
"edit_special_row": "Edit row using the code editor",
|
||||||
|
"entity_row_editor": "Entity Row Editor",
|
||||||
|
"secondary_info_values": {
|
||||||
|
"none": "No Secondary Info",
|
||||||
|
"entity-id": "Entity ID",
|
||||||
|
"last-changed": "Last Changed",
|
||||||
|
"last-triggered": "Last Triggered",
|
||||||
|
"position": "Position",
|
||||||
|
"tilt-position": "Tilt Position",
|
||||||
|
"brightness": "Brightness"
|
||||||
|
},
|
||||||
"entity_row": {
|
"entity_row": {
|
||||||
"divider": "Divider",
|
"divider": "Divider",
|
||||||
"call-service": "Call Service",
|
"call-service": "Call Service",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user