mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-12 11:56:34 +00:00
Show triggered in automation editor (#11771)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
1e6f402d0f
commit
f5b5414461
@ -11,7 +11,7 @@ export const debounce = <T extends any[]>(
|
||||
immediate = false
|
||||
) => {
|
||||
let timeout: number | undefined;
|
||||
return (...args: T): void => {
|
||||
const debouncedFunc = (...args: T): void => {
|
||||
const later = () => {
|
||||
timeout = undefined;
|
||||
if (!immediate) {
|
||||
@ -25,4 +25,8 @@ export const debounce = <T extends any[]>(
|
||||
func(...args);
|
||||
}
|
||||
};
|
||||
debouncedFunc.cancel = () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
return debouncedFunc;
|
||||
};
|
||||
|
19
src/data/config.ts
Normal file
19
src/data/config.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
interface ValidationResult {
|
||||
valid: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
type ValidKeys = "trigger" | "action" | "condition";
|
||||
|
||||
export const validateConfig = <
|
||||
T extends Partial<{ [key in ValidKeys]: unknown }>
|
||||
>(
|
||||
hass: HomeAssistant,
|
||||
config: T
|
||||
): Promise<Record<keyof T, ValidationResult>> =>
|
||||
hass.callWS({
|
||||
type: "validate_config",
|
||||
...config,
|
||||
});
|
@ -1,11 +1,13 @@
|
||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { mdiDotsVertical } from "@mdi/js";
|
||||
import "@material/mwc-select";
|
||||
import type { Select } from "@material/mwc-select";
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { stringCompare } from "../../../../common/string/compare";
|
||||
@ -16,7 +18,7 @@ import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-alert";
|
||||
import "../../../../components/ha-textfield";
|
||||
import "../../../../components/ha-icon-button";
|
||||
import type { Trigger } from "../../../../data/automation";
|
||||
import { subscribeTrigger, Trigger } from "../../../../data/automation";
|
||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
@ -34,6 +36,8 @@ import "./types/ha-automation-trigger-time";
|
||||
import "./types/ha-automation-trigger-time_pattern";
|
||||
import "./types/ha-automation-trigger-webhook";
|
||||
import "./types/ha-automation-trigger-zone";
|
||||
import { debounce } from "../../../../common/util/debounce";
|
||||
import { validateConfig } from "../../../../data/config";
|
||||
|
||||
const OPTIONS = [
|
||||
"device",
|
||||
@ -90,6 +94,12 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
|
||||
@state() private _requestShowId = false;
|
||||
|
||||
@state() private _triggered = false;
|
||||
|
||||
@state() private _triggerColor = false;
|
||||
|
||||
private _triggerUnsub?: Promise<UnsubscribeFunc>;
|
||||
|
||||
private _processedTypes = memoizeOne(
|
||||
(localize: LocalizeFunc): [string, string][] =>
|
||||
OPTIONS.map(
|
||||
@ -219,10 +229,98 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
<div
|
||||
class="triggered ${classMap({
|
||||
active: this._triggered,
|
||||
accent: this._triggerColor,
|
||||
})}"
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.triggered"
|
||||
)}
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
protected override updated(changedProps: PropertyValues): void {
|
||||
super.updated(changedProps);
|
||||
if (changedProps.has("trigger")) {
|
||||
this._subscribeTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (this.hasUpdated && this.trigger) {
|
||||
this._subscribeTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
if (this._triggerUnsub) {
|
||||
this._triggerUnsub.then((unsub) => unsub());
|
||||
this._triggerUnsub = undefined;
|
||||
}
|
||||
this._doSubscribeTrigger.cancel();
|
||||
}
|
||||
|
||||
private _subscribeTrigger() {
|
||||
// Clean up old trigger subscription.
|
||||
if (this._triggerUnsub) {
|
||||
this._triggerUnsub.then((unsub) => unsub());
|
||||
this._triggerUnsub = undefined;
|
||||
}
|
||||
|
||||
this._doSubscribeTrigger();
|
||||
}
|
||||
|
||||
private _doSubscribeTrigger = debounce(async () => {
|
||||
let untriggerTimeout: number | undefined;
|
||||
const showTriggeredTime = 5000;
|
||||
const trigger = this.trigger;
|
||||
|
||||
// Clean up old trigger subscription.
|
||||
if (this._triggerUnsub) {
|
||||
this._triggerUnsub.then((unsub) => unsub());
|
||||
this._triggerUnsub = undefined;
|
||||
}
|
||||
|
||||
const validateResult = await validateConfig(this.hass, {
|
||||
trigger: this.trigger,
|
||||
});
|
||||
|
||||
// Don't do anything if trigger not valid or if trigger changed.
|
||||
if (!validateResult.trigger.valid || this.trigger !== trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerUnsub = subscribeTrigger(
|
||||
this.hass,
|
||||
() => {
|
||||
if (untriggerTimeout !== undefined) {
|
||||
clearTimeout(untriggerTimeout);
|
||||
this._triggerColor = !this._triggerColor;
|
||||
} else {
|
||||
this._triggerColor = false;
|
||||
}
|
||||
this._triggered = true;
|
||||
untriggerTimeout = window.setTimeout(() => {
|
||||
this._triggered = false;
|
||||
untriggerTimeout = undefined;
|
||||
}, showTriggeredTime);
|
||||
},
|
||||
trigger
|
||||
);
|
||||
triggerUnsub.catch(() => {
|
||||
if (this._triggerUnsub === triggerUnsub) {
|
||||
this._triggerUnsub = undefined;
|
||||
}
|
||||
});
|
||||
this._triggerUnsub = triggerUnsub;
|
||||
}, 5000);
|
||||
|
||||
private _handleUiModeNotAvailable(ev: CustomEvent) {
|
||||
this._warnings = handleStructError(this.hass, ev.detail).warnings;
|
||||
if (!this._yamlMode) {
|
||||
@ -327,6 +425,31 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
z-index: 3;
|
||||
--mdc-theme-text-primary-on-background: var(--primary-text-color);
|
||||
}
|
||||
.triggered {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
text-transform: uppercase;
|
||||
pointer-events: none;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--text-primary-color);
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s;
|
||||
text-align: center;
|
||||
border-top-right-radius: var(--ha-card-border-radius, 4px);
|
||||
border-top-left-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
.triggered.active {
|
||||
max-height: 100px;
|
||||
}
|
||||
.triggered.accent {
|
||||
background-color: var(--accent-color);
|
||||
color: var(--text-accent-color, var(--text-primary-color));
|
||||
}
|
||||
.rtl .card-menu {
|
||||
float: left;
|
||||
}
|
||||
|
@ -1623,6 +1623,7 @@
|
||||
"header": "Triggers",
|
||||
"introduction": "Triggers are what starts the processing of an automation rule. It is possible to specify multiple triggers for the same rule. Once a trigger starts, Home Assistant will validate the conditions, if any, and call the action.",
|
||||
"learn_more": "Learn more about triggers",
|
||||
"triggered": "Triggered",
|
||||
"add": "Add trigger",
|
||||
"id": "Trigger ID",
|
||||
"edit_id": "Edit trigger ID",
|
||||
|
Loading…
x
Reference in New Issue
Block a user