mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-02 14:07:55 +00:00
Card Picker with Previews of cards (#4975)
* Card Picker with Previews of cards * Getting Preview Async - Using dialogs entities * Create generic getElement - filter entities before * lint * Add entities back to Picker. Set Qualifier * Style Updates * Move setup of filtered cards to connected * style updates * Dont pull entities if noEntity config * Move all config logic to getConfig * Style Update - Remove Manual process * lint * Accounting for ll-rebuild for async cards * Style Updates - Use GetStubConfig for most * Lint * Filter entities with function - style - no preview * Iframe rename and description * Move getstubconfig to helper - update spinner * Style for themes * Move entities to be calc once * Should update * oops * TSC * Comments
This commit is contained in:
parent
f3445d99cf
commit
aa2e632df3
@ -24,6 +24,8 @@ import {
|
|||||||
import { AlarmPanelCardConfig } from "./types";
|
import { AlarmPanelCardConfig } from "./types";
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
|
||||||
const ICONS = {
|
const ICONS = {
|
||||||
armed_away: "hass:shield-lock",
|
armed_away: "hass:shield-lock",
|
||||||
@ -46,8 +48,27 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-alarm-panel-card-editor");
|
return document.createElement("hui-alarm-panel-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig() {
|
public static getStubConfig(
|
||||||
return { states: ["arm_home", "arm_away"], entity: "" };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
) {
|
||||||
|
const includeDomains = ["alarm_control_panel"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
states: ["arm_home", "arm_away"],
|
||||||
|
entity: foundEntities[0] || "",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -30,9 +30,10 @@ import { ButtonCardConfig } from "./types";
|
|||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
import { hasAction } from "../common/has-action";
|
import { hasAction } from "../common/has-action";
|
||||||
import { handleAction } from "../common/handle-action";
|
import { handleAction } from "../common/handle-action";
|
||||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
import { ActionHandlerEvent, LovelaceConfig } from "../../../data/lovelace";
|
||||||
import { computeActiveState } from "../../../common/entity/compute_active_state";
|
import { computeActiveState } from "../../../common/entity/compute_active_state";
|
||||||
import { iconColorCSS } from "../../../common/style/icon_color_css";
|
import { iconColorCSS } from "../../../common/style/icon_color_css";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-button-card")
|
@customElement("hui-button-card")
|
||||||
export class HuiButtonCard extends LitElement implements LovelaceCard {
|
export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||||
@ -43,13 +44,28 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-button-card-editor");
|
return document.createElement("hui-button-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tap_action: { action: "toggle" },
|
tap_action: { action: "toggle" },
|
||||||
hold_action: { action: "more-info" },
|
hold_action: { action: "more-info" },
|
||||||
show_icon: true,
|
show_icon: true,
|
||||||
show_name: true,
|
show_name: true,
|
||||||
state_color: true,
|
state_color: true,
|
||||||
|
entity: foundEntities[0] || "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import { createHeaderFooterElement } from "../create-element/create-header-foote
|
|||||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-entities-card")
|
@customElement("hui-entities-card")
|
||||||
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||||
@ -37,8 +39,22 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-entities-card-editor");
|
return document.createElement("hui-entities-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entities: [] };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
) {
|
||||||
|
const maxEntities = 3;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entities: foundEntities };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() private _config?: EntitiesCardConfig;
|
@property() private _config?: EntitiesCardConfig;
|
||||||
|
@ -22,6 +22,9 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
import { GaugeCardConfig } from "./types";
|
import { GaugeCardConfig } from "./types";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket/dist/types";
|
||||||
|
|
||||||
export const severityMap = {
|
export const severityMap = {
|
||||||
red: "var(--label-badge-red)",
|
red: "var(--label-badge-red)",
|
||||||
@ -38,8 +41,30 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
return document.createElement("hui-gauge-card-editor");
|
return document.createElement("hui-gauge-card-editor");
|
||||||
}
|
}
|
||||||
public static getStubConfig(): object {
|
|
||||||
return { entity: "" };
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["sensor"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const entityFilter = (stateObj: HassEntity): boolean => {
|
||||||
|
return !isNaN(Number(stateObj.state));
|
||||||
|
};
|
||||||
|
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains,
|
||||||
|
entityFilter
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -27,10 +27,11 @@ import { processConfigEntities } from "../common/process-config-entities";
|
|||||||
import { GlanceCardConfig, GlanceConfigEntity } from "./types";
|
import { GlanceCardConfig, GlanceConfigEntity } from "./types";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
import { hasAction } from "../common/has-action";
|
import { hasAction } from "../common/has-action";
|
||||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
import { ActionHandlerEvent, LovelaceConfig } from "../../../data/lovelace";
|
||||||
import { handleAction } from "../common/handle-action";
|
import { handleAction } from "../common/handle-action";
|
||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
import { UNAVAILABLE, UNKNOWN } from "../../../data/entity";
|
import { UNAVAILABLE, UNKNOWN } from "../../../data/entity";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-glance-card")
|
@customElement("hui-glance-card")
|
||||||
export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||||
@ -41,8 +42,24 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-glance-card-editor");
|
return document.createElement("hui-glance-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entities: [] };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["sensor"];
|
||||||
|
const maxEntities = 3;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entities: foundEntities };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -20,6 +20,8 @@ import { HomeAssistant } from "../../../types";
|
|||||||
import { HistoryGraphCardConfig } from "./types";
|
import { HistoryGraphCardConfig } from "./types";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-history-graph-card")
|
@customElement("hui-history-graph-card")
|
||||||
export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
||||||
@ -30,8 +32,24 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-history-graph-card-editor");
|
return document.createElement("hui-history-graph-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig() {
|
public static getStubConfig(
|
||||||
return { entities: [] };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["sensor"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entities: foundEntities };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -29,6 +29,8 @@ import { toggleEntity } from "../common/entity/toggle-entity";
|
|||||||
import { LightCardConfig } from "./types";
|
import { LightCardConfig } from "./types";
|
||||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||||
import { SUPPORT_BRIGHTNESS } from "../../../data/light";
|
import { SUPPORT_BRIGHTNESS } from "../../../data/light";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
|
||||||
@customElement("hui-light-card")
|
@customElement("hui-light-card")
|
||||||
@ -39,8 +41,25 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
return document.createElement("hui-light-card-editor");
|
return document.createElement("hui-light-card-editor");
|
||||||
}
|
}
|
||||||
public static getStubConfig(): object {
|
|
||||||
return { entity: "" };
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["light"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -30,6 +30,8 @@ import { EntityConfig } from "../entity-rows/types";
|
|||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { MapCardConfig } from "./types";
|
import { MapCardConfig } from "./types";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-map-card")
|
@customElement("hui-map-card")
|
||||||
class HuiMapCard extends LitElement implements LovelaceCard {
|
class HuiMapCard extends LitElement implements LovelaceCard {
|
||||||
@ -40,8 +42,24 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-map-card-editor");
|
return document.createElement("hui-map-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig() {
|
public static getStubConfig(
|
||||||
return { entities: [] };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["device_tracker"];
|
||||||
|
const maxEntities = 2;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entities: foundEntities };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -34,6 +34,8 @@ import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { MediaControlCardConfig } from "./types";
|
import { MediaControlCardConfig } from "./types";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-media-control-card")
|
@customElement("hui-media-control-card")
|
||||||
export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
||||||
@ -44,8 +46,24 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-media-control-card-editor");
|
return document.createElement("hui-media-control-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entity: "" };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["media_player"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -15,9 +15,39 @@ import { HomeAssistant } from "../../../types";
|
|||||||
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
||||||
import { PictureElementsCardConfig } from "./types";
|
import { PictureElementsCardConfig } from "./types";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-picture-elements-card")
|
@customElement("hui-picture-elements-card")
|
||||||
class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
||||||
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
type: "state-badge",
|
||||||
|
entity: foundEntities[0] || "",
|
||||||
|
style: "position: absolute, transform: translate(-50%, -50%)",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
image:
|
||||||
|
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@property() private _config?: PictureElementsCardConfig;
|
@property() private _config?: PictureElementsCardConfig;
|
||||||
|
|
||||||
private _hass?: HomeAssistant;
|
private _hass?: HomeAssistant;
|
||||||
|
@ -27,8 +27,9 @@ import { PictureEntityCardConfig } from "./types";
|
|||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
import { hasAction } from "../common/has-action";
|
import { hasAction } from "../common/has-action";
|
||||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
import { ActionHandlerEvent, LovelaceConfig } from "../../../data/lovelace";
|
||||||
import { handleAction } from "../common/handle-action";
|
import { handleAction } from "../common/handle-action";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
@customElement("hui-picture-entity-card")
|
@customElement("hui-picture-entity-card")
|
||||||
class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
||||||
@ -38,9 +39,24 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
return document.createElement("hui-picture-entity-card-editor");
|
return document.createElement("hui-picture-entity-card-editor");
|
||||||
}
|
}
|
||||||
public static getStubConfig(): object {
|
|
||||||
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entity: "",
|
entity: foundEntities[0] || "",
|
||||||
image:
|
image:
|
||||||
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
|
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
|
||||||
};
|
};
|
||||||
|
@ -29,8 +29,9 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
|
|||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
import { hasAction } from "../common/has-action";
|
import { hasAction } from "../common/has-action";
|
||||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
import { ActionHandlerEvent, LovelaceConfig } from "../../../data/lovelace";
|
||||||
import { handleAction } from "../common/handle-action";
|
import { handleAction } from "../common/handle-action";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
|
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
|
||||||
|
|
||||||
@ -42,11 +43,26 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
return document.createElement("hui-picture-glance-card-editor");
|
return document.createElement("hui-picture-glance-card-editor");
|
||||||
}
|
}
|
||||||
public static getStubConfig(): object {
|
|
||||||
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const maxEntities = 2;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
image:
|
image:
|
||||||
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
|
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
|
||||||
entities: [],
|
entities: foundEntities,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
|
|||||||
import { PlantStatusCardConfig, PlantAttributeTarget } from "./types";
|
import { PlantStatusCardConfig, PlantAttributeTarget } from "./types";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
const SENSORS = {
|
const SENSORS = {
|
||||||
moisture: "hass:water",
|
moisture: "hass:water",
|
||||||
@ -40,8 +42,24 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-plant-status-card-editor");
|
return document.createElement("hui-plant-status-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entity: "" };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["plant"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -26,6 +26,9 @@ import { fetchRecent } from "../../../data/history";
|
|||||||
import { SensorCardConfig } from "./types";
|
import { SensorCardConfig } from "./types";
|
||||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket/dist/types";
|
||||||
|
|
||||||
const strokeWidth = 5;
|
const strokeWidth = 5;
|
||||||
|
|
||||||
@ -174,8 +177,32 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-sensor-card-editor");
|
return document.createElement("hui-sensor-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entity: "" };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["sensor"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const entityFilter = (stateObj: HassEntity): boolean => {
|
||||||
|
return (
|
||||||
|
!isNaN(Number(stateObj.state)) &&
|
||||||
|
!!stateObj.attributes.unit_of_measurement
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains,
|
||||||
|
entityFilter
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "", graph: "line" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -34,6 +34,8 @@ import {
|
|||||||
} from "../../../data/climate";
|
} from "../../../data/climate";
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
|
||||||
const modeIcons: { [mode in HvacMode]: string } = {
|
const modeIcons: { [mode in HvacMode]: string } = {
|
||||||
@ -55,8 +57,24 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-thermostat-card-editor");
|
return document.createElement("hui-thermostat-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): object {
|
public static getStubConfig(
|
||||||
return { entity: "" };
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["climate"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -24,6 +24,8 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { findEntities } from "../common/find-entites";
|
||||||
|
|
||||||
const cardinalDirections = [
|
const cardinalDirections = [
|
||||||
"N",
|
"N",
|
||||||
@ -71,8 +73,25 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
|
|||||||
);
|
);
|
||||||
return document.createElement("hui-weather-forecast-card-editor");
|
return document.createElement("hui-weather-forecast-card-editor");
|
||||||
}
|
}
|
||||||
public static getStubConfig(): object {
|
|
||||||
return { entity: "" };
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): object {
|
||||||
|
const includeDomains = ["weather"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFill,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return { entity: foundEntities[0] || "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { LovelaceConfig, ActionConfig } from "../../../data/lovelace";
|
import { LovelaceConfig, ActionConfig } from "../../../data/lovelace";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
const EXCLUDED_DOMAINS = ["zone", "persistent_notification"];
|
export const EXCLUDED_DOMAINS = ["zone", "persistent_notification"];
|
||||||
|
|
||||||
const addFromAction = (entities: Set<string>, actionConfig: ActionConfig) => {
|
const addFromAction = (entities: Set<string>, actionConfig: ActionConfig) => {
|
||||||
if (
|
if (
|
||||||
@ -61,7 +61,7 @@ const addEntities = (entities: Set<string>, obj) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeUsedEntities = (config) => {
|
export const computeUsedEntities = (config) => {
|
||||||
const entities = new Set<string>();
|
const entities = new Set<string>();
|
||||||
config.views.forEach((view) => addEntities(entities, view));
|
config.views.forEach((view) => addEntities(entities, view));
|
||||||
return entities;
|
return entities;
|
||||||
|
59
src/panels/lovelace/common/find-entites.ts
Normal file
59
src/panels/lovelace/common/find-entites.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
computeUnusedEntities,
|
||||||
|
computeUsedEntities,
|
||||||
|
} from "./compute-unused-entities";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
|
export const findEntities = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
maxEntities: number,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[],
|
||||||
|
includeDomains?: string[],
|
||||||
|
entityFilter?: (stateObj: HassEntity) => boolean
|
||||||
|
) => {
|
||||||
|
let entityIds: string[];
|
||||||
|
|
||||||
|
entityIds = !entities?.length
|
||||||
|
? computeUnusedEntities(hass, lovelaceConfig)
|
||||||
|
: entities;
|
||||||
|
|
||||||
|
if (includeDomains && includeDomains.length) {
|
||||||
|
entityIds = entityIds.filter((eid) =>
|
||||||
|
includeDomains!.includes(computeDomain(eid))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityFilter) {
|
||||||
|
entityIds = entityIds.filter(
|
||||||
|
(eid) => hass.states[eid] && entityFilter(hass.states[eid])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityIds.length < (maxEntities || 1)) {
|
||||||
|
let fillEntityIds =
|
||||||
|
entitiesFill && entitiesFill.length
|
||||||
|
? entitiesFill
|
||||||
|
: [...computeUsedEntities(lovelaceConfig)];
|
||||||
|
|
||||||
|
if (includeDomains && includeDomains.length) {
|
||||||
|
fillEntityIds = fillEntityIds.filter((eid) =>
|
||||||
|
includeDomains!.includes(computeDomain(eid))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityFilter) {
|
||||||
|
fillEntityIds = fillEntityIds.filter(
|
||||||
|
(eid) => hass.states[eid] && entityFilter(hass.states[eid])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityIds = [...entityIds, ...fillEntityIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
return entityIds.slice(0, maxEntities);
|
||||||
|
};
|
@ -5,26 +5,31 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
|
property,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@material/mwc-button";
|
import { until } from "lit-html/directives/until";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../../types";
|
|
||||||
import { LovelaceCardConfig } from "../../../../data/lovelace";
|
|
||||||
import { CardPickTarget } from "../types";
|
import { CardPickTarget } from "../types";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import { LovelaceCard } from "../../types";
|
||||||
|
import { LovelaceCardConfig, LovelaceConfig } from "../../../../data/lovelace";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { getCardElementClass } from "../../create-element/create-card-element";
|
import { createCardElement } from "../../create-element/create-card-element";
|
||||||
|
import { getCardStubConfig } from "../get-card-stub-config";
|
||||||
|
import {
|
||||||
|
computeUnusedEntities,
|
||||||
|
computeUsedEntities,
|
||||||
|
} from "../../common/compute-unused-entities";
|
||||||
|
|
||||||
const cards: string[] = [
|
const previewCards: string[] = [
|
||||||
"alarm-panel",
|
"alarm-panel",
|
||||||
"conditional",
|
|
||||||
"entities",
|
"entities",
|
||||||
"button",
|
"button",
|
||||||
"entity-filter",
|
|
||||||
"gauge",
|
"gauge",
|
||||||
"glance",
|
"glance",
|
||||||
"history-graph",
|
"history-graph",
|
||||||
"horizontal-stack",
|
|
||||||
"iframe",
|
|
||||||
"light",
|
"light",
|
||||||
"map",
|
"map",
|
||||||
"markdown",
|
"markdown",
|
||||||
@ -35,78 +40,247 @@ const cards: string[] = [
|
|||||||
"picture-glance",
|
"picture-glance",
|
||||||
"plant-status",
|
"plant-status",
|
||||||
"sensor",
|
"sensor",
|
||||||
"shopping-list",
|
|
||||||
"thermostat",
|
"thermostat",
|
||||||
"vertical-stack",
|
|
||||||
"weather-forecast",
|
"weather-forecast",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const nonPreviewCards: string[] = [
|
||||||
|
"conditional",
|
||||||
|
"entity-filter",
|
||||||
|
"horizontal-stack",
|
||||||
|
"iframe",
|
||||||
|
"vertical-stack",
|
||||||
|
"shopping-list",
|
||||||
|
];
|
||||||
|
|
||||||
@customElement("hui-card-picker")
|
@customElement("hui-card-picker")
|
||||||
export class HuiCardPicker extends LitElement {
|
export class HuiCardPicker extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
public lovelace?: LovelaceConfig;
|
||||||
public cardPicked?: (cardConf: LovelaceCardConfig) => void;
|
public cardPicked?: (cardConf: LovelaceCardConfig) => void;
|
||||||
|
private _unusedEntities?: string[];
|
||||||
|
private _usedEntities?: string[];
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
if (
|
||||||
|
!this.hass ||
|
||||||
|
!this.lovelace ||
|
||||||
|
!this._unusedEntities ||
|
||||||
|
!this._usedEntities
|
||||||
|
) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="cards-container">
|
<div class="cards-container">
|
||||||
${cards.map((card: string) => {
|
${previewCards.map((type: string) => {
|
||||||
return html`
|
return html`
|
||||||
<mwc-button @click="${this._cardPicked}" .type="${card}">
|
${until(
|
||||||
${this.hass!.localize(
|
this._renderCardElement(type),
|
||||||
`ui.panel.lovelace.editor.card.${card}.name`
|
html`
|
||||||
)}
|
<div class="card spinner">
|
||||||
</mwc-button>
|
<paper-spinner active alt="Loading"></paper-spinner>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
${nonPreviewCards.map((type: string) => {
|
||||||
|
return html`
|
||||||
|
${until(
|
||||||
|
this._renderCardElement(type, true),
|
||||||
|
html`
|
||||||
|
<div class="card spinner">
|
||||||
|
<paper-spinner active alt="Loading"></paper-spinner>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div class="cards-container">
|
<div class="cards-container">
|
||||||
<mwc-button @click="${this._manualPicked}">MANUAL CARD</mwc-button>
|
<div
|
||||||
|
class="card"
|
||||||
|
@click="${this._cardPicked}"
|
||||||
|
.config="${{ type: "" }}"
|
||||||
|
>
|
||||||
|
<div class="preview description">
|
||||||
|
${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.generic.manual_description`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.generic.manual`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||||
|
if (!oldHass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldHass.language !== this.hass!.language) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(): void {
|
||||||
|
if (!this.hass || !this.lovelace) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._unusedEntities = computeUnusedEntities(this.hass, this.lovelace);
|
||||||
|
this._usedEntities = [...computeUsedEntities(this.lovelace)];
|
||||||
|
this.requestUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
css`
|
css`
|
||||||
.cards-container {
|
.cards-container {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-gap: 8px 8px;
|
||||||
margin-bottom: 10px;
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
}
|
margin-top: 20px;
|
||||||
.cards-container mwc-button {
|
|
||||||
flex: 1 0 25%;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
.card {
|
||||||
.cards-container mwc-button {
|
height: 100%;
|
||||||
flex: 1 0 33%;
|
display: flex;
|
||||||
}
|
flex-direction: column;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--divider-color);
|
||||||
|
background: var(--primary-background-color, #fafafa);
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
color: var(--ha-card-header-color, --primary-text-color);
|
||||||
|
font-family: var(--ha-card-header-font-family, inherit);
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: -0.012em;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
background: var(
|
||||||
|
--ha-card-background,
|
||||||
|
var(--paper-card-background-color, white)
|
||||||
|
);
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
border-top: 1px solid var(--divider-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
pointer-events: none;
|
||||||
|
margin: 20px;
|
||||||
|
flex: 1 1 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview > :first-child {
|
||||||
|
zoom: 0.6;
|
||||||
|
-moz-transform: scale(0.6); /* Firefox */
|
||||||
|
-moz-transform-origin: 0 0;
|
||||||
|
-o-transform: scale(0.6); /* Opera */
|
||||||
|
-o-transform-origin: 0 0;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _manualPicked(): void {
|
private _cardPicked(ev: Event): void {
|
||||||
fireEvent(this, "config-changed", {
|
const config: LovelaceCardConfig = (ev.currentTarget! as CardPickTarget)
|
||||||
config: { type: "" },
|
.config;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _cardPicked(ev: Event): Promise<void> {
|
|
||||||
const type = (ev.currentTarget! as CardPickTarget).type;
|
|
||||||
|
|
||||||
const elClass = await getCardElementClass(type);
|
|
||||||
let config: LovelaceCardConfig = { type };
|
|
||||||
|
|
||||||
if (elClass && elClass.getStubConfig) {
|
|
||||||
const cardConfig = elClass.getStubConfig(this.hass!);
|
|
||||||
config = { ...config, ...cardConfig };
|
|
||||||
}
|
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||||
|
const element = createCardElement(cardConfig) as LovelaceCard;
|
||||||
|
element.hass = this.hass;
|
||||||
|
element.addEventListener(
|
||||||
|
"ll-rebuild",
|
||||||
|
(ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
element.parentElement!.replaceChild(
|
||||||
|
this._createCardElement(cardConfig),
|
||||||
|
element
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _renderCardElement(
|
||||||
|
type: string,
|
||||||
|
noElement: boolean = false
|
||||||
|
): Promise<TemplateResult> {
|
||||||
|
let element: LovelaceCard | undefined;
|
||||||
|
let cardConfig: LovelaceCardConfig = { type };
|
||||||
|
|
||||||
|
if (this.hass && this.lovelace) {
|
||||||
|
cardConfig = await getCardStubConfig(
|
||||||
|
this.hass,
|
||||||
|
this.lovelace,
|
||||||
|
type,
|
||||||
|
this._unusedEntities,
|
||||||
|
this._usedEntities
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!noElement) {
|
||||||
|
element = this._createCardElement(cardConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="card" @click="${this._cardPicked}" .config="${cardConfig}">
|
||||||
|
<div
|
||||||
|
class="preview ${classMap({
|
||||||
|
description: !element || element.tagName === "HUI-ERROR-CARD",
|
||||||
|
})}"
|
||||||
|
>
|
||||||
|
${!element || element.tagName === "HUI-ERROR-CARD"
|
||||||
|
? html`
|
||||||
|
${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.${cardConfig.type}.description`
|
||||||
|
)}
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
${element}
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
${this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.${cardConfig.type}.name`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -99,6 +99,7 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
${this._cardConfig === undefined
|
${this._cardConfig === undefined
|
||||||
? html`
|
? html`
|
||||||
<hui-card-picker
|
<hui-card-picker
|
||||||
|
.lovelace="${this._params.lovelaceConfig}"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
@config-changed="${this._handleCardPicked}"
|
@config-changed="${this._handleCardPicked}"
|
||||||
></hui-card-picker>
|
></hui-card-picker>
|
||||||
@ -254,7 +255,7 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
|
|
||||||
private _handleCardPicked(ev) {
|
private _handleCardPicked(ev) {
|
||||||
const config = ev.detail.config;
|
const config = ev.detail.config;
|
||||||
if (this._params!.entities && this._params!.entities.length > 0) {
|
if (this._params!.entities && this._params!.entities.length) {
|
||||||
if (Object.keys(config).includes("entities")) {
|
if (Object.keys(config).includes("entities")) {
|
||||||
config.entities = this._params!.entities;
|
config.entities = this._params!.entities;
|
||||||
} else if (Object.keys(config).includes("entity")) {
|
} else if (Object.keys(config).includes("entity")) {
|
||||||
|
28
src/panels/lovelace/editor/get-card-stub-config.ts
Normal file
28
src/panels/lovelace/editor/get-card-stub-config.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { LovelaceCardConfig, LovelaceConfig } from "../../../data/lovelace";
|
||||||
|
import { getCardElementClass } from "../create-element/create-card-element";
|
||||||
|
|
||||||
|
export const getCardStubConfig = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
type: string,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
): Promise<LovelaceCardConfig> => {
|
||||||
|
let cardConfig: LovelaceCardConfig = { type };
|
||||||
|
|
||||||
|
const elClass = await getCardElementClass(type);
|
||||||
|
|
||||||
|
if (elClass && elClass.getStubConfig) {
|
||||||
|
const classStubConfig = elClass.getStubConfig(
|
||||||
|
hass,
|
||||||
|
lovelaceConfig,
|
||||||
|
entities,
|
||||||
|
entitiesFill
|
||||||
|
);
|
||||||
|
|
||||||
|
cardConfig = { ...cardConfig, ...classStubConfig };
|
||||||
|
}
|
||||||
|
|
||||||
|
return cardConfig;
|
||||||
|
};
|
@ -46,7 +46,7 @@ export interface EditorTarget extends EventTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CardPickTarget extends EventTarget {
|
export interface CardPickTarget extends EventTarget {
|
||||||
type: string;
|
config: LovelaceCardConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actionConfigStruct = struct({
|
export const actionConfigStruct = struct({
|
||||||
|
@ -38,7 +38,12 @@ export interface LovelaceCard extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LovelaceCardConstructor extends Constructor<LovelaceCard> {
|
export interface LovelaceCardConstructor extends Constructor<LovelaceCard> {
|
||||||
getStubConfig?: (hass: HomeAssistant) => LovelaceCardConfig;
|
getStubConfig?: (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
lovelaceConfig: LovelaceConfig,
|
||||||
|
entities?: string[],
|
||||||
|
entitiesFill?: string[]
|
||||||
|
) => LovelaceCardConfig;
|
||||||
getConfigElement?: () => LovelaceCardEditor;
|
getConfigElement?: () => LovelaceCardEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1956,7 +1956,8 @@
|
|||||||
"available_states": "Available States"
|
"available_states": "Available States"
|
||||||
},
|
},
|
||||||
"conditional": {
|
"conditional": {
|
||||||
"name": "Conditional"
|
"name": "Conditional",
|
||||||
|
"description": "Displays another card based on entity states."
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
@ -1971,7 +1972,8 @@
|
|||||||
"name": "Button"
|
"name": "Button"
|
||||||
},
|
},
|
||||||
"entity-filter": {
|
"entity-filter": {
|
||||||
"name": "Entity Filter"
|
"name": "Entity Filter",
|
||||||
|
"description": "This card allows you to define a list of entities that you want to track only when in a certain state."
|
||||||
},
|
},
|
||||||
"gauge": {
|
"gauge": {
|
||||||
"name": "Gauge",
|
"name": "Gauge",
|
||||||
@ -1990,10 +1992,12 @@
|
|||||||
"name": "History Graph"
|
"name": "History Graph"
|
||||||
},
|
},
|
||||||
"horizontal-stack": {
|
"horizontal-stack": {
|
||||||
"name": "Horizontal Stack"
|
"name": "Horizontal Stack",
|
||||||
|
"description": "Horizontal stack card allows you to stack together multiple cards, so they always sit next to each other in the space of one column."
|
||||||
},
|
},
|
||||||
"iframe": {
|
"iframe": {
|
||||||
"name": "iFrame"
|
"name": "Webpage",
|
||||||
|
"description": "Embed your favorite webpage right into Home Assistant"
|
||||||
},
|
},
|
||||||
"light": {
|
"light": {
|
||||||
"name": "Light"
|
"name": "Light"
|
||||||
@ -2010,6 +2014,8 @@
|
|||||||
"icon_height": "Icon Height",
|
"icon_height": "Icon Height",
|
||||||
"image": "Image Path",
|
"image": "Image Path",
|
||||||
"maximum": "Maximum",
|
"maximum": "Maximum",
|
||||||
|
"manual": "Manual",
|
||||||
|
"manual_description": "Need to add a custom card or just want to manually write the yaml?",
|
||||||
"minimum": "Minimum",
|
"minimum": "Minimum",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"refresh_interval": "Refresh Interval",
|
"refresh_interval": "Refresh Interval",
|
||||||
@ -2049,7 +2055,8 @@
|
|||||||
"name": "Picture Glance"
|
"name": "Picture Glance"
|
||||||
},
|
},
|
||||||
"plant-status": {
|
"plant-status": {
|
||||||
"name": "Plant Status"
|
"name": "Plant Status",
|
||||||
|
"description": "A card for all the lovely botanists out there."
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
"name": "Sensor",
|
"name": "Sensor",
|
||||||
@ -2058,13 +2065,15 @@
|
|||||||
},
|
},
|
||||||
"shopping-list": {
|
"shopping-list": {
|
||||||
"name": "Shopping List",
|
"name": "Shopping List",
|
||||||
|
"description": "The Shopping List Card allows you to add, edit, check-off, and clear items from your shopping list.",
|
||||||
"integration_not_loaded": "This card requires the `shopping_list` integration to be set up."
|
"integration_not_loaded": "This card requires the `shopping_list` integration to be set up."
|
||||||
},
|
},
|
||||||
"thermostat": {
|
"thermostat": {
|
||||||
"name": "Thermostat"
|
"name": "Thermostat"
|
||||||
},
|
},
|
||||||
"vertical-stack": {
|
"vertical-stack": {
|
||||||
"name": "Vertical Stack"
|
"name": "Vertical Stack",
|
||||||
|
"description": "Vertical stack allows you to group multiple cards so they always sit in the same column."
|
||||||
},
|
},
|
||||||
"weather-forecast": {
|
"weather-forecast": {
|
||||||
"name": "Weather Forecast"
|
"name": "Weather Forecast"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user