Add teachingbirds demo (#2516)

* Add teachingbirds demo

* Remove some custom cards

* Lint
This commit is contained in:
Paulus Schoutsen 2019-01-20 16:15:53 -08:00 committed by GitHub
parent 3b66d58f91
commit 871ee33229
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 14675 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -3,6 +3,7 @@ import { Lovelace } from "../../../src/panels/lovelace/types";
import { DemoConfig } from "./types"; import { DemoConfig } from "./types";
export const demoConfigs: Array<() => Promise<DemoConfig>> = [ export const demoConfigs: Array<() => Promise<DemoConfig>> = [
() => import("./teachingbirds").then((mod) => mod.demoTeachingbirds),
() => import("./kernehed").then((mod) => mod.demoKernehed), () => import("./kernehed").then((mod) => mod.demoKernehed),
() => import("./jimpower").then((mod) => mod.demoJimpower), () => import("./jimpower").then((mod) => mod.demoJimpower),
]; ];

View File

@ -4,7 +4,7 @@ import { demoEntitiesJimpower } from "./entities";
export const demoJimpower: DemoConfig = { export const demoJimpower: DemoConfig = {
authorName: "Jimpower", authorName: "Jimpower",
authorUrl: " https://github.com/JamesMcCarthy79/Home-Assistant-Config", authorUrl: "https://github.com/JamesMcCarthy79/Home-Assistant-Config",
name: "Kingia Castle", name: "Kingia Castle",
lovelace: demoLovelaceJimpower, lovelace: demoLovelaceJimpower,
entities: demoEntitiesJimpower, entities: demoEntitiesJimpower,

View File

@ -4,7 +4,7 @@ import { demoEntitiesKernehed } from "./entities";
export const demoKernehed: DemoConfig = { export const demoKernehed: DemoConfig = {
authorName: "Kernehed", authorName: "Kernehed",
authorUrl: "", authorUrl: "https://github.com/kernehed",
name: "Hem", name: "Hem",
lovelace: demoLovelaceKernehed, lovelace: demoLovelaceKernehed,
entities: demoEntitiesKernehed, entities: demoEntitiesKernehed,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
import { DemoConfig } from "../types";
import { demoLovelaceTeachingbirds } from "./lovelace";
import { demoEntitiesTeachingbirds } from "./entities";
export const demoTeachingbirds: DemoConfig = {
authorName: "Isabella Gross Alström",
authorUrl: "https://github.com/isabellaalstrom/",
name: "Isa's mobile friendly LL",
lovelace: demoLovelaceTeachingbirds,
entities: demoEntitiesTeachingbirds,
};

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ import { mockLovelace } from "./stubs/lovelace";
import { mockAuth } from "./stubs/auth"; import { mockAuth } from "./stubs/auth";
import { selectedDemoConfig } from "./configs/demo-configs"; import { selectedDemoConfig } from "./configs/demo-configs";
import { mockTranslations } from "./stubs/translations"; import { mockTranslations } from "./stubs/translations";
import { mockHistory } from "./stubs/history";
import { mockShoppingList } from "./stubs/shopping_list";
class HaDemo extends HomeAssistant { class HaDemo extends HomeAssistant {
protected async _handleConnProm() { protected async _handleConnProm() {
@ -16,6 +18,8 @@ class HaDemo extends HomeAssistant {
mockLovelace(hass); mockLovelace(hass);
mockAuth(hass); mockAuth(hass);
mockTranslations(hass); mockTranslations(hass);
mockHistory(hass);
mockShoppingList(hass);
selectedDemoConfig.then((conf) => hass.addEntities(conf.entities())); selectedDemoConfig.then((conf) => hass.addEntities(conf.entities()));
// Taken from polymer/pwa-helpers. BSD-3 licensed // Taken from polymer/pwa-helpers. BSD-3 licensed

View File

@ -0,0 +1,5 @@
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockHistory = (hass: MockHomeAssistant) => {
hass.mockAPI(new RegExp("history/period/.+"), () => []);
};

View File

@ -0,0 +1,44 @@
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import { ShoppingListItem } from "../../../src/data/shopping-list";
let items: ShoppingListItem[] = [
{
id: 12,
name: "Milk",
complete: false,
},
{
id: 13,
name: "Eggs",
complete: false,
},
{
id: 14,
name: "Oranges",
complete: true,
},
];
export const mockShoppingList = (hass: MockHomeAssistant) => {
hass.mockWS("shopping_list/items", () => items);
hass.mockWS("shopping_list/items/add", (msg) => {
const item: ShoppingListItem = {
id: new Date().getTime(),
complete: false,
name: msg.name,
};
items.push(item);
hass.mockEvent("shopping_list_updated");
return item;
});
hass.mockWS("shopping_list/items/update", ({ type, item_id, ...updates }) => {
items = items.map((item) =>
item.id === item_id ? { ...item, ...updates } : item
);
hass.mockEvent("shopping_list_updated");
});
hass.mockWS("shopping_list/items/clear", () => {
items = items.filter((item) => !item.complete);
hass.mockEvent("shopping_list_updated");
});
};

View File

@ -12,20 +12,20 @@ import { translationMetadata } from "../resources/translations-metadata";
const ensureArray = <T>(val: T | T[]): T[] => const ensureArray = <T>(val: T | T[]): T[] =>
Array.isArray(val) ? val : [val]; Array.isArray(val) ? val : [val];
type RestCallback = (
method: string,
path: string,
parameters: { [key: string]: any } | undefined
) => any;
export interface MockHomeAssistant extends HomeAssistant { export interface MockHomeAssistant extends HomeAssistant {
mockEntities: any; mockEntities: any;
updateHass(obj: Partial<MockHomeAssistant>); updateHass(obj: Partial<MockHomeAssistant>);
updateStates(newStates: HassEntities); updateStates(newStates: HassEntities);
addEntities(entites: Entity | Entity[], replace?: boolean); addEntities(entites: Entity | Entity[], replace?: boolean);
mockWS(type: string, callback: (msg: any) => any); mockWS(type: string, callback: (msg: any) => any);
mockAPI( mockAPI(path: string | RegExp, callback: RestCallback);
path: string, mockEvent(event);
callback: (
method: string,
path: string,
parameters: { [key: string]: any }
) => any
);
} }
export const provideHass = ( export const provideHass = (
@ -35,7 +35,10 @@ export const provideHass = (
elements = ensureArray(elements); elements = ensureArray(elements);
const wsCommands = {}; const wsCommands = {};
const restResponses = {}; const restResponses: Array<[string | RegExp, RestCallback]> = [];
const eventListeners: {
[event: string]: Array<(event) => void>;
} = {};
const entities = {}; const entities = {};
function updateHass(obj: Partial<MockHomeAssistant>) { function updateHass(obj: Partial<MockHomeAssistant>) {
@ -67,12 +70,16 @@ export const provideHass = (
} }
} }
function mockUpdateStateAPI( function mockAPI(path, callback) {
restResponses.push([path, callback]);
}
mockAPI(new RegExp("states/.+"), (
// @ts-ignore // @ts-ignore
method, method,
path, path,
parameters parameters
) { ) => {
const [domain, objectId] = path.substr(7).split(".", 2); const [domain, objectId] = path.substr(7).split(".", 2);
if (!domain || !objectId) { if (!domain || !objectId) {
return; return;
@ -80,7 +87,7 @@ export const provideHass = (
addEntities( addEntities(
getEntity(domain, objectId, parameters.state, parameters.attributes) getEntity(domain, objectId, parameters.state, parameters.attributes)
); );
} });
updateHass({ updateHass({
// Home Assistant properties // Home Assistant properties
@ -97,10 +104,15 @@ export const provideHass = (
callback, callback,
event event
) => { ) => {
// tslint:disable-next-line if (!(event in eventListeners)) {
console.log("subscribeEvents", event); eventListeners[event] = [];
// tslint:disable-next-line }
return () => console.log("unsubscribeEvents", event); eventListeners[event].push(callback);
return () => {
eventListeners[event] = eventListeners[event].filter(
(cb) => cb !== callback
);
};
}, },
socket: { socket: {
readyState: WebSocket.OPEN, readyState: WebSocket.OPEN,
@ -146,13 +158,12 @@ export const provideHass = (
} }
}, },
async callApi(method, path, parameters) { async callApi(method, path, parameters) {
const callback = const response = restResponses.find(([resPath]) =>
path.substr(0, 7) === "states/" typeof resPath === "string" ? path === resPath : resPath.test(path)
? mockUpdateStateAPI );
: restResponses[path];
return callback return response
? callback(method, path, parameters) ? response[1](method, path, parameters)
: Promise.reject(`API Mock for ${path} is not implemented`); : Promise.reject(`API Mock for ${path} is not implemented`);
}, },
fetchWithAuth: () => Promise.reject("Not implemented"), fetchWithAuth: () => Promise.reject("Not implemented"),
@ -188,9 +199,11 @@ export const provideHass = (
mockWS(type, callback) { mockWS(type, callback) {
wsCommands[type] = callback; wsCommands[type] = callback;
}, },
mockAPI(path, callback) { mockAPI,
restResponses[path] = callback; mockEvent(event) {
(eventListeners[event] || []).forEach((fn) => fn(event));
}, },
...overrideData, ...overrideData,
} as MockHomeAssistant); } as MockHomeAssistant);

View File

@ -156,6 +156,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
protected firstUpdated(): void { protected firstUpdated(): void {
this._updated = true; this._updated = true;
this._setBaseUnit(); this._setBaseUnit();
this.classList.add("init");
} }
protected updated(changedProps: PropertyValues): void { protected updated(changedProps: PropertyValues): void {
@ -283,6 +284,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
border-radius: 0px 0px calc(var(--base-unit) * 2) border-radius: 0px 0px calc(var(--base-unit) * 2)
calc(var(--base-unit) * 2); calc(var(--base-unit) * 2);
transform-origin: center top; transform-origin: center top;
}
.init .gauge-c {
transition: all 1.3s ease-in-out; transition: all 1.3s ease-in-out;
} }
.gauge-data { .gauge-data {
@ -295,6 +298,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
top: calc(var(--base-unit) * 1.2); top: calc(var(--base-unit) * 1.2);
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
}
.init .gauge-data {
transition: all 1s ease-out; transition: all 1s ease-out;
} }
.gauge-data #percent { .gauge-data #percent {

View File

@ -201,7 +201,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
let graph; let graph;
if (this._config.graph === "line") { if (stateObj && this._config.graph === "line") {
if (!stateObj.attributes.unit_of_measurement) { if (!stateObj.attributes.unit_of_measurement) {
graph = html` graph = html`
<div class="not-found"> <div class="not-found">
@ -308,7 +308,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
endTime endTime
); );
if (stateHistory[0].length < 1) { if (stateHistory.length < 1 || stateHistory[0].length < 1) {
return; return;
} }