mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 02:36:37 +00:00
Card Picker: Entity Picker (#6693)
This commit is contained in:
parent
1431e75f8b
commit
f3639c2663
@ -1,4 +1,7 @@
|
||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
||||
import "@material/mwc-tab/mwc-tab";
|
||||
import Fuse from "fuse.js";
|
||||
import memoizeOne from "memoize-one";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@ -11,30 +14,35 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import memoizeOne from "memoize-one";
|
||||
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../common/search/search-input";
|
||||
import { UNAVAILABLE_STATES } from "../../../../data/entity";
|
||||
import { LovelaceCardConfig, LovelaceConfig } from "../../../../data/lovelace";
|
||||
import {
|
||||
CustomCardEntry,
|
||||
customCards,
|
||||
CUSTOM_TYPE_PREFIX,
|
||||
getCustomCardEntry,
|
||||
} from "../../../../data/lovelace_custom_cards";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import {
|
||||
calcUnusedEntities,
|
||||
computeUsedEntities,
|
||||
calcUnusedEntities,
|
||||
} from "../../common/compute-unused-entities";
|
||||
import { tryCreateCardElement } from "../../create-element/create-card-element";
|
||||
import { LovelaceCard } from "../../types";
|
||||
import { getCardStubConfig } from "../get-card-stub-config";
|
||||
import { CardPickTarget, Card } from "../types";
|
||||
import { coreCards } from "../lovelace-cards";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
|
||||
import type { CardPickTarget, Card } from "../types";
|
||||
import type { LovelaceCard } from "../../types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type {
|
||||
LovelaceCardConfig,
|
||||
LovelaceConfig,
|
||||
} from "../../../../data/lovelace";
|
||||
|
||||
import "../../../../components/ha-circular-progress";
|
||||
import "../../../../common/search/search-input";
|
||||
|
||||
interface CardElement {
|
||||
card: Card;
|
||||
@ -53,14 +61,14 @@ export class HuiCardPicker extends LitElement {
|
||||
|
||||
@internalProperty() private _filter = "";
|
||||
|
||||
private _unusedEntities?: string[];
|
||||
|
||||
private _usedEntities?: string[];
|
||||
|
||||
@internalProperty() private _width?: number;
|
||||
|
||||
@internalProperty() private _height?: number;
|
||||
|
||||
private _unusedEntities?: string[];
|
||||
|
||||
private _usedEntities?: string[];
|
||||
|
||||
private _filterCards = memoizeOne(
|
||||
(cardElements: CardElement[], filter?: string): CardElement[] => {
|
||||
if (!filter) {
|
||||
@ -232,85 +240,6 @@ export class HuiCardPicker extends LitElement {
|
||||
this._filter = value;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
.cards-container {
|
||||
display: grid;
|
||||
grid-gap: 8px 8px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
height: 100%;
|
||||
max-width: 500px;
|
||||
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;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
color: var(--ha-card-header-color, --primary-text-color);
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
letter-spacing: -0.012em;
|
||||
line-height: 20px;
|
||||
padding: 12px 16px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
background: var(
|
||||
--ha-card-background,
|
||||
var(--card-background-color, white)
|
||||
);
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
.preview {
|
||||
pointer-events: none;
|
||||
margin: 20px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preview > :first-child {
|
||||
zoom: 0.6;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.manual {
|
||||
max-width: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
private _cardPicked(ev: Event): void {
|
||||
const config: LovelaceCardConfig = (ev.currentTarget! as CardPickTarget)
|
||||
.config;
|
||||
@ -406,6 +335,85 @@ export class HuiCardPicker extends LitElement {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
.cards-container {
|
||||
display: grid;
|
||||
grid-gap: 8px 8px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
height: 100%;
|
||||
max-width: 500px;
|
||||
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;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
color: var(--ha-card-header-color, --primary-text-color);
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
letter-spacing: -0.012em;
|
||||
line-height: 20px;
|
||||
padding: 12px 16px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
background: var(
|
||||
--ha-card-background,
|
||||
var(--card-background-color, white)
|
||||
);
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
.preview {
|
||||
pointer-events: none;
|
||||
margin: 20px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preview > :first-child {
|
||||
zoom: 0.6;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.manual {
|
||||
max-width: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
278
src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts
Normal file
278
src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts
Normal file
@ -0,0 +1,278 @@
|
||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
||||
import "@material/mwc-tab/mwc-tab";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import memoize from "memoize-one";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../../common/entity/compute_state_name";
|
||||
import { DataTableRowData } from "../../../../components/data-table/ha-data-table";
|
||||
import "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-header-bar";
|
||||
import type { LovelaceViewConfig } from "../../../../data/lovelace";
|
||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||
import { haStyleDialog } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import "./hui-card-picker";
|
||||
import "./hui-entity-picker-table";
|
||||
import {
|
||||
EditCardDialogParams,
|
||||
showEditCardDialog,
|
||||
} from "./show-edit-card-dialog";
|
||||
import { showSuggestCardDialog } from "./show-suggest-card-dialog";
|
||||
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
"selected-changed": SelectedChangedEvent;
|
||||
}
|
||||
}
|
||||
|
||||
interface SelectedChangedEvent {
|
||||
selectedEntities: string[];
|
||||
}
|
||||
|
||||
@customElement("hui-dialog-create-card")
|
||||
export class HuiCreateDialogCard extends LitElement implements HassDialog {
|
||||
@property({ attribute: false }) protected hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _params?: EditCardDialogParams;
|
||||
|
||||
@internalProperty() private _viewConfig!: LovelaceViewConfig;
|
||||
|
||||
@internalProperty() private _selectedEntities: string[] = [];
|
||||
|
||||
@internalProperty() private _currTabIndex = 0;
|
||||
|
||||
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
||||
this._params = params;
|
||||
const [view] = params.path;
|
||||
this._viewConfig = params.lovelaceConfig.views[view];
|
||||
}
|
||||
|
||||
public closeDialog(): boolean {
|
||||
this._params = undefined;
|
||||
this._currTabIndex = 0;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
return true;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._params) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
scrimClickAction
|
||||
@keydown=${this._ignoreKeydown}
|
||||
@closed=${this._cancel}
|
||||
.heading=${true}
|
||||
>
|
||||
<div slot="heading">
|
||||
<ha-header-bar>
|
||||
<div slot="title">
|
||||
${this._viewConfig.title
|
||||
? this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.pick_card_view_title",
|
||||
"name",
|
||||
`"${this._viewConfig.title}"`
|
||||
)
|
||||
: this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.pick_card"
|
||||
)}
|
||||
</div>
|
||||
</ha-header-bar>
|
||||
<mwc-tab-bar
|
||||
.activeIndex=${this._currTabIndex}
|
||||
@MDCTabBar:activated=${(ev: CustomEvent) =>
|
||||
this._handleTabChanged(ev)}
|
||||
>
|
||||
<mwc-tab
|
||||
.label=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.cardpicker.by_card"
|
||||
)}
|
||||
></mwc-tab>
|
||||
<mwc-tab
|
||||
.label=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.cardpicker.by_entity"
|
||||
)}
|
||||
></mwc-tab>
|
||||
</mwc-tab-bar>
|
||||
</div>
|
||||
${this._currTabIndex === 0
|
||||
? html`
|
||||
<hui-card-picker
|
||||
.lovelace=${this._params.lovelaceConfig}
|
||||
.hass=${this.hass}
|
||||
@config-changed=${this._handleCardPicked}
|
||||
></hui-card-picker>
|
||||
`
|
||||
: html`
|
||||
<div class="entity-picker-container">
|
||||
<hui-entity-picker-table
|
||||
.hass=${this.hass}
|
||||
.narrow=${true}
|
||||
.entities=${this._allEntities(this.hass.states)}
|
||||
@selected-changed=${this._handleSelectedChanged}
|
||||
></hui-entity-picker-table>
|
||||
</div>
|
||||
`}
|
||||
|
||||
<div slot="primaryAction">
|
||||
<mwc-button @click=${this._cancel}>
|
||||
${this.hass!.localize("ui.common.cancel")}
|
||||
</mwc-button>
|
||||
${this._selectedEntities.length
|
||||
? html`
|
||||
<mwc-button @click=${this._suggestCards}>
|
||||
${this.hass!.localize("ui.common.continue")}
|
||||
</mwc-button>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _ignoreKeydown(ev: KeyboardEvent) {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 850px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: 845px;
|
||||
}
|
||||
}
|
||||
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: 845px;
|
||||
}
|
||||
|
||||
ha-header-bar {
|
||||
--mdc-theme-on-primary: var(--primary-text-color);
|
||||
--mdc-theme-primary: var(--mdc-theme-surface);
|
||||
flex-shrink: 0;
|
||||
border-bottom: 1px solid
|
||||
var(--mdc-dialog-scroll-divider-color, rgba(0, 0, 0, 0.12));
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: calc(100% - 32px);
|
||||
--mdc-dialog-min-width: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
.header_button {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
mwc-tab-bar {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.entity-picker-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: calc(100vh - 112px);
|
||||
margin-top: -20px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
private _handleCardPicked(ev) {
|
||||
const config = ev.detail.config;
|
||||
if (this._params!.entities && this._params!.entities.length) {
|
||||
if (Object.keys(config).includes("entities")) {
|
||||
config.entities = this._params!.entities;
|
||||
} else if (Object.keys(config).includes("entity")) {
|
||||
config.entity = this._params!.entities[0];
|
||||
}
|
||||
}
|
||||
|
||||
showEditCardDialog(this, {
|
||||
lovelaceConfig: this._params!.lovelaceConfig,
|
||||
saveConfig: this._params!.saveConfig,
|
||||
path: this._params!.path,
|
||||
cardConfig: config,
|
||||
});
|
||||
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private _handleTabChanged(ev: CustomEvent): void {
|
||||
const newTab = ev.detail.index;
|
||||
if (newTab === this._currTabIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._currTabIndex = ev.detail.index;
|
||||
this._selectedEntities = [];
|
||||
}
|
||||
|
||||
private _handleSelectedChanged(ev: CustomEvent): void {
|
||||
this._selectedEntities = ev.detail.selectedEntities;
|
||||
}
|
||||
|
||||
private _cancel(ev?: Event) {
|
||||
if (ev) {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private _suggestCards(): void {
|
||||
showSuggestCardDialog(this, {
|
||||
lovelaceConfig: this._params!.lovelaceConfig,
|
||||
saveConfig: this._params!.saveConfig,
|
||||
path: this._params!.path as [number],
|
||||
entities: this._selectedEntities,
|
||||
});
|
||||
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private _allEntities = memoize((entities) =>
|
||||
Object.keys(entities).map((entity) => {
|
||||
const stateObj = this.hass.states[entity];
|
||||
return {
|
||||
icon: "",
|
||||
entity_id: entity,
|
||||
stateObj,
|
||||
name: computeStateName(stateObj),
|
||||
domain: computeDomain(entity),
|
||||
last_changed: stateObj!.last_changed,
|
||||
} as DataTableRowData;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dialog-create-card": HuiCreateDialogCard;
|
||||
}
|
||||
}
|
@ -11,28 +11,32 @@ import {
|
||||
TemplateResult,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-dialog";
|
||||
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 {
|
||||
LovelaceCardConfig,
|
||||
LovelaceViewConfig,
|
||||
} from "../../../../data/lovelace";
|
||||
import { haStyleDialog } from "../../../../resources/styles";
|
||||
import "../../../../components/ha-circular-progress";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
||||
import { addCard, replaceCard } from "../config-util";
|
||||
import type { GUIModeChangedEvent } from "../types";
|
||||
|
||||
import "./hui-card-editor";
|
||||
import type { ConfigChangedEvent, HuiCardEditor } from "./hui-card-editor";
|
||||
import "./hui-card-picker";
|
||||
import "./hui-card-preview";
|
||||
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
||||
import { getCardDocumentationURL } from "../get-card-documentation-url";
|
||||
import { mdiHelpCircle } from "@mdi/js";
|
||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||
import { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
import "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-header-bar";
|
||||
import "../../../../components/ha-circular-progress";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
@ -47,7 +51,7 @@ declare global {
|
||||
|
||||
@customElement("hui-dialog-edit-card")
|
||||
export class HuiDialogEditCard extends LitElement implements HassDialog {
|
||||
@property() protected hass!: HomeAssistant;
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _params?: EditCardDialogParams;
|
||||
|
||||
@ -150,62 +154,56 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
||||
@keydown=${this._ignoreKeydown}
|
||||
@closed=${this._cancel}
|
||||
@opened=${this._opened}
|
||||
.heading=${html`${heading}
|
||||
${this._documentationURL !== undefined
|
||||
? html`
|
||||
<a
|
||||
class="header_button"
|
||||
href=${this._documentationURL}
|
||||
title=${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<mwc-icon-button>
|
||||
<ha-svg-icon path=${mdiHelpCircle}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</a>
|
||||
`
|
||||
: ""}`}
|
||||
.heading=${true}
|
||||
>
|
||||
<div>
|
||||
${this._cardConfig === undefined
|
||||
? html`
|
||||
<hui-card-picker
|
||||
.lovelace=${this._params.lovelaceConfig}
|
||||
.hass=${this.hass}
|
||||
@config-changed=${this._handleCardPicked}
|
||||
></hui-card-picker>
|
||||
`
|
||||
: html`
|
||||
<div class="content">
|
||||
<div class="element-editor">
|
||||
<hui-card-editor
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this._params.lovelaceConfig}
|
||||
.value=${this._cardConfig}
|
||||
@config-changed=${this._handleConfigChanged}
|
||||
@GUImode-changed=${this._handleGUIModeChanged}
|
||||
@editor-save=${this._save}
|
||||
></hui-card-editor>
|
||||
</div>
|
||||
<div class="element-preview">
|
||||
<hui-card-preview
|
||||
.hass=${this.hass}
|
||||
.config=${this._cardConfig}
|
||||
class=${this._error ? "blur" : ""}
|
||||
></hui-card-preview>
|
||||
${this._error
|
||||
? html`
|
||||
<ha-circular-progress
|
||||
active
|
||||
alt="Can't update card"
|
||||
></ha-circular-progress>
|
||||
`
|
||||
: ``}
|
||||
</div>
|
||||
</div>
|
||||
`}
|
||||
<div slot="heading">
|
||||
<ha-header-bar>
|
||||
<div slot="title">${heading}</div>
|
||||
${this._documentationURL !== undefined
|
||||
? html`
|
||||
<a
|
||||
slot="actionItems"
|
||||
class="header_button"
|
||||
href=${this._documentationURL}
|
||||
title=${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<mwc-icon-button>
|
||||
<ha-svg-icon path=${mdiHelpCircle}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
</ha-header-bar>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="element-editor">
|
||||
<hui-card-editor
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this._params.lovelaceConfig}
|
||||
.value=${this._cardConfig}
|
||||
@config-changed=${this._handleConfigChanged}
|
||||
@GUImode-changed=${this._handleGUIModeChanged}
|
||||
@editor-save=${this._save}
|
||||
></hui-card-editor>
|
||||
</div>
|
||||
<div class="element-preview">
|
||||
<hui-card-preview
|
||||
.hass=${this.hass}
|
||||
.config=${this._cardConfig}
|
||||
class=${this._error ? "blur" : ""}
|
||||
></hui-card-preview>
|
||||
${this._error
|
||||
? html`
|
||||
<ha-circular-progress
|
||||
active
|
||||
alt="Can't update card"
|
||||
></ha-circular-progress>
|
||||
`
|
||||
: ``}
|
||||
</div>
|
||||
</div>
|
||||
${this._cardConfig !== undefined
|
||||
? html`
|
||||
@ -256,126 +254,6 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
:host {
|
||||
--code-mirror-max-height: calc(100vh - 176px);
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 850px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: 845px;
|
||||
}
|
||||
}
|
||||
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: 845px;
|
||||
}
|
||||
|
||||
.center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 -10px;
|
||||
}
|
||||
.content hui-card-preview {
|
||||
margin: 4px auto;
|
||||
max-width: 390px;
|
||||
}
|
||||
.content .element-editor {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: calc(100% - 32px);
|
||||
--mdc-dialog-min-width: 1000px;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-direction: row;
|
||||
}
|
||||
.content > * {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.content hui-card-preview {
|
||||
padding: 8px 10px;
|
||||
margin: auto 0px;
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
mwc-button ha-circular-progress {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.element-editor {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.blur {
|
||||
filter: blur(2px) grayscale(100%);
|
||||
}
|
||||
.element-preview {
|
||||
position: relative;
|
||||
}
|
||||
.element-preview ha-circular-progress {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
hui-card-preview {
|
||||
padding-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.gui-mode-button {
|
||||
margin-right: auto;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
private _handleCardPicked(ev) {
|
||||
const config = ev.detail.config;
|
||||
if (this._params!.entities && this._params!.entities.length) {
|
||||
if (Object.keys(config).includes("entities")) {
|
||||
config.entities = this._params!.entities;
|
||||
} else if (Object.keys(config).includes("entity")) {
|
||||
config.entity = this._params!.entities[0];
|
||||
}
|
||||
}
|
||||
this._cardConfig = deepFreeze(config);
|
||||
this._error = ev.detail.error;
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
private _handleConfigChanged(ev: HASSDomEvent<ConfigChangedEvent>) {
|
||||
this._cardConfig = deepFreeze(ev.detail.config);
|
||||
this._error = ev.detail.error;
|
||||
@ -463,6 +341,124 @@ export class HuiDialogEditCard extends LitElement implements HassDialog {
|
||||
showSaveSuccessToast(this, this.hass);
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
:host {
|
||||
--code-mirror-max-height: calc(100vh - 176px);
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 850px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: 845px;
|
||||
}
|
||||
}
|
||||
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: 845px;
|
||||
}
|
||||
|
||||
ha-header-bar {
|
||||
--mdc-theme-on-primary: var(--primary-text-color);
|
||||
--mdc-theme-primary: var(--mdc-theme-surface);
|
||||
flex-shrink: 0;
|
||||
border-bottom: 1px solid
|
||||
var(--mdc-dialog-scroll-divider-color, rgba(0, 0, 0, 0.12));
|
||||
}
|
||||
|
||||
.center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 -10px;
|
||||
}
|
||||
.content hui-card-preview {
|
||||
margin: 4px auto;
|
||||
max-width: 390px;
|
||||
}
|
||||
.content .element-editor {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-max-width: calc(100% - 32px);
|
||||
--mdc-dialog-min-width: 1000px;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-direction: row;
|
||||
}
|
||||
.content > * {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.content hui-card-preview {
|
||||
padding: 8px 10px;
|
||||
margin: auto 0px;
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
mwc-button ha-circular-progress {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.element-editor {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.blur {
|
||||
filter: blur(2px) grayscale(100%);
|
||||
}
|
||||
.element-preview {
|
||||
position: relative;
|
||||
}
|
||||
.element-preview ha-circular-progress {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
hui-card-preview {
|
||||
padding-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.gui-mode-button {
|
||||
margin-right: auto;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.header_button {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -5,9 +5,9 @@ import {
|
||||
CSSResultArray,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
internalProperty,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
@ -21,7 +21,7 @@ import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
||||
import { computeCards } from "../../common/generate-lovelace-config";
|
||||
import { addCards } from "../config-util";
|
||||
import "./hui-card-preview";
|
||||
import { showEditCardDialog } from "./show-edit-card-dialog";
|
||||
import { showCreateCardDialog } from "./show-create-card-dialog";
|
||||
import { SuggestCardDialogParams } from "./show-suggest-card-dialog";
|
||||
|
||||
@customElement("hui-dialog-suggest-card")
|
||||
@ -179,7 +179,8 @@ export class HuiDialogSuggestCard extends LitElement {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
showEditCardDialog(this, {
|
||||
|
||||
showCreateCardDialog(this, {
|
||||
lovelaceConfig: this._params!.lovelaceConfig,
|
||||
saveConfig: this._params!.saveConfig,
|
||||
path: this._params!.path,
|
||||
|
@ -0,0 +1,151 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||
import "../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
DataTableRowData,
|
||||
SelectionChangedEvent,
|
||||
} from "../../../../components/data-table/ha-data-table";
|
||||
import "../../../../components/entity/state-badge";
|
||||
import "../../../../components/ha-relative-time";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
|
||||
@customElement("hui-entity-picker-table")
|
||||
export class HuiEntityPickerTable extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean }) public narrow?: boolean;
|
||||
|
||||
@property({ type: Array }) public entities!: DataTableRowData[];
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-data-table
|
||||
auto-height
|
||||
selectable
|
||||
.id=${"entity_id"}
|
||||
.columns=${this._columns(this.narrow!)}
|
||||
.data=${this.entities}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize(
|
||||
"ui.panel.lovelace.unused_entities.search"
|
||||
)}
|
||||
.noDataText=${this.hass.localize(
|
||||
"ui.panel.lovelace.unused_entities.no_data"
|
||||
)}
|
||||
@selection-changed=${this._handleSelectionChanged}
|
||||
></ha-data-table>
|
||||
`;
|
||||
}
|
||||
|
||||
private _columns = memoizeOne((narrow: boolean) => {
|
||||
const columns: DataTableColumnContainer = {
|
||||
icon: {
|
||||
title: "",
|
||||
type: "icon",
|
||||
template: (_icon, entity: any) => html`
|
||||
<state-badge
|
||||
@click=${this._handleEntityClicked}
|
||||
.hass=${this.hass!}
|
||||
.stateObj=${entity.stateObj}
|
||||
></state-badge>
|
||||
`,
|
||||
},
|
||||
name: {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
grows: true,
|
||||
direction: "asc",
|
||||
template: (name, entity: any) => html`
|
||||
<div @click=${this._handleEntityClicked} style="cursor: pointer;">
|
||||
${name}
|
||||
${narrow
|
||||
? html`
|
||||
<div class="secondary">
|
||||
${entity.stateObj.entity_id}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
};
|
||||
|
||||
columns.entity_id = {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity_id"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "30%",
|
||||
hidden: narrow,
|
||||
};
|
||||
|
||||
columns.domain = {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.domain"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "15%",
|
||||
hidden: narrow,
|
||||
};
|
||||
|
||||
columns.last_changed = {
|
||||
title: this.hass!.localize(
|
||||
"ui.panel.lovelace.unused_entities.last_changed"
|
||||
),
|
||||
type: "numeric",
|
||||
sortable: true,
|
||||
width: "15%",
|
||||
hidden: narrow,
|
||||
template: (lastChanged: string) => html`
|
||||
<ha-relative-time
|
||||
.hass=${this.hass!}
|
||||
.datetime=${lastChanged}
|
||||
></ha-relative-time>
|
||||
`,
|
||||
};
|
||||
|
||||
return columns;
|
||||
});
|
||||
|
||||
private _handleSelectionChanged(
|
||||
ev: HASSDomEvent<SelectionChangedEvent>
|
||||
): void {
|
||||
const selectedEntities = ev.detail.value;
|
||||
|
||||
fireEvent(this, "selected-changed", { selectedEntities });
|
||||
}
|
||||
|
||||
private _handleEntityClicked(ev: Event) {
|
||||
const entityId = ((ev.target as HTMLElement).closest(
|
||||
".mdc-data-table__row"
|
||||
) as any).rowId;
|
||||
fireEvent(this, "hass-more-info", {
|
||||
entityId,
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-data-table {
|
||||
--data-table-border-width: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-entity-picker-table": HuiEntityPickerTable;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { LovelaceConfig } from "../../../../data/lovelace";
|
||||
|
||||
export interface CreateCardDialogParams {
|
||||
lovelaceConfig: LovelaceConfig;
|
||||
saveConfig: (config: LovelaceConfig) => void;
|
||||
path: [number] | [number, number];
|
||||
entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked
|
||||
}
|
||||
|
||||
const importCreateCardDialog = () =>
|
||||
import(
|
||||
/* webpackChunkName: "hui-dialog-create-card" */ "./hui-dialog-create-card"
|
||||
);
|
||||
|
||||
export const showCreateCardDialog = (
|
||||
element: HTMLElement,
|
||||
createCardDialogParams: CreateCardDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "hui-dialog-create-card",
|
||||
dialogImport: importCreateCardDialog,
|
||||
dialogParams: createCardDialogParams,
|
||||
});
|
||||
};
|
@ -10,39 +10,31 @@ import {
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { mdiPlus } from "@mdi/js";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
|
||||
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../../common/entity/compute_state_name";
|
||||
import {
|
||||
computeRTL,
|
||||
computeRTLDirection,
|
||||
} from "../../../../common/util/compute_rtl";
|
||||
import "../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
SelectionChangedEvent,
|
||||
} from "../../../../components/data-table/ha-data-table";
|
||||
import "../../../../components/entity/state-badge";
|
||||
import "../../../../components/ha-icon";
|
||||
import "../../../../components/ha-relative-time";
|
||||
import type { LovelaceConfig } from "../../../../data/lovelace";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||
import { computeUnusedEntities } from "../../common/compute-unused-entities";
|
||||
import type { Lovelace } from "../../types";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
import { mdiPlus } from "@mdi/js";
|
||||
import { showSuggestCardDialog } from "../card-editor/show-suggest-card-dialog";
|
||||
import { showSelectViewDialog } from "../select-view/show-select-view-dialog";
|
||||
|
||||
import type { DataTableRowData } from "../../../../components/data-table/ha-data-table";
|
||||
import type { LovelaceConfig } from "../../../../data/lovelace";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { Lovelace } from "../../types";
|
||||
|
||||
import "../card-editor/hui-entity-picker-table";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
|
||||
@customElement("hui-unused-entities")
|
||||
export class HuiUnusedEntities extends LitElement {
|
||||
@property({ attribute: false }) public lovelace!: Lovelace;
|
||||
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public narrow?: boolean;
|
||||
@property({ type: Boolean }) public narrow?: boolean;
|
||||
|
||||
@internalProperty() private _unusedEntities: string[] = [];
|
||||
|
||||
@ -52,74 +44,6 @@ export class HuiUnusedEntities extends LitElement {
|
||||
return this.lovelace.config;
|
||||
}
|
||||
|
||||
private _columns = memoizeOne((narrow: boolean) => {
|
||||
const columns: DataTableColumnContainer = {
|
||||
icon: {
|
||||
title: "",
|
||||
type: "icon",
|
||||
template: (_icon, entity: any) => html`
|
||||
<state-badge
|
||||
@click=${this._handleEntityClicked}
|
||||
.hass=${this.hass!}
|
||||
.stateObj=${entity.stateObj}
|
||||
></state-badge>
|
||||
`,
|
||||
},
|
||||
name: {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
grows: true,
|
||||
direction: "asc",
|
||||
template: (name, entity: any) => html`
|
||||
<div @click=${this._handleEntityClicked} style="cursor: pointer;">
|
||||
${name}
|
||||
${narrow
|
||||
? html`
|
||||
<div class="secondary">
|
||||
${entity.stateObj.entity_id}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
};
|
||||
|
||||
if (narrow) {
|
||||
return columns;
|
||||
}
|
||||
|
||||
columns.entity_id = {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.entity_id"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "30%",
|
||||
};
|
||||
columns.domain = {
|
||||
title: this.hass!.localize("ui.panel.lovelace.unused_entities.domain"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "15%",
|
||||
};
|
||||
columns.last_changed = {
|
||||
title: this.hass!.localize(
|
||||
"ui.panel.lovelace.unused_entities.last_changed"
|
||||
),
|
||||
type: "numeric",
|
||||
sortable: true,
|
||||
width: "15%",
|
||||
template: (lastChanged: string) => html`
|
||||
<ha-relative-time
|
||||
.hass=${this.hass!}
|
||||
.datetime=${lastChanged}
|
||||
></ha-relative-time>
|
||||
`,
|
||||
};
|
||||
|
||||
return columns;
|
||||
});
|
||||
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
@ -161,9 +85,10 @@ export class HuiUnusedEntities extends LitElement {
|
||||
</ha-card>
|
||||
`
|
||||
: ""}
|
||||
<ha-data-table
|
||||
.columns=${this._columns(this.narrow!)}
|
||||
.data=${this._unusedEntities.map((entity) => {
|
||||
<hui-entity-picker-table
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.entities=${this._unusedEntities.map((entity) => {
|
||||
const stateObj = this.hass!.states[entity];
|
||||
return {
|
||||
icon: "",
|
||||
@ -173,18 +98,9 @@ export class HuiUnusedEntities extends LitElement {
|
||||
domain: computeDomain(entity),
|
||||
last_changed: stateObj!.last_changed,
|
||||
};
|
||||
})}
|
||||
.id=${"entity_id"}
|
||||
selectable
|
||||
@selection-changed=${this._handleSelectionChanged}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize(
|
||||
"ui.panel.lovelace.unused_entities.search"
|
||||
)}
|
||||
.noDataText=${this.hass.localize(
|
||||
"ui.panel.lovelace.unused_entities.no_data"
|
||||
)}
|
||||
></ha-data-table>
|
||||
}) as DataTableRowData[]}
|
||||
@selected-changed=${this._handleSelectedChanged}
|
||||
></hui-entity-picker-table>
|
||||
</div>
|
||||
<div
|
||||
class="fab ${classMap({
|
||||
@ -211,19 +127,8 @@ export class HuiUnusedEntities extends LitElement {
|
||||
this._unusedEntities = [...unusedEntities].sort();
|
||||
}
|
||||
|
||||
private _handleSelectionChanged(
|
||||
ev: HASSDomEvent<SelectionChangedEvent>
|
||||
): void {
|
||||
this._selectedEntities = ev.detail.value;
|
||||
}
|
||||
|
||||
private _handleEntityClicked(ev: Event) {
|
||||
const entityId = ((ev.target as HTMLElement).closest(
|
||||
".mdc-data-table__row"
|
||||
) as any).rowId;
|
||||
fireEvent(this, "hass-more-info", {
|
||||
entityId,
|
||||
});
|
||||
private _handleSelectedChanged(ev: CustomEvent): void {
|
||||
this._selectedEntities = ev.detail.selectedEntities;
|
||||
}
|
||||
|
||||
private _addToLovelaceView(): void {
|
||||
@ -258,25 +163,22 @@ export class HuiUnusedEntities extends LitElement {
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* min-height: calc(100vh - 112px); */
|
||||
height: 100%;
|
||||
}
|
||||
ha-card {
|
||||
--ha-card-box-shadow: none;
|
||||
--ha-card-border-radius: 0;
|
||||
}
|
||||
ha-data-table {
|
||||
--data-table-border-width: 0;
|
||||
hui-entity-picker-table {
|
||||
flex-grow: 1;
|
||||
margin-top: -20px;
|
||||
}
|
||||
.fab {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 16px;
|
||||
padding-right: calc(16px + env(safe-area-inset-right));
|
||||
padding-bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
position: sticky;
|
||||
float: right;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
}
|
||||
.fab.rtl {
|
||||
|
@ -23,11 +23,11 @@ import { computeCardSize } from "../common/compute-card-size";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { createBadgeElement } from "../create-element/create-badge-element";
|
||||
import { createCardElement } from "../create-element/create-card-element";
|
||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
import { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import { mdiPlus } from "@mdi/js";
|
||||
import { nextRender } from "../../../common/util/render-status";
|
||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||
|
||||
let editCodeLoaded = false;
|
||||
|
||||
@ -186,7 +186,7 @@ export class HUIView extends LitElement {
|
||||
}
|
||||
|
||||
private _addCard(): void {
|
||||
showEditCardDialog(this, {
|
||||
showCreateCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: [this.index!],
|
||||
|
@ -260,6 +260,7 @@
|
||||
},
|
||||
"common": {
|
||||
"and": "and",
|
||||
"continue": "Continue",
|
||||
"previous": "Previous",
|
||||
"loading": "Loading",
|
||||
"refresh": "Refresh",
|
||||
@ -2351,7 +2352,11 @@
|
||||
},
|
||||
"cardpicker": {
|
||||
"no_description": "No description available.",
|
||||
"custom_card": "Custom"
|
||||
"custom_card": "Custom",
|
||||
"domain": "Domain",
|
||||
"entity": "Entity",
|
||||
"by_entity": "By Entity",
|
||||
"by_card": "By Card"
|
||||
}
|
||||
},
|
||||
"warning": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user