mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-08 09:56:36 +00:00
Card Editor: Documentation per Card (#5888)
* Doc-links * Comments * Fix * Remove unneeded code * undo the change * better
This commit is contained in:
parent
1ad1fd28f1
commit
a1ee9ad48b
@ -3,6 +3,7 @@ export interface CustomCardEntry {
|
|||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
preview?: boolean;
|
preview?: boolean;
|
||||||
|
documentationURL?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CustomCardsWindow {
|
export interface CustomCardsWindow {
|
||||||
|
@ -30,52 +30,14 @@ import {
|
|||||||
import { createCardElement } from "../../create-element/create-card-element";
|
import { createCardElement } from "../../create-element/create-card-element";
|
||||||
import { LovelaceCard } from "../../types";
|
import { LovelaceCard } from "../../types";
|
||||||
import { getCardStubConfig } from "../get-card-stub-config";
|
import { getCardStubConfig } from "../get-card-stub-config";
|
||||||
import { CardPickTarget } from "../types";
|
import { CardPickTarget, Card } from "../types";
|
||||||
|
import { coreCards } from "../lovelace-cards";
|
||||||
interface Card {
|
|
||||||
type: string;
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
noElement?: boolean;
|
|
||||||
isCustom?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CardElement {
|
interface CardElement {
|
||||||
card: Card;
|
card: Card;
|
||||||
element: TemplateResult;
|
element: TemplateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const previewCards: string[] = [
|
|
||||||
"alarm-panel",
|
|
||||||
"button",
|
|
||||||
"entities",
|
|
||||||
"entity",
|
|
||||||
"gauge",
|
|
||||||
"glance",
|
|
||||||
"history-graph",
|
|
||||||
"light",
|
|
||||||
"map",
|
|
||||||
"markdown",
|
|
||||||
"media-control",
|
|
||||||
"picture",
|
|
||||||
"picture-elements",
|
|
||||||
"picture-entity",
|
|
||||||
"picture-glance",
|
|
||||||
"plant-status",
|
|
||||||
"sensor",
|
|
||||||
"thermostat",
|
|
||||||
"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 {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
@ -136,11 +98,7 @@ export class HuiCardPicker extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div class="cards-container">
|
<div class="cards-container">
|
||||||
<div
|
<div class="card" @click=${this._cardPicked} .config=${{ type: "" }}>
|
||||||
class="card"
|
|
||||||
@click="${this._cardPicked}"
|
|
||||||
.config="${{ type: "" }}"
|
|
||||||
>
|
|
||||||
<div class="preview description">
|
<div class="preview description">
|
||||||
${this.hass!.localize(
|
${this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.manual_description`
|
`ui.panel.lovelace.editor.card.generic.manual_description`
|
||||||
@ -192,33 +150,22 @@ export class HuiCardPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _loadCards() {
|
private _loadCards() {
|
||||||
let cards: Card[] = previewCards
|
let cards: Card[] = coreCards.map((card: Card) => ({
|
||||||
.map((type: string) => ({
|
|
||||||
type,
|
|
||||||
name: this.hass!.localize(`ui.panel.lovelace.editor.card.${type}.name`),
|
|
||||||
description: this.hass!.localize(
|
|
||||||
`ui.panel.lovelace.editor.card.${type}.description`
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
.concat(
|
|
||||||
nonPreviewCards.map((type: string) => ({
|
|
||||||
type,
|
|
||||||
name: this.hass!.localize(
|
name: this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.${type}.name`
|
`ui.panel.lovelace.editor.card.${card.type}.name`
|
||||||
),
|
),
|
||||||
description: this.hass!.localize(
|
description: this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.${type}.description`
|
`ui.panel.lovelace.editor.card.${card.type}.description`
|
||||||
),
|
),
|
||||||
noElement: true,
|
...card,
|
||||||
}))
|
}));
|
||||||
);
|
|
||||||
if (customCards.length > 0) {
|
if (customCards.length > 0) {
|
||||||
cards = cards.concat(
|
cards = cards.concat(
|
||||||
customCards.map((ccard: CustomCardEntry) => ({
|
customCards.map((ccard: CustomCardEntry) => ({
|
||||||
type: ccard.type,
|
type: ccard.type,
|
||||||
name: ccard.name,
|
name: ccard.name,
|
||||||
description: ccard.description,
|
description: ccard.description,
|
||||||
noElement: true,
|
showElement: ccard.preview,
|
||||||
isCustom: true,
|
isCustom: true,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -341,7 +288,7 @@ export class HuiCardPicker extends LitElement {
|
|||||||
|
|
||||||
private async _renderCardElement(card: Card): Promise<TemplateResult> {
|
private async _renderCardElement(card: Card): Promise<TemplateResult> {
|
||||||
let { type } = card;
|
let { type } = card;
|
||||||
const { noElement, isCustom, name, description } = card;
|
const { showElement, isCustom, name, description } = card;
|
||||||
const customCard = isCustom ? getCustomCardEntry(type) : undefined;
|
const customCard = isCustom ? getCustomCardEntry(type) : undefined;
|
||||||
if (isCustom) {
|
if (isCustom) {
|
||||||
type = `${CUSTOM_TYPE_PREFIX}${type}`;
|
type = `${CUSTOM_TYPE_PREFIX}${type}`;
|
||||||
@ -358,7 +305,7 @@ export class HuiCardPicker extends LitElement {
|
|||||||
this._usedEntities!
|
this._usedEntities!
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!noElement || customCard?.preview) {
|
if (showElement) {
|
||||||
element = this._createCardElement(cardConfig);
|
element = this._createCardElement(cardConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
import deepFreeze from "deep-freeze";
|
import deepFreeze from "deep-freeze";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@ -8,6 +9,7 @@ import {
|
|||||||
property,
|
property,
|
||||||
query,
|
query,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/dialog/ha-paper-dialog";
|
import "../../../../components/dialog/ha-paper-dialog";
|
||||||
@ -25,7 +27,7 @@ import type { ConfigChangedEvent, HuiCardEditor } from "./hui-card-editor";
|
|||||||
import "./hui-card-picker";
|
import "./hui-card-picker";
|
||||||
import "./hui-card-preview";
|
import "./hui-card-preview";
|
||||||
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
import type { EditCardDialogParams } from "./show-edit-card-dialog";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
import { getCardDocumentationURL } from "../get-card-documentation-url";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
@ -58,6 +60,8 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
|
|
||||||
@property() private _GUImode = true;
|
@property() private _GUImode = true;
|
||||||
|
|
||||||
|
@property() private _documentationURL?: string;
|
||||||
|
|
||||||
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
public async showDialog(params: EditCardDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._GUImode = true;
|
this._GUImode = true;
|
||||||
@ -71,6 +75,22 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues): void {
|
||||||
|
if (
|
||||||
|
!this._cardConfig ||
|
||||||
|
this._documentationURL !== undefined ||
|
||||||
|
!changedProps.has("_cardConfig")
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldConfig = changedProps.get("_cardConfig") as LovelaceCardConfig;
|
||||||
|
|
||||||
|
if (oldConfig?.type !== this._cardConfig!.type) {
|
||||||
|
this._documentationURL = getCardDocumentationURL(this._cardConfig!.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -97,9 +117,26 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-paper-dialog with-backdrop opened modal @keyup=${this._handleKeyUp}>
|
<ha-paper-dialog with-backdrop opened modal @keyup=${this._handleKeyUp}>
|
||||||
|
<div class="header">
|
||||||
<h2>
|
<h2>
|
||||||
${heading}
|
${heading}
|
||||||
</h2>
|
</h2>
|
||||||
|
${this._documentationURL !== undefined
|
||||||
|
? html`
|
||||||
|
<a
|
||||||
|
class="help-icon"
|
||||||
|
href=${this._documentationURL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
icon="hass:help-circle"
|
||||||
|
.title=${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
<paper-dialog-scrollable>
|
<paper-dialog-scrollable>
|
||||||
${this._cardConfig === undefined
|
${this._cardConfig === undefined
|
||||||
? html`
|
? html`
|
||||||
@ -275,6 +312,15 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
.gui-mode-button {
|
.gui-mode-button {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.help-icon {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -318,6 +364,7 @@ export class HuiDialogEditCard extends LitElement {
|
|||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
this._cardConfig = undefined;
|
this._cardConfig = undefined;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
|
this._documentationURL = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _canSave(): boolean {
|
private get _canSave(): boolean {
|
||||||
|
14
src/panels/lovelace/editor/get-card-documentation-url.ts
Normal file
14
src/panels/lovelace/editor/get-card-documentation-url.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {
|
||||||
|
getCustomCardEntry,
|
||||||
|
CUSTOM_TYPE_PREFIX,
|
||||||
|
} from "../../../data/lovelace_custom_cards";
|
||||||
|
|
||||||
|
const coreDocumentationURLBase = "https://www.home-assistant.io/lovelace/";
|
||||||
|
|
||||||
|
export const getCardDocumentationURL = (type: string): string | undefined => {
|
||||||
|
if (type.startsWith(CUSTOM_TYPE_PREFIX)) {
|
||||||
|
return getCustomCardEntry(type)?.documentationURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${coreDocumentationURLBase}${type}`;
|
||||||
|
};
|
98
src/panels/lovelace/editor/lovelace-cards.ts
Normal file
98
src/panels/lovelace/editor/lovelace-cards.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { Card } from "./types";
|
||||||
|
|
||||||
|
export const coreCards: Card[] = [
|
||||||
|
{
|
||||||
|
type: "alarm-panel",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "entities",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "entity",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "gauge",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "glance",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "history-graph",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "light",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "map",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "markdown",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "media-control",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "picture",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "picture-elements",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "picture-entity",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "picture-glance",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "plant-status",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "sensor",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "thermostat",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "weather-forecast",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "conditional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "entity-filter",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "horizontal-stack",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "iframe",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "vertical-stack",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "shopping-list",
|
||||||
|
},
|
||||||
|
];
|
@ -54,6 +54,14 @@ export interface EditorTarget extends EventTarget {
|
|||||||
config: ActionConfig;
|
config: ActionConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Card {
|
||||||
|
type: string;
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
showElement?: boolean;
|
||||||
|
isCustom?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CardPickTarget extends EventTarget {
|
export interface CardPickTarget extends EventTarget {
|
||||||
config: LovelaceCardConfig;
|
config: LovelaceCardConfig;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user