mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 04:16:34 +00:00
Lovelace cleanups (#3427)
* Improvements * Add types CAF * Fix demo switching * Do not set background color in hui-view
This commit is contained in:
parent
dae0ecce6a
commit
6abbe72e4d
@ -1,4 +1,4 @@
|
||||
// Run HA develop mode
|
||||
// Run demo develop mode
|
||||
const gulp = require("gulp");
|
||||
|
||||
require("./clean.js");
|
||||
|
@ -84,12 +84,12 @@ gulp.task("webpack-dev-server-demo", () => {
|
||||
open: true,
|
||||
watchContentBase: true,
|
||||
contentBase: path.resolve(paths.demo_dir, "dist"),
|
||||
}).listen(8080, "localhost", function(err) {
|
||||
}).listen(8090, "localhost", function(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
// Server listening
|
||||
log("[webpack-dev-server]", "http://localhost:8080");
|
||||
log("[webpack-dev-server]", "http://localhost:8090");
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -96,7 +96,7 @@ const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||
// Create an object mapping browser urls to their paths during build
|
||||
const translationMetadata = require("../build-translations/translationMetadata.json");
|
||||
const workBoxTranslationsTemplatedURLs = {};
|
||||
const englishFP = translationMetadata["translations"]["en"]["fingerprints"];
|
||||
const englishFP = translationMetadata.translations.en.fingerprints;
|
||||
Object.keys(englishFP).forEach((key) => {
|
||||
workBoxTranslationsTemplatedURLs[
|
||||
`/static/translations/${englishFP[key]}`
|
||||
@ -192,7 +192,7 @@ const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||
new webpack.DefinePlugin({
|
||||
__DEV__: !isProdBuild,
|
||||
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
||||
__VERSION__: JSON.stringify("DEMO"),
|
||||
__VERSION__: JSON.stringify(`DEMO-${version}`),
|
||||
__DEMO__: true,
|
||||
__STATIC_PATH__: "/static/",
|
||||
"process.env.NODE_ENV": JSON.stringify(
|
||||
|
@ -16,6 +16,7 @@ import { mockEvents } from "./stubs/events";
|
||||
import { mockMediaPlayer } from "./stubs/media_player";
|
||||
import { HomeAssistant } from "../../src/types";
|
||||
import { mockFrontend } from "./stubs/frontend";
|
||||
import { mockPersistentNotification } from "./stubs/persistent_notification";
|
||||
|
||||
class HaDemo extends HomeAssistantAppEl {
|
||||
protected async _initialize() {
|
||||
@ -43,6 +44,7 @@ class HaDemo extends HomeAssistantAppEl {
|
||||
mockEvents(hass);
|
||||
mockMediaPlayer(hass);
|
||||
mockFrontend(hass);
|
||||
mockPersistentNotification(hass);
|
||||
|
||||
// Once config is loaded AND localize, set entities and apply theme.
|
||||
Promise.all([selectedDemoConfig, localizePromise]).then(
|
||||
|
16
demo/src/stubs/persistent_notification.ts
Normal file
16
demo/src/stubs/persistent_notification.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
import { PersistentNotification } from "../../../src/data/persistent_notification";
|
||||
|
||||
export const mockPersistentNotification = (hass: MockHomeAssistant) => {
|
||||
hass.mockWS("persistent_notification/get", () =>
|
||||
Promise.resolve([
|
||||
{
|
||||
created_at: new Date().toISOString(),
|
||||
message: "There was motion detected in the backyard.",
|
||||
notification_id: "demo-1",
|
||||
title: "Motion Detected!",
|
||||
status: "unread",
|
||||
},
|
||||
] as PersistentNotification[])
|
||||
);
|
||||
};
|
@ -78,7 +78,7 @@
|
||||
"fuse.js": "^3.4.4",
|
||||
"google-timezones-json": "^1.0.2",
|
||||
"hls.js": "^0.12.4",
|
||||
"home-assistant-js-websocket": "^4.2.2",
|
||||
"home-assistant-js-websocket": "4.3.1",
|
||||
"intl-messageformat": "^2.2.0",
|
||||
"jquery": "^3.3.1",
|
||||
"js-yaml": "^3.13.0",
|
||||
@ -112,6 +112,8 @@
|
||||
"@babel/preset-typescript": "^7.3.3",
|
||||
"@gfx/zopfli": "^1.0.11",
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/chromecast-caf-receiver": "^3.0.12",
|
||||
"@types/chromecast-caf-sender": "^1.0.1",
|
||||
"@types/hls.js": "^0.12.3",
|
||||
"@types/leaflet": "^1.4.3",
|
||||
"@types/memoize-one": "4.1.0",
|
||||
|
@ -199,3 +199,9 @@ class HaEntityPicker extends LitElement {
|
||||
}
|
||||
|
||||
customElements.define("ha-entity-picker", HaEntityPicker);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-entity-picker": HaEntityPicker;
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,10 @@ import { HassEntity } from "home-assistant-js-websocket";
|
||||
// Not duplicate, this is for typing.
|
||||
// tslint:disable-next-line
|
||||
import { HaIcon } from "../ha-icon";
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
class StateBadge extends LitElement {
|
||||
public hass?: HomeAssistant;
|
||||
@property() public stateObj?: HassEntity;
|
||||
@property() public overrideIcon?: string;
|
||||
@query("ha-icon") private _icon!: HaIcon;
|
||||
@ -54,8 +56,11 @@ class StateBadge extends LitElement {
|
||||
if (stateObj) {
|
||||
// hide icon if we have entity picture
|
||||
if (stateObj.attributes.entity_picture && !this.overrideIcon) {
|
||||
hostStyle.backgroundImage =
|
||||
"url(" + stateObj.attributes.entity_picture + ")";
|
||||
let imageUrl = stateObj.attributes.entity_picture;
|
||||
if (this.hass) {
|
||||
imageUrl = this.hass.hassUrl(imageUrl);
|
||||
}
|
||||
hostStyle.backgroundImage = `url(${imageUrl})`;
|
||||
iconStyle.display = "none";
|
||||
} else {
|
||||
if (stateObj.attributes.hs_color) {
|
||||
|
@ -35,8 +35,13 @@ export const fetchThumbnailUrlWithCache = (
|
||||
entityId
|
||||
);
|
||||
|
||||
export const fetchThumbnailUrl = (hass: HomeAssistant, entityId: string) =>
|
||||
getSignedPath(hass, `/api/camera_proxy/${entityId}`).then(({ path }) => path);
|
||||
export const fetchThumbnailUrl = async (
|
||||
hass: HomeAssistant,
|
||||
entityId: string
|
||||
) => {
|
||||
const path = await getSignedPath(hass, `/api/camera_proxy/${entityId}`);
|
||||
return hass.hassUrl(path.path);
|
||||
};
|
||||
|
||||
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) => {
|
||||
// tslint:disable-next-line: no-console
|
||||
@ -47,7 +52,7 @@ export const fetchThumbnail = (hass: HomeAssistant, entityId: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchStreamUrl = (
|
||||
export const fetchStreamUrl = async (
|
||||
hass: HomeAssistant,
|
||||
entityId: string,
|
||||
format?: "hls"
|
||||
@ -60,7 +65,9 @@ export const fetchStreamUrl = (
|
||||
// @ts-ignore
|
||||
data.format = format;
|
||||
}
|
||||
return hass.callWS<Stream>(data);
|
||||
const stream = await hass.callWS<Stream>(data);
|
||||
stream.url = hass.hassUrl(stream.url);
|
||||
return stream;
|
||||
};
|
||||
|
||||
export const fetchCameraPrefs = (hass: HomeAssistant, entityId: string) =>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
import { Connection } from "home-assistant-js-websocket";
|
||||
import { Connection, getCollection } from "home-assistant-js-websocket";
|
||||
|
||||
export interface LovelaceConfig {
|
||||
title?: string;
|
||||
@ -83,6 +83,17 @@ export const subscribeLovelaceUpdates = (
|
||||
onChange: () => void
|
||||
) => conn.subscribeEvents(onChange, "lovelace_updated");
|
||||
|
||||
export const getLovelaceCollection = (conn: Connection) =>
|
||||
getCollection(
|
||||
conn,
|
||||
"_lovelace",
|
||||
(conn2) => fetchConfig(conn2, false),
|
||||
(_conn, store) =>
|
||||
subscribeLovelaceUpdates(conn, () =>
|
||||
fetchConfig(conn, false).then((config) => store.setState(config, true))
|
||||
)
|
||||
);
|
||||
|
||||
export interface WindowWithLovelaceProm extends Window {
|
||||
llConfProm?: Promise<LovelaceConfig>;
|
||||
}
|
||||
|
@ -203,6 +203,25 @@ class CoverEntity extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
class InputNumberEntity extends Entity {
|
||||
public async handleService(
|
||||
domain,
|
||||
service,
|
||||
// @ts-ignore
|
||||
data
|
||||
) {
|
||||
if (domain !== this.domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (service === "set_value") {
|
||||
this.update("" + data.value);
|
||||
} else {
|
||||
super.handleService(domain, service, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ClimateEntity extends Entity {
|
||||
public async handleService(domain, service, data) {
|
||||
if (domain !== this.domain) {
|
||||
@ -256,6 +275,7 @@ const TYPES = {
|
||||
cover: CoverEntity,
|
||||
group: GroupEntity,
|
||||
input_boolean: ToggleEntity,
|
||||
input_number: InputNumberEntity,
|
||||
light: LightEntity,
|
||||
lock: LockEntity,
|
||||
media_player: MediaPlayerEntity,
|
||||
|
@ -90,7 +90,11 @@ export const provideHass = (
|
||||
|
||||
const hassObj: MockHomeAssistant = {
|
||||
// Home Assistant properties
|
||||
auth: {} as any,
|
||||
auth: {
|
||||
data: {
|
||||
hassUrl: "",
|
||||
},
|
||||
} as any,
|
||||
connection: {
|
||||
addEventListener: () => undefined,
|
||||
removeEventListener: () => undefined,
|
||||
@ -182,6 +186,7 @@ export const provideHass = (
|
||||
? response[1](hass(), method, path, parameters)
|
||||
: Promise.reject(`API Mock for ${path} is not implemented`);
|
||||
},
|
||||
hassUrl: (path?) => path,
|
||||
fetchWithAuth: () => Promise.reject("Not implemented"),
|
||||
sendWS: (msg) => hassObj.connection.sendMessage(msg),
|
||||
callWS: (msg) => hassObj.connection.sendMessagePromise(msg),
|
||||
|
@ -1,15 +1,4 @@
|
||||
<meta charset="utf-8">
|
||||
<link rel='manifest' href='/manifest.json' crossorigin="use-credentials">
|
||||
<link rel='icon' href='/static/icons/favicon.ico'>
|
||||
<meta name='viewport' content='width=device-width, user-scalable=no'>
|
||||
<style>
|
||||
body {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
<%= renderTemplate('_style_base') %>
|
||||
|
12
src/html/_style_base.html.template
Normal file
12
src/html/_style_base.html.template
Normal file
@ -0,0 +1,12 @@
|
||||
<meta name='viewport' content='width=device-width, user-scalable=no'>
|
||||
<style>
|
||||
body {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
@ -198,8 +198,9 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
${this._config!.show_icon !== false
|
||||
? html`
|
||||
<state-badge
|
||||
.stateObj="${stateObj}"
|
||||
.overrideIcon="${entityConf.icon}"
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
.overrideIcon=${entityConf.icon}
|
||||
></state-badge>
|
||||
`
|
||||
: ""}
|
||||
|
@ -148,6 +148,27 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||
`;
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps) {
|
||||
if (!changedProps.has("hass") || changedProps.size > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
|
||||
if (!oldHass || !this._configEntities) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if any state has changed
|
||||
for (const entity of this._configEntities) {
|
||||
if (oldHass.states[entity.entity] !== this.hass!.states[entity.entity]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues): void {
|
||||
super.firstUpdated(changedProps);
|
||||
this.loadMap();
|
||||
|
@ -59,15 +59,6 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
/* start paper-font-body1 style */
|
||||
font-family: "Roboto", "Noto", sans-serif;
|
||||
-webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
/* end paper-font-body1 style */
|
||||
}
|
||||
ha-markdown {
|
||||
display: block;
|
||||
padding: 0 16px 16px;
|
||||
|
@ -64,7 +64,7 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
|
||||
),
|
||||
})}"
|
||||
>
|
||||
<img src="${this._config.image}" />
|
||||
<img src="${this.hass.hassUrl(this._config.image)}" />
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
@ -492,7 +492,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
#thermostat .rs-handle {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
padding: 7px;
|
||||
padding: 10px;
|
||||
margin: -10px 0 0 -8px !important;
|
||||
border: 2px solid var(--disabled-text-color);
|
||||
}
|
||||
#thermostat .rs-handle.rs-focus {
|
||||
|
@ -30,6 +30,7 @@ export interface EntitiesCardEntityConfig extends EntityConfig {
|
||||
}
|
||||
|
||||
export interface EntitiesCardConfig extends LovelaceCardConfig {
|
||||
type: "entities";
|
||||
show_header_toggle?: boolean;
|
||||
title?: string;
|
||||
entities: EntitiesCardEntityConfig[];
|
||||
@ -104,6 +105,7 @@ export interface LightCardConfig extends LovelaceCardConfig {
|
||||
}
|
||||
|
||||
export interface MapCardConfig extends LovelaceCardConfig {
|
||||
type: "map";
|
||||
title: string;
|
||||
aspect_ratio: string;
|
||||
default_zoom?: number;
|
||||
@ -113,6 +115,7 @@ export interface MapCardConfig extends LovelaceCardConfig {
|
||||
}
|
||||
|
||||
export interface MarkdownCardConfig extends LovelaceCardConfig {
|
||||
type: "markdown";
|
||||
content: string;
|
||||
title?: string;
|
||||
}
|
||||
|
@ -129,6 +129,10 @@ export const createRowElement = (
|
||||
return element;
|
||||
}
|
||||
|
||||
if (!config.entity) {
|
||||
return _createErrorElement("Invalid config given.", config);
|
||||
}
|
||||
|
||||
const domain = config.entity.split(".", 1)[0];
|
||||
tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || "text"}-entity-row`;
|
||||
|
||||
|
44
src/panels/lovelace/common/load-resources.ts
Normal file
44
src/panels/lovelace/common/load-resources.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { loadModule, loadCSS, loadJS } from "../../../common/dom/load_resource";
|
||||
|
||||
import { LovelaceConfig } from "../../../data/lovelace";
|
||||
|
||||
// CSS and JS should only be imported once. Modules and HTML are safe.
|
||||
const CSS_CACHE = {};
|
||||
const JS_CACHE = {};
|
||||
|
||||
export const loadLovelaceResources = (
|
||||
resources: NonNullable<LovelaceConfig["resources"]>,
|
||||
hassUrl: string
|
||||
) =>
|
||||
resources.forEach((resource) => {
|
||||
const normalizedUrl = new URL(resource.url, hassUrl).toString();
|
||||
switch (resource.type) {
|
||||
case "css":
|
||||
if (normalizedUrl in CSS_CACHE) {
|
||||
break;
|
||||
}
|
||||
CSS_CACHE[normalizedUrl] = loadCSS(normalizedUrl);
|
||||
break;
|
||||
|
||||
case "js":
|
||||
if (normalizedUrl in JS_CACHE) {
|
||||
break;
|
||||
}
|
||||
JS_CACHE[normalizedUrl] = loadJS(normalizedUrl);
|
||||
break;
|
||||
|
||||
case "module":
|
||||
loadModule(normalizedUrl);
|
||||
break;
|
||||
|
||||
case "html":
|
||||
import(/* webpackChunkName: "import-href-polyfill" */ "../../../resources/html-import/import-href").then(
|
||||
({ importHref }) => importHref(normalizedUrl)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
// tslint:disable-next-line
|
||||
console.warn(`Unknown resource type specified: ${resource.type}`);
|
||||
}
|
||||
});
|
@ -47,8 +47,9 @@ class HuiGenericEntityRow extends LitElement {
|
||||
|
||||
return html`
|
||||
<state-badge
|
||||
.stateObj="${stateObj}"
|
||||
.overrideIcon="${this.config.icon}"
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
.overrideIcon=${this.config.icon}
|
||||
></state-badge>
|
||||
<div class="flex">
|
||||
<div class="info">
|
||||
@ -63,8 +64,8 @@ class HuiGenericEntityRow extends LitElement {
|
||||
: this.config.secondary_info === "last-changed"
|
||||
? html`
|
||||
<ha-relative-time
|
||||
.hass="${this.hass}"
|
||||
.datetime="${stateObj.last_changed}"
|
||||
.hass=${this.hass}
|
||||
.datetime=${stateObj.last_changed}
|
||||
></ha-relative-time>
|
||||
`
|
||||
: ""}
|
||||
|
@ -104,6 +104,10 @@ export class HuiImage extends LitElement {
|
||||
imageSrc = this.image;
|
||||
}
|
||||
|
||||
if (imageSrc) {
|
||||
imageSrc = this.hass!.hassUrl(imageSrc);
|
||||
}
|
||||
|
||||
// Figure out filter to use
|
||||
let filter = this.filter || "";
|
||||
|
||||
|
@ -7,20 +7,21 @@ export interface EntityConfig {
|
||||
icon?: string;
|
||||
}
|
||||
export interface DividerConfig {
|
||||
type: string;
|
||||
type: "divider";
|
||||
style: string;
|
||||
}
|
||||
export interface SectionConfig {
|
||||
type: string;
|
||||
type: "section";
|
||||
label: string;
|
||||
}
|
||||
export interface WeblinkConfig {
|
||||
type: string;
|
||||
type: "weblink";
|
||||
name?: string;
|
||||
icon?: string;
|
||||
url: string;
|
||||
}
|
||||
export interface CallServiceConfig extends EntityConfig {
|
||||
type: "call-service";
|
||||
action_name?: string;
|
||||
service: string;
|
||||
service_data?: { [key: string]: any };
|
||||
|
@ -28,7 +28,6 @@ import "../../components/ha-start-voice-button";
|
||||
import "../../components/ha-paper-icon-button-arrow-next";
|
||||
import "../../components/ha-paper-icon-button-arrow-prev";
|
||||
import "../../components/ha-icon";
|
||||
import { loadModule, loadCSS, loadJS } from "../../common/dom/load_resource";
|
||||
import { debounce } from "../../common/util/debounce";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { LovelaceConfig } from "../../data/lovelace";
|
||||
@ -47,10 +46,7 @@ import { Lovelace } from "./types";
|
||||
import { afterNextRender } from "../../common/util/render-status";
|
||||
import { haStyle } from "../../resources/styles";
|
||||
import { computeRTLDirection } from "../../common/util/compute_rtl";
|
||||
|
||||
// CSS and JS should only be imported once. Modules and HTML are safe.
|
||||
const CSS_CACHE = {};
|
||||
const JS_CACHE = {};
|
||||
import { loadLovelaceResources } from "./common/load-resources";
|
||||
|
||||
class HUIRoot extends LitElement {
|
||||
@property() public hass?: HomeAssistant;
|
||||
@ -349,10 +345,14 @@ class HUIRoot extends LitElement {
|
||||
* https://www.w3.org/TR/CSS2/visudet.html#the-height-property
|
||||
*/
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
#view.tabs-hidden {
|
||||
min-height: calc(100vh - 64px);
|
||||
}
|
||||
#view > * {
|
||||
flex: 1;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -408,7 +408,12 @@ class HUIRoot extends LitElement {
|
||||
| undefined;
|
||||
|
||||
if (!oldLovelace || oldLovelace.config !== this.lovelace!.config) {
|
||||
this._loadResources(this.lovelace!.config.resources || []);
|
||||
if (this.lovelace!.config.resources) {
|
||||
loadLovelaceResources(
|
||||
this.lovelace!.config.resources,
|
||||
this.hass!.auth.data.hassUrl
|
||||
);
|
||||
}
|
||||
// On config change, recreate the current view from scratch.
|
||||
force = true;
|
||||
// Recalculate to see if we need to adjust content area for tab bar
|
||||
@ -595,40 +600,6 @@ class HUIRoot extends LitElement {
|
||||
viewConfig.background || this.config.background || "";
|
||||
root.append(view);
|
||||
}
|
||||
|
||||
private _loadResources(resources) {
|
||||
resources.forEach((resource) => {
|
||||
switch (resource.type) {
|
||||
case "css":
|
||||
if (resource.url in CSS_CACHE) {
|
||||
break;
|
||||
}
|
||||
CSS_CACHE[resource.url] = loadCSS(resource.url);
|
||||
break;
|
||||
|
||||
case "js":
|
||||
if (resource.url in JS_CACHE) {
|
||||
break;
|
||||
}
|
||||
JS_CACHE[resource.url] = loadJS(resource.url);
|
||||
break;
|
||||
|
||||
case "module":
|
||||
loadModule(resource.url);
|
||||
break;
|
||||
|
||||
case "html":
|
||||
import(/* webpackChunkName: "import-href-polyfill" */ "../../resources/html-import/import-href").then(
|
||||
({ importHref }) => importHref(resource.url)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
// tslint:disable-next-line
|
||||
console.warn(`Unknown resource type specified: ${resource.type}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -57,8 +57,8 @@ export class HUIView extends LitElement {
|
||||
return {
|
||||
hass: {},
|
||||
lovelace: {},
|
||||
columns: {},
|
||||
index: {},
|
||||
columns: { type: Number },
|
||||
index: { type: Number },
|
||||
_cards: {},
|
||||
_badges: {},
|
||||
};
|
||||
@ -116,10 +116,10 @@ export class HUIView extends LitElement {
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 4px 0;
|
||||
transform: translateZ(0);
|
||||
position: relative;
|
||||
min-height: calc(100vh - 155px);
|
||||
}
|
||||
|
||||
#badges {
|
||||
@ -194,7 +194,9 @@ export class HUIView extends LitElement {
|
||||
let editModeChanged = false;
|
||||
let configChanged = false;
|
||||
|
||||
if (changedProperties.has("lovelace")) {
|
||||
if (changedProperties.has("index")) {
|
||||
configChanged = true;
|
||||
} else if (changedProperties.has("lovelace")) {
|
||||
const oldLovelace = changedProperties.get("lovelace") as Lovelace;
|
||||
editModeChanged =
|
||||
!oldLovelace || lovelace.editMode !== oldLovelace.editMode;
|
||||
@ -310,10 +312,8 @@ export class HUIView extends LitElement {
|
||||
|
||||
this._cards = elements;
|
||||
|
||||
if ("theme" in config) {
|
||||
applyThemesOnElement(root, this.hass!.themes, config.theme);
|
||||
}
|
||||
}
|
||||
|
||||
private _rebuildCard(
|
||||
cardElToReplace: LovelaceCard,
|
||||
|
@ -46,6 +46,7 @@ export const connectionMixin = (
|
||||
translationMetadata,
|
||||
dockedSidebar: "docked",
|
||||
moreInfoEntityId: null,
|
||||
hassUrl: (path = "") => new URL(path, auth.data.hassUrl).toString(),
|
||||
callService: async (domain, service, serviceData = {}) => {
|
||||
if (__DEV__) {
|
||||
// tslint:disable-next-line: no-console
|
||||
|
18
src/types.ts
18
src/types.ts
@ -142,22 +142,20 @@ export interface HomeAssistant {
|
||||
dockedSidebar: "docked" | "always_hidden" | "auto";
|
||||
moreInfoEntityId: string | null;
|
||||
user?: CurrentUser;
|
||||
callService: (
|
||||
hassUrl(path?): string;
|
||||
callService(
|
||||
domain: string,
|
||||
service: string,
|
||||
serviceData?: { [key: string]: any }
|
||||
) => Promise<void>;
|
||||
callApi: <T>(
|
||||
): Promise<void>;
|
||||
callApi<T>(
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
parameters?: { [key: string]: any }
|
||||
) => Promise<T>;
|
||||
fetchWithAuth: (
|
||||
path: string,
|
||||
init?: { [key: string]: any }
|
||||
) => Promise<Response>;
|
||||
sendWS: (msg: MessageBase) => void;
|
||||
callWS: <T>(msg: MessageBase) => Promise<T>;
|
||||
): Promise<T>;
|
||||
fetchWithAuth(path: string, init?: { [key: string]: any }): Promise<Response>;
|
||||
sendWS(msg: MessageBase): void;
|
||||
callWS<T>(msg: MessageBase): Promise<T>;
|
||||
}
|
||||
|
||||
export type LightEntity = HassEntityBase & {
|
||||
|
18
yarn.lock
18
yarn.lock
@ -1570,6 +1570,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/chalk/-/chalk-0.4.31.tgz#a31d74241a6b1edbb973cf36d97a2896834a51f9"
|
||||
integrity sha1-ox10JBprHtu5c8822XooloNKUfk=
|
||||
|
||||
"@types/chromecast-caf-receiver@^3.0.12":
|
||||
version "3.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/chromecast-caf-receiver/-/chromecast-caf-receiver-3.0.12.tgz#0172edc5e43a0b4f426b21a614a58e04e3df009d"
|
||||
integrity sha512-GdR9nGOENDWYhF40FasB0Xnsy3c+e68K90sGVBZx1W1N3LP1NGOmCtaxgUpxk4IuHYmzGrW7I57zWZIbT3D5BQ==
|
||||
|
||||
"@types/chromecast-caf-sender@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/chromecast-caf-sender/-/chromecast-caf-sender-1.0.1.tgz#da0047c41c2a7ecf2d5348715b27c4542ed9b579"
|
||||
integrity sha512-/JuG+zrS+KCPwEiOrK9O7WrIMyiUEF7Ev9ywbzXcCOPkXin9tLX7w9zxCmxtnOPdgH9lZbtOvgo5IA4cEJknRg==
|
||||
|
||||
"@types/clean-css@*":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-4.2.1.tgz#cb0134241ec5e6ede1b5344bc829668fd9871a8d"
|
||||
@ -7303,10 +7313,10 @@ hoek@6.x.x:
|
||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
||||
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
||||
|
||||
home-assistant-js-websocket@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-4.2.2.tgz#e13b058a9e200bc56080e1b48fdeaaf1ed2e4e5f"
|
||||
integrity sha512-4mXYbn2DCiDVBYGZROUSWLBDerSoDRJulw1GiQbhKEyrDhzFs5KQkcLdIu6k3CSDYQiiKQez5uAhOfb0Hr/M0A==
|
||||
home-assistant-js-websocket@4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-4.3.1.tgz#be320672b070cb4fcae2f1709a0eba1845ef7b31"
|
||||
integrity sha512-eVIRdisSmcIzYKNSgB3gqUCrZpQkSUKlluYTsM0NqpUc4W0hHmF2vd8bShl3URWJXPOI5XPdeHuAPPqc0gUj+Q==
|
||||
|
||||
homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1:
|
||||
version "1.0.3"
|
||||
|
Loading…
x
Reference in New Issue
Block a user