Update Automation Picker Table (#13405)

This commit is contained in:
Zack Barett 2022-08-23 08:47:15 -05:00 committed by GitHub
parent ab14cf9e9b
commit c82782fa1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 139 deletions

View File

@ -1,7 +1,7 @@
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { FrontendLocaleData } from "../../data/translation"; import { FrontendLocaleData } from "../../data/translation";
import { useAmPm } from "./use_am_pm";
import { polyfillsLoaded } from "../translations/localize"; import { polyfillsLoaded } from "../translations/localize";
import { useAmPm } from "./use_am_pm";
if (__BUILD__ === "latest" && polyfillsLoaded) { if (__BUILD__ === "latest" && polyfillsLoaded) {
await polyfillsLoaded; await polyfillsLoaded;
@ -28,6 +28,28 @@ const formatDateTimeMem = memoizeOne(
) )
); );
// Aug 9, 8:23 AM
export const formatShortDateTime = (
dateObj: Date,
locale: FrontendLocaleData
) => formatShortDateTimeMem(locale).format(dateObj);
const formatShortDateTimeMem = memoizeOne(
(locale: FrontendLocaleData) =>
new Intl.DateTimeFormat(
locale.language === "en" && !useAmPm(locale)
? "en-u-hc-h23"
: locale.language,
{
month: "short",
day: "numeric",
hour: useAmPm(locale) ? "numeric" : "2-digit",
minute: "2-digit",
hour12: useAmPm(locale),
}
)
);
// August 9, 2021, 8:23:15 AM // August 9, 2021, 8:23:15 AM
export const formatDateTimeWithSeconds = ( export const formatDateTimeWithSeconds = (
dateObj: Date, dateObj: Date,

View File

@ -1,32 +1,22 @@
import { import { mdiHelpCircle, mdiInformationOutline, mdiPlus } from "@mdi/js";
mdiHelpCircle,
mdiHistory,
mdiInformationOutline,
mdiPencil,
mdiPencilOff,
mdiPlayCircleOutline,
mdiPlus,
} from "@mdi/js";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { 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 memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { formatDateTime } from "../../../common/datetime/format_date_time"; import { formatShortDateTime } from "../../../common/datetime/format_date_time";
import { fireEvent } from "../../../common/dom/fire_event"; import { relativeTime } from "../../../common/datetime/relative_time";
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { navigate } from "../../../common/navigate"; import { navigate } from "../../../common/navigate";
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table"; import type {
import "../../../components/entity/ha-entity-toggle"; DataTableColumnContainer,
RowClickedEvent,
} from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu"; import "../../../components/ha-button-related-filter-menu";
import "../../../components/ha-fab"; import "../../../components/ha-fab";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-icon-overflow-menu"; import type { AutomationEntity } from "../../../data/automation";
import {
AutomationEntity,
triggerAutomationActions,
} from "../../../data/automation";
import { UNAVAILABLE_STATES } from "../../../data/entity";
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
import "../../../layouts/hass-tabs-subpage-data-table"; import "../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
@ -35,6 +25,8 @@ import { documentationUrl } from "../../../util/documentation-url";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import { showNewAutomationDialog } from "./show-dialog-new-automation"; import { showNewAutomationDialog } from "./show-dialog-new-automation";
const DAY_IN_MILLISECONDS = 86400000;
@customElement("ha-automation-picker") @customElement("ha-automation-picker")
class HaAutomationPicker extends LitElement { class HaAutomationPicker extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -78,20 +70,6 @@ class HaAutomationPicker extends LitElement {
private _columns = memoizeOne( private _columns = memoizeOne(
(narrow: boolean, _locale): DataTableColumnContainer => { (narrow: boolean, _locale): DataTableColumnContainer => {
const columns: DataTableColumnContainer = { const columns: DataTableColumnContainer = {
toggle: {
title: "",
label: this.hass.localize(
"ui.panel.config.automation.picker.headers.toggle"
),
type: "icon",
template: (_toggle, automation: any) =>
html`
<ha-entity-toggle
.hass=${this.hass}
.stateObj=${automation}
></ha-entity-toggle>
`,
},
name: { name: {
title: this.hass.localize( title: this.hass.localize(
"ui.panel.config.automation.picker.headers.name" "ui.panel.config.automation.picker.headers.name"
@ -101,19 +79,25 @@ class HaAutomationPicker extends LitElement {
direction: "asc", direction: "asc",
grows: true, grows: true,
template: narrow template: narrow
? (name, automation: any) => ? (name, automation: any) => {
html` const date = new Date(automation.attributes.last_triggered);
const now = new Date();
const diff = now.getTime() - date.getTime();
const dayDiff = diff / DAY_IN_MILLISECONDS;
return html`
${name} ${name}
<div class="secondary"> <div class="secondary">
${this.hass.localize("ui.card.automation.last_triggered")}: ${this.hass.localize("ui.card.automation.last_triggered")}:
${automation.attributes.last_triggered ${automation.attributes.last_triggered
? formatDateTime( ? dayDiff > 3
new Date(automation.attributes.last_triggered), ? formatShortDateTime(date, this.hass.locale)
this.hass.locale : relativeTime(date, this.hass.locale)
)
: this.hass.localize("ui.components.relative_time.never")} : this.hass.localize("ui.components.relative_time.never")}
</div> </div>
` `;
}
: undefined, : undefined,
}, },
}; };
@ -122,31 +106,21 @@ class HaAutomationPicker extends LitElement {
sortable: true, sortable: true,
width: "20%", width: "20%",
title: this.hass.localize("ui.card.automation.last_triggered"), title: this.hass.localize("ui.card.automation.last_triggered"),
template: (last_triggered) => html` template: (last_triggered) => {
${last_triggered const date = new Date(last_triggered);
? formatDateTime(new Date(last_triggered), this.hass.locale) const now = new Date();
: this.hass.localize("ui.components.relative_time.never")}
`, const diff = now.getTime() - date.getTime();
}; const dayDiff = diff / DAY_IN_MILLISECONDS;
columns.trigger = {
label: this.hass.localize( return html`
"ui.panel.config.automation.picker.headers.trigger" ${last_triggered
), ? dayDiff > 3
title: html` ? formatShortDateTime(date, this.hass.locale)
<mwc-button style="visibility: hidden"> : relativeTime(date, this.hass.locale)
${this.hass.localize("ui.card.automation.trigger")} : this.hass.localize("ui.components.relative_time.never")}
</mwc-button> `;
`, },
width: "20%",
template: (_info, automation: any) => html`
<mwc-button
.automation=${automation}
@click=${this._triggerRunActions}
.disabled=${UNAVAILABLE_STATES.includes(automation.state)}
>
${this.hass.localize("ui.card.automation.trigger")}
</mwc-button>
`,
}; };
} }
columns.actions = { columns.actions = {
@ -154,71 +128,16 @@ class HaAutomationPicker extends LitElement {
label: this.hass.localize( label: this.hass.localize(
"ui.panel.config.automation.picker.headers.actions" "ui.panel.config.automation.picker.headers.actions"
), ),
type: "overflow-menu", type: "icon-button",
template: (_info, automation: any) => html` template: (_info, automation: any) => html`
<ha-icon-overflow-menu <ha-icon-button
.hass=${this.hass} .automation=${automation}
.narrow=${this.narrow} .label=${this.hass.localize(
.items=${[ "ui.panel.config.automation.picker.headers.actions"
// Info Button )}
{ .path=${mdiInformationOutline}
path: mdiInformationOutline, @click=${this._showInfo}
label: this.hass.localize( ></ha-icon-button>
"ui.panel.config.automation.picker.show_info_automation"
),
action: () => this._showInfo(automation),
},
// Trigger Button
{
path: mdiPlayCircleOutline,
label: this.hass.localize("ui.card.automation.trigger"),
narrowOnly: true,
action: () => this._runActions(automation),
},
// Trace Button
{
path: mdiHistory,
disabled: !automation.attributes.id,
label: this.hass.localize(
"ui.panel.config.automation.picker.dev_automation"
),
tooltip: !automation.attributes.id
? this.hass.localize(
"ui.panel.config.automation.picker.dev_only_editable"
)
: "",
action: () => {
if (automation.attributes.id) {
navigate(
`/config/automation/trace/${automation.attributes.id}`
);
}
},
},
// Edit Button
{
path: automation.attributes.id ? mdiPencil : mdiPencilOff,
disabled: !automation.attributes.id,
label: this.hass.localize(
"ui.panel.config.automation.picker.edit_automation"
),
tooltip: !automation.attributes.id
? this.hass.localize(
"ui.panel.config.automation.picker.dev_only_editable"
)
: "",
action: () => {
if (automation.attributes.id) {
navigate(
`/config/automation/edit/${automation.attributes.id}`
);
}
},
},
]}
style="color: var(--secondary-text-color)"
>
</ha-icon-overflow-menu>
`, `,
}; };
return columns; return columns;
@ -237,11 +156,13 @@ class HaAutomationPicker extends LitElement {
.activeFilters=${this._activeFilters} .activeFilters=${this._activeFilters}
.columns=${this._columns(this.narrow, this.hass.locale)} .columns=${this._columns(this.narrow, this.hass.locale)}
.data=${this._automations(this.automations, this._filteredAutomations)} .data=${this._automations(this.automations, this._filteredAutomations)}
@row-click=${this._handleRowClicked}
.noDataText=${this.hass.localize( .noDataText=${this.hass.localize(
"ui.panel.config.automation.picker.no_automations" "ui.panel.config.automation.picker.no_automations"
)} )}
@clear-filter=${this._clearFilter} @clear-filter=${this._clearFilter}
hasFab hasFab
clickable
> >
<ha-icon-button <ha-icon-button
slot="toolbar-icon" slot="toolbar-icon"
@ -289,9 +210,10 @@ class HaAutomationPicker extends LitElement {
this._filterValue = undefined; this._filterValue = undefined;
} }
private _showInfo(automation: AutomationEntity) { private _showInfo(ev) {
const entityId = automation.entity_id; ev.stopPropagation();
fireEvent(this, "hass-more-info", { entityId }); const automation = ev.currentTarget.automation;
fireEvent(this, "hass-more-info", { entityId: automation.entity_id });
} }
private _showHelp() { private _showHelp() {
@ -314,13 +236,15 @@ class HaAutomationPicker extends LitElement {
}); });
} }
private _triggerRunActions = (ev) => { private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
this._runActions(ev.currentTarget.automation); const automation = this.automations.find(
}; (a) => a.entity_id === ev.detail.id
);
private _runActions = (automation: AutomationEntity) => { if (automation?.attributes.id) {
triggerAutomationActions(this.hass, automation.entity_id); navigate(`/config/automation/edit/${automation?.attributes.id}`);
}; }
}
private _createNew() { private _createNew() {
if (isComponentLoaded(this.hass, "blueprint")) { if (isComponentLoaded(this.hass, "blueprint")) {