mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Update create automation dialog (#15286)
This commit is contained in:
parent
c19cba85ec
commit
b2bfb1fdcb
@ -41,9 +41,9 @@ class HaBluePrintPicker extends LitElement {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const result = Object.entries(blueprints)
|
const result = Object.entries(blueprints)
|
||||||
.filter(([_path, blueprint]) => !("error" in blueprint))
|
.filter((entry): entry is [string, Blueprint] => !("error" in entry[1]))
|
||||||
.map(([path, blueprint]) => ({
|
.map(([path, blueprint]) => ({
|
||||||
...(blueprint as Blueprint).metadata,
|
...blueprint.metadata,
|
||||||
path,
|
path,
|
||||||
}));
|
}));
|
||||||
return result.sort((a, b) =>
|
return result.sort((a, b) =>
|
||||||
|
@ -16,6 +16,7 @@ export interface BlueprintMetaData {
|
|||||||
input?: Record<string, BlueprintInput | null>;
|
input?: Record<string, BlueprintInput | null>;
|
||||||
description?: string;
|
description?: string;
|
||||||
source_url?: string;
|
source_url?: string;
|
||||||
|
author?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BlueprintInput {
|
export interface BlueprintInput {
|
||||||
@ -63,3 +64,19 @@ export const deleteBlueprint = (
|
|||||||
domain,
|
domain,
|
||||||
path,
|
path,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type BlueprintSourceType = "local" | "community" | "homeassistant";
|
||||||
|
|
||||||
|
export const getBlueprintSourceType = (
|
||||||
|
blueprint: Blueprint
|
||||||
|
): BlueprintSourceType => {
|
||||||
|
const sourceUrl = blueprint.metadata.source_url;
|
||||||
|
|
||||||
|
if (!sourceUrl) {
|
||||||
|
return "local";
|
||||||
|
}
|
||||||
|
if (sourceUrl.includes("github.com/home-assistant")) {
|
||||||
|
return "homeassistant";
|
||||||
|
}
|
||||||
|
return "community";
|
||||||
|
};
|
||||||
|
@ -1,17 +1,40 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import {
|
||||||
|
mdiAccount,
|
||||||
|
mdiFile,
|
||||||
|
mdiHomeAssistant,
|
||||||
|
mdiOpenInNew,
|
||||||
|
mdiPencilOutline,
|
||||||
|
mdiWeb,
|
||||||
|
} from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/ha-blueprint-picker";
|
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
|
||||||
import "../../../components/ha-circular-progress";
|
import { stringCompare } from "../../../common/string/compare";
|
||||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||||
|
import "../../../components/ha-icon-next";
|
||||||
|
import "../../../components/ha-list-item";
|
||||||
|
import "../../../components/ha-tip";
|
||||||
import { showAutomationEditor } from "../../../data/automation";
|
import { showAutomationEditor } from "../../../data/automation";
|
||||||
|
import {
|
||||||
|
Blueprint,
|
||||||
|
Blueprints,
|
||||||
|
BlueprintSourceType,
|
||||||
|
fetchBlueprints,
|
||||||
|
getBlueprintSourceType,
|
||||||
|
} from "../../../data/blueprint";
|
||||||
import { HassDialog } from "../../../dialogs/make-dialog-manager";
|
import { HassDialog } from "../../../dialogs/make-dialog-manager";
|
||||||
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
import { documentationUrl } from "../../../util/documentation-url";
|
||||||
import "../../../components/ha-icon-next";
|
|
||||||
import "@material/mwc-list/mwc-list";
|
const SOURCE_TYPE_ICONS: Record<BlueprintSourceType, string> = {
|
||||||
|
local: mdiFile,
|
||||||
|
community: mdiAccount,
|
||||||
|
homeassistant: mdiHomeAssistant,
|
||||||
|
};
|
||||||
|
|
||||||
@customElement("ha-dialog-new-automation")
|
@customElement("ha-dialog-new-automation")
|
||||||
class DialogNewAutomation extends LitElement implements HassDialog {
|
class DialogNewAutomation extends LitElement implements HassDialog {
|
||||||
@ -19,8 +42,13 @@ class DialogNewAutomation extends LitElement implements HassDialog {
|
|||||||
|
|
||||||
@state() private _opened = false;
|
@state() private _opened = false;
|
||||||
|
|
||||||
|
@state() public blueprints?: Blueprints;
|
||||||
|
|
||||||
public showDialog(): void {
|
public showDialog(): void {
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
|
fetchBlueprints(this.hass!, "automation").then((blueprints) => {
|
||||||
|
this.blueprints = blueprints;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
@ -30,10 +58,33 @@ class DialogNewAutomation extends LitElement implements HassDialog {
|
|||||||
this._opened = false;
|
this._opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _processedBlueprints = memoizeOne((blueprints?: Blueprints) => {
|
||||||
|
if (!blueprints) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const result = Object.entries(blueprints)
|
||||||
|
.filter((entry): entry is [string, Blueprint] => !("error" in entry[1]))
|
||||||
|
.map(([path, blueprint]) => {
|
||||||
|
const sourceType = getBlueprintSourceType(blueprint);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...blueprint.metadata,
|
||||||
|
sourceType,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return result.sort((a, b) =>
|
||||||
|
stringCompare(a.name, b.name, this.hass!.locale.language)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this._opened) {
|
if (!this._opened) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const processedBlueprints = this._processedBlueprints(this.blueprints);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-dialog
|
||||||
open
|
open
|
||||||
@ -41,48 +92,117 @@ class DialogNewAutomation extends LitElement implements HassDialog {
|
|||||||
@closed=${this.closeDialog}
|
@closed=${this.closeDialog}
|
||||||
.heading=${createCloseHeading(
|
.heading=${createCloseHeading(
|
||||||
this.hass,
|
this.hass,
|
||||||
this.hass.localize("ui.panel.config.automation.dialog_new.how")
|
this.hass.localize("ui.panel.config.automation.dialog_new.header")
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<mwc-list>
|
<mwc-list
|
||||||
<mwc-list-item twoline class="blueprint" @click=${this._blueprint}>
|
innerRole="listbox"
|
||||||
|
itemRoles="option"
|
||||||
|
innerAriaLabel=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.dialog_new.header"
|
||||||
|
)}
|
||||||
|
rootTabbable
|
||||||
|
dialogInitialFocus
|
||||||
|
>
|
||||||
|
<ha-list-item
|
||||||
|
hasmeta
|
||||||
|
twoline
|
||||||
|
graphic="icon"
|
||||||
|
@request-selected=${this._blank}
|
||||||
|
>
|
||||||
|
<ha-svg-icon slot="graphic" .path=${mdiPencilOutline}></ha-svg-icon>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.dialog_new.blueprint.use_blueprint"
|
"ui.panel.config.automation.dialog_new.create_empty"
|
||||||
)}
|
|
||||||
<span slot="secondary">
|
|
||||||
<ha-blueprint-picker
|
|
||||||
@value-changed=${this._blueprintPicked}
|
|
||||||
.hass=${this.hass}
|
|
||||||
></ha-blueprint-picker>
|
|
||||||
</span>
|
|
||||||
</mwc-list-item>
|
|
||||||
<li divider role="separator"></li>
|
|
||||||
<mwc-list-item hasmeta twoline @click=${this._blank}>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.automation.dialog_new.start_empty"
|
|
||||||
)}
|
)}
|
||||||
<span slot="secondary">
|
<span slot="secondary">
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.dialog_new.start_empty_description"
|
"ui.panel.config.automation.dialog_new.create_empty_description"
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<ha-icon-next slot="meta"></ha-icon-next>
|
<ha-icon-next slot="meta"></ha-icon-next>
|
||||||
</mwc-list-item>
|
</ha-list-item>
|
||||||
|
<li divider role="separator"></li>
|
||||||
|
${processedBlueprints.map(
|
||||||
|
(blueprint) => html`
|
||||||
|
<ha-list-item
|
||||||
|
hasmeta
|
||||||
|
twoline
|
||||||
|
graphic="icon"
|
||||||
|
@request-selected=${this._blueprint}
|
||||||
|
.path=${blueprint.path}
|
||||||
|
>
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${SOURCE_TYPE_ICONS[blueprint.sourceType]}
|
||||||
|
></ha-svg-icon>
|
||||||
|
${blueprint.name}
|
||||||
|
<span slot="secondary">
|
||||||
|
${blueprint.author
|
||||||
|
? this.hass.localize(
|
||||||
|
`ui.panel.config.automation.dialog_new.blueprint_source.author`,
|
||||||
|
{ author: blueprint.author }
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
|
`ui.panel.config.automation.dialog_new.blueprint_source.${blueprint.sourceType}`
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<ha-icon-next slot="meta"></ha-icon-next>
|
||||||
|
</ha-list-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
${processedBlueprints.length === 0
|
||||||
|
? html`
|
||||||
|
<a
|
||||||
|
href=${documentationUrl(this.hass, "/get-blueprints")}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
class="item"
|
||||||
|
>
|
||||||
|
<ha-list-item hasmeta twoline graphic="icon">
|
||||||
|
<ha-svg-icon slot="graphic" .path=${mdiWeb}></ha-svg-icon>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.dialog_new.create_blueprint"
|
||||||
|
)}
|
||||||
|
<span slot="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.dialog_new.create_blueprint_description"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<ha-svg-icon slot="meta" path=${mdiOpenInNew}></ha-svg-icon>
|
||||||
|
</ha-list-item>
|
||||||
|
</a>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<ha-tip>
|
||||||
|
<a
|
||||||
|
href=${documentationUrl(this.hass, "/get-blueprints")}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.dialog_new.discover_blueprint_tip"
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</ha-tip>
|
||||||
|
`}
|
||||||
</mwc-list>
|
</mwc-list>
|
||||||
</ha-dialog>
|
</ha-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _blueprintPicked(ev: CustomEvent) {
|
private async _blueprint(ev) {
|
||||||
|
if (!shouldHandleRequestSelectedEvent(ev)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const path = (ev.currentTarget! as any).path;
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
showAutomationEditor({ use_blueprint: { path: ev.detail.value } });
|
showAutomationEditor({ use_blueprint: { path } });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _blueprint() {
|
private async _blank(ev) {
|
||||||
this.shadowRoot!.querySelector("ha-blueprint-picker")!.open();
|
if (!shouldHandleRequestSelectedEvent(ev)) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
private async _blank() {
|
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
showAutomationEditor();
|
showAutomationEditor();
|
||||||
}
|
}
|
||||||
@ -92,14 +212,24 @@ class DialogNewAutomation extends LitElement implements HassDialog {
|
|||||||
haStyle,
|
haStyle,
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
mwc-list-item.blueprint {
|
|
||||||
height: 110px;
|
|
||||||
}
|
|
||||||
ha-blueprint-picker {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
--dialog-content-padding: 0;
|
--dialog-content-padding: 0;
|
||||||
|
--mdc-dialog-max-height: 60vh;
|
||||||
|
}
|
||||||
|
@media all and (min-width: 550px) {
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-min-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ha-icon-next {
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
ha-tip {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
a.item {
|
||||||
|
text-decoration: unset;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -1931,19 +1931,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dialog_new": {
|
"dialog_new": {
|
||||||
"header": "Create a new automation",
|
"header": "Create automation",
|
||||||
"how": "How do you want to create your new automation?",
|
"create_empty": "Create new automation",
|
||||||
"blueprint": {
|
"create_empty_description": "Start with an empty automation from scratch",
|
||||||
"use_blueprint": "Use a blueprint"
|
"create_blueprint": "Create from blueprint",
|
||||||
|
"create_blueprint_description": "Discover community blueprints",
|
||||||
|
"blueprint_source": {
|
||||||
|
"author": "By {author}",
|
||||||
|
"local": "By you",
|
||||||
|
"community": "By the community",
|
||||||
|
"homeassistant": "By Home Assistant"
|
||||||
},
|
},
|
||||||
"thingtalk": {
|
"discover_blueprint_tip": "Discover more community blueprints"
|
||||||
"header": "Describe the automation you want to create",
|
|
||||||
"intro": "And we will try to create it for you. For example: Turn the lights off when I leave.",
|
|
||||||
"input_label": "What should this automation do?",
|
|
||||||
"create": "Create"
|
|
||||||
},
|
|
||||||
"start_empty": "Start with an empty automation",
|
|
||||||
"start_empty_description": "Create a new automation from scratch"
|
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
"enable": "[%key:ui::common::enable%]",
|
"enable": "[%key:ui::common::enable%]",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user