Add empty page to automation/script/scene config (#19075)

This commit is contained in:
Bram Kragten 2023-12-18 13:59:36 +01:00 committed by GitHub
parent 3e7fa66790
commit 45b7ebbe46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 205 additions and 54 deletions

View File

@ -124,6 +124,12 @@ export class HaTabsSubpageDataTable extends LitElement {
*/
@property({ type: String }) public noDataText?: string;
/**
* Hides the data table and show an empty message.
* @type {Boolean}
*/
@property({ type: Boolean }) public empty = false;
@property() public route!: Route;
/**
@ -198,56 +204,61 @@ export class HaTabsSubpageDataTable extends LitElement {
.mainPage=${this.mainPage}
.supervisor=${this.supervisor}
>
${!this.hideFilterMenu
? html`
<div slot="toolbar-icon">
${this.narrow
${this.empty
? html`<div class="center">
<slot name="empty">${this.noDataText}</slot>
</div>`
: html`${!this.hideFilterMenu
? html`
<div slot="toolbar-icon">
${this.narrow
? html`
<div class="filter-menu">
${this.numHidden || this.activeFilters
? html`<span class="badge"
>${this.numHidden || "!"}</span
>`
: ""}
<slot name="filter-menu"></slot>
</div>
`
: ""}<slot name="toolbar-icon"></slot>
</div>
`
: ""}
${this.narrow
? html`
<div slot="header">
<slot name="header">
<div class="search-toolbar">${headerToolbar}</div>
</slot>
</div>
`
: ""}
<ha-data-table
.hass=${this.hass}
.columns=${this.columns}
.data=${this.data}
.noDataText=${this.noDataText}
.filter=${this.filter}
.selectable=${this.selectable}
.hasFab=${this.hasFab}
.id=${this.id}
.dir=${computeRTLDirection(this.hass)}
.clickable=${this.clickable}
.appendRow=${this.appendRow}
>
${!this.narrow
? html`
<div class="filter-menu">
${this.numHidden || this.activeFilters
? html`<span class="badge"
>${this.numHidden || "!"}</span
>`
: ""}
<slot name="filter-menu"></slot>
<div slot="header">
<slot name="header">
<div class="table-header">${headerToolbar}</div>
</slot>
</div>
`
: ""}<slot name="toolbar-icon"></slot>
</div>
`
: ""}
${this.narrow
? html`
<div slot="header">
<slot name="header">
<div class="search-toolbar">${headerToolbar}</div>
</slot>
</div>
`
: ""}
<ha-data-table
.hass=${this.hass}
.columns=${this.columns}
.data=${this.data}
.filter=${this.filter}
.selectable=${this.selectable}
.hasFab=${this.hasFab}
.id=${this.id}
.noDataText=${this.noDataText}
.dir=${computeRTLDirection(this.hass)}
.clickable=${this.clickable}
.appendRow=${this.appendRow}
>
${!this.narrow
? html`
<div slot="header">
<slot name="header">
<div class="table-header">${headerToolbar}</div>
</slot>
</div>
`
: html` <div slot="header"></div> `}
</ha-data-table>
: html` <div slot="header"></div> `}
</ha-data-table>`}
<div slot="fab"><slot name="fab"></slot></div>
</hass-tabs-subpage>
`;
@ -374,6 +385,16 @@ export class HaTabsSubpageDataTable extends LitElement {
.filter-menu {
position: relative;
}
.center {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
box-sizing: border-box;
height: 100%;
width: 100%;
padding: 16px;
}
`;
}
}

View File

@ -7,11 +7,19 @@ import {
mdiPlay,
mdiPlayCircleOutline,
mdiPlus,
mdiRobotHappy,
mdiStopCircleOutline,
mdiTransitConnection,
} from "@mdi/js";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import {
css,
CSSResultGroup,
html,
LitElement,
nothing,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { differenceInDays } from "date-fns/esm";
@ -295,6 +303,7 @@ class HaAutomationPicker extends LitElement {
.activeFilters=${this._activeFilters}
.columns=${this._columns(this.narrow, this.hass.locale)}
.data=${this._automations(this.automations, this._filteredAutomations)}
.empty=${!this.automations.length}
@row-click=${this._handleRowClicked}
.noDataText=${this.hass.localize(
"ui.panel.config.automation.picker.no_automations"
@ -318,6 +327,35 @@ class HaAutomationPicker extends LitElement {
@related-changed=${this._relatedFilterChanged}
>
</ha-button-related-filter-menu>
${!this.automations.length
? html` <div class="empty" slot="empty">
<ha-svg-icon .path=${mdiRobotHappy}></ha-svg-icon>
<h1>
${this.hass.localize(
"ui.panel.config.automation.picker.empty_header"
)}
</h1>
<p>
${this.hass.localize(
"ui.panel.config.automation.picker.empty_text_1"
)}<br />
${this.hass.localize(
"ui.panel.config.automation.picker.empty_text_2"
)}
</p>
<a
href=${documentationUrl(this.hass, "/docs/automation/editor/")}
target="_blank"
rel="noreferrer"
>
<ha-button>
${this.hass.localize(
"ui.panel.config.automation.picker.learn_more"
)}
</ha-button>
</a>
</div>`
: nothing}
<ha-fab
slot="fab"
.label=${this.hass.localize(
@ -505,7 +543,15 @@ class HaAutomationPicker extends LitElement {
}
static get styles(): CSSResultGroup {
return haStyle;
return [
haStyle,
css`
.empty {
--paper-font-headline_-_font-size: 28px;
--mdc-icon-size: 80px;
}
`,
];
}
}

View File

@ -3,12 +3,20 @@ import {
mdiDelete,
mdiHelpCircle,
mdiInformationOutline,
mdiPalette,
mdiPencilOff,
mdiPlay,
mdiPlus,
} from "@mdi/js";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import {
css,
CSSResultGroup,
html,
LitElement,
nothing,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { differenceInDays } from "date-fns/esm";
@ -21,6 +29,7 @@ import {
} from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu";
import "../../../components/ha-fab";
import "../../../components/ha-button";
import "../../../components/ha-icon-button";
import "../../../components/ha-state-icon";
import "../../../components/ha-svg-icon";
@ -214,6 +223,7 @@ class HaSceneDashboard extends LitElement {
.columns=${this._columns(this.hass.locale, this.narrow)}
id="entity_id"
.data=${this._scenes(this.scenes, this._filteredScenes)}
.empty=${!this.scenes.length}
.activeFilters=${this._activeFilters}
.noDataText=${this.hass.localize(
"ui.panel.config.scene.picker.no_scenes"
@ -238,6 +248,30 @@ class HaSceneDashboard extends LitElement {
@related-changed=${this._relatedFilterChanged}
>
</ha-button-related-filter-menu>
${!this.scenes.length
? html` <div class="empty" slot="empty">
<ha-svg-icon .path=${mdiPalette}></ha-svg-icon>
<h1>
${this.hass.localize(
"ui.panel.config.scene.picker.empty_header"
)}
</h1>
<p>
${this.hass.localize("ui.panel.config.scene.picker.empty_text")}
</p>
<a
href=${documentationUrl(this.hass, "/docs/scene/editor/")}
target="_blank"
rel="noreferrer"
>
<ha-button>
${this.hass.localize(
"ui.panel.config.scene.picker.learn_more"
)}
</ha-button>
</a>
</div>`
: nothing}
<a href="/config/scene/edit/new" slot="fab">
<ha-fab
.label=${this.hass.localize(
@ -350,6 +384,10 @@ class HaSceneDashboard extends LitElement {
a {
text-decoration: none;
}
.empty {
--paper-font-headline_-_font-size: 28px;
--mdc-icon-size: 80px;
}
`,
];
}

View File

@ -5,10 +5,18 @@ import {
mdiInformationOutline,
mdiPlay,
mdiPlus,
mdiScriptText,
mdiTransitConnection,
} from "@mdi/js";
import { differenceInDays } from "date-fns/esm";
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
import {
CSSResultGroup,
LitElement,
TemplateResult,
css,
html,
nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
@ -241,6 +249,7 @@ class HaScriptPicker extends LitElement {
.tabs=${configSections.automations}
.columns=${this._columns(this.narrow, this.hass.locale)}
.data=${this._scripts(this.scripts, this._filteredScripts)}
.empty=${!this.scripts.length}
.activeFilters=${this._activeFilters}
id="entity_id"
.noDataText=${this.hass.localize(
@ -266,6 +275,32 @@ class HaScriptPicker extends LitElement {
@related-changed=${this._relatedFilterChanged}
>
</ha-button-related-filter-menu>
${!this.scripts.length
? html` <div class="empty" slot="empty">
<ha-svg-icon .path=${mdiScriptText}></ha-svg-icon>
<h1>
${this.hass.localize(
"ui.panel.config.script.picker.empty_header"
)}
</h1>
<p>
${this.hass.localize(
"ui.panel.config.script.picker.empty_text"
)}
</p>
<a
href=${documentationUrl(this.hass, "/docs/script/editor/")}
target="_blank"
rel="noreferrer"
>
<ha-button>
${this.hass.localize(
"ui.panel.config.script.picker.learn_more"
)}
</ha-button>
</a>
</div>`
: nothing}
<ha-fab
slot="fab"
?is-wide=${this.isWide}
@ -471,6 +506,10 @@ class HaScriptPicker extends LitElement {
a {
text-decoration: none;
}
.empty {
--paper-font-headline_-_font-size: 28px;
--mdc-icon-size: 80px;
}
`,
];
}

View File

@ -2360,7 +2360,10 @@
"trigger": "Trigger",
"actions": "Actions",
"state": "State"
}
},
"empty_header": "Start automating",
"empty_text_1": "The automation editor is an easy way of creating and editing automations.",
"empty_text_2": "Even if you're new to home automation."
},
"dialog_new": {
"header": "Create automation",
@ -3059,7 +3062,9 @@
"state": "State"
},
"delete": "[%key:ui::common::delete%]",
"duplicate": "[%key:ui::common::duplicate%]"
"duplicate": "[%key:ui::common::duplicate%]",
"empty_header": "Create your first script",
"empty_text": "Scripts allow you to perform a sequence of actions."
},
"dialog_new": {
"header": "Create script",
@ -3159,7 +3164,9 @@
"state": "State",
"name": "Name",
"last_activated": "Last activated"
}
},
"empty_header": "Create your first scene",
"empty_text": "Scenes are an easy way to store and replicate the state of devices."
},
"editor": {
"default_name": "New scene",