mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Update Automation Picker Table (#13405)
This commit is contained in:
parent
ab14cf9e9b
commit
c82782fa1b
@ -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,
|
||||||
|
@ -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")) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user