mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-08 18:39:40 +00:00
Add date card feature (#26531)
* Add date card feature * Rename from "date" to "date-set" * Better label * Fix * Parse date for datetime
This commit is contained in:
143
src/panels/lovelace/card-features/hui-date-set-card-feature.ts
Normal file
143
src/panels/lovelace/card-features/hui-date-set-card-feature.ts
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import { html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import "../../../components/ha-control-slider";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import type { LovelaceCardFeature } from "../types";
|
||||||
|
import { cardFeatureStyles } from "./common/card-feature-styles";
|
||||||
|
import type {
|
||||||
|
LovelaceCardFeatureContext,
|
||||||
|
DateSetCardFeatureConfig,
|
||||||
|
} from "./types";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import type { DatePickerDialogParams } from "../../../components/ha-date-input";
|
||||||
|
import { firstWeekdayIndex } from "../../../common/datetime/first_weekday";
|
||||||
|
import "../../../components/ha-control-button";
|
||||||
|
import "../../../components/ha-control-button-group";
|
||||||
|
|
||||||
|
const loadDatePickerDialog = () =>
|
||||||
|
import("../../../components/ha-dialog-date-picker");
|
||||||
|
|
||||||
|
export const supportsDateSetCardFeature = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
context: LovelaceCardFeatureContext
|
||||||
|
) => {
|
||||||
|
const stateObj = context.entity_id
|
||||||
|
? hass.states[context.entity_id]
|
||||||
|
: undefined;
|
||||||
|
if (!stateObj) return false;
|
||||||
|
const domain = computeDomain(stateObj.entity_id);
|
||||||
|
return (
|
||||||
|
(domain === "input_datetime" && stateObj.attributes.has_date) ||
|
||||||
|
["datetime", "date"].includes(domain)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("hui-date-set-card-feature")
|
||||||
|
class HuiDateSetCardFeature extends LitElement implements LovelaceCardFeature {
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public color?: string;
|
||||||
|
|
||||||
|
@state() private _config?: DateSetCardFeatureConfig;
|
||||||
|
|
||||||
|
private get _stateObj() {
|
||||||
|
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this.hass.states[this.context.entity_id!] ?? undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _pressButton() {
|
||||||
|
if (!this.hass || !this._stateObj) return;
|
||||||
|
|
||||||
|
const dialogParams: DatePickerDialogParams = {
|
||||||
|
min: "1970-01-01",
|
||||||
|
value: this._stateObj.state,
|
||||||
|
onChange: (value) => this._dateChanged(value),
|
||||||
|
locale: this.hass.locale.language,
|
||||||
|
firstWeekday: firstWeekdayIndex(this.hass.locale),
|
||||||
|
};
|
||||||
|
|
||||||
|
fireEvent(this, "show-dialog", {
|
||||||
|
dialogTag: "ha-dialog-date-picker",
|
||||||
|
dialogImport: loadDatePickerDialog,
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dateChanged(value: string | undefined) {
|
||||||
|
if (!this.hass || !this._stateObj || !value) return;
|
||||||
|
|
||||||
|
const domain = computeDomain(this._stateObj.entity_id);
|
||||||
|
const service = domain === "input_datetime" ? "set_datetime" : "set_value";
|
||||||
|
|
||||||
|
// datetime requires a full datetime string
|
||||||
|
if (domain === "datetime") {
|
||||||
|
const dateObj = new Date(this._stateObj.state);
|
||||||
|
const selectedDate = new Date(`${value}T00:00:00`);
|
||||||
|
dateObj.setFullYear(
|
||||||
|
selectedDate.getFullYear(),
|
||||||
|
selectedDate.getMonth(),
|
||||||
|
selectedDate.getDate()
|
||||||
|
);
|
||||||
|
|
||||||
|
this.hass.callService(domain, service, {
|
||||||
|
entity_id: this._stateObj.entity_id,
|
||||||
|
datetime: dateObj.toISOString(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.hass.callService(domain, service, {
|
||||||
|
entity_id: this._stateObj.entity_id,
|
||||||
|
date: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getStubConfig(): DateSetCardFeatureConfig {
|
||||||
|
return {
|
||||||
|
type: "date-set",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setConfig(config: DateSetCardFeatureConfig): void {
|
||||||
|
if (!config) {
|
||||||
|
throw new Error("Invalid configuration");
|
||||||
|
}
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (
|
||||||
|
!this._config ||
|
||||||
|
!this.hass ||
|
||||||
|
!this.context ||
|
||||||
|
!this._stateObj ||
|
||||||
|
!supportsDateSetCardFeature(this.hass, this.context)
|
||||||
|
) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-control-button-group>
|
||||||
|
<ha-control-button
|
||||||
|
.disabled=${["unavailable", "unknown"].includes(this._stateObj.state)}
|
||||||
|
class="press-button"
|
||||||
|
@click=${this._pressButton}
|
||||||
|
>
|
||||||
|
${this.hass.localize("ui.card.date.set_date")}
|
||||||
|
</ha-control-button>
|
||||||
|
</ha-control-button-group>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = cardFeatureStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-date-set-card-feature": HuiDateSetCardFeature;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,6 +101,10 @@ export interface CounterActionsCardFeatureConfig {
|
|||||||
actions?: CounterActions[];
|
actions?: CounterActions[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DateSetCardFeatureConfig {
|
||||||
|
type: "date-set";
|
||||||
|
}
|
||||||
|
|
||||||
export interface SelectOptionsCardFeatureConfig {
|
export interface SelectOptionsCardFeatureConfig {
|
||||||
type: "select-options";
|
type: "select-options";
|
||||||
options?: string[];
|
options?: string[];
|
||||||
@@ -213,6 +217,7 @@ export type LovelaceCardFeatureConfig =
|
|||||||
| CoverPositionCardFeatureConfig
|
| CoverPositionCardFeatureConfig
|
||||||
| CoverTiltPositionCardFeatureConfig
|
| CoverTiltPositionCardFeatureConfig
|
||||||
| CoverTiltCardFeatureConfig
|
| CoverTiltCardFeatureConfig
|
||||||
|
| DateSetCardFeatureConfig
|
||||||
| FanDirectionCardFeatureConfig
|
| FanDirectionCardFeatureConfig
|
||||||
| FanPresetModesCardFeatureConfig
|
| FanPresetModesCardFeatureConfig
|
||||||
| FanSpeedCardFeatureConfig
|
| FanSpeedCardFeatureConfig
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import "../card-features/hui-cover-open-close-card-feature";
|
|||||||
import "../card-features/hui-cover-position-card-feature";
|
import "../card-features/hui-cover-position-card-feature";
|
||||||
import "../card-features/hui-cover-tilt-card-feature";
|
import "../card-features/hui-cover-tilt-card-feature";
|
||||||
import "../card-features/hui-cover-tilt-position-card-feature";
|
import "../card-features/hui-cover-tilt-position-card-feature";
|
||||||
|
import "../card-features/hui-date-set-card-feature";
|
||||||
import "../card-features/hui-fan-direction-card-feature";
|
import "../card-features/hui-fan-direction-card-feature";
|
||||||
import "../card-features/hui-fan-preset-modes-card-feature";
|
import "../card-features/hui-fan-preset-modes-card-feature";
|
||||||
import "../card-features/hui-fan-speed-card-feature";
|
import "../card-features/hui-fan-speed-card-feature";
|
||||||
@@ -53,6 +54,7 @@ const TYPES = new Set<LovelaceCardFeatureConfig["type"]>([
|
|||||||
"cover-position",
|
"cover-position",
|
||||||
"cover-tilt-position",
|
"cover-tilt-position",
|
||||||
"cover-tilt",
|
"cover-tilt",
|
||||||
|
"date-set",
|
||||||
"fan-direction",
|
"fan-direction",
|
||||||
"fan-preset-modes",
|
"fan-preset-modes",
|
||||||
"fan-speed",
|
"fan-speed",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { supportsCoverOpenCloseCardFeature } from "../../card-features/hui-cover
|
|||||||
import { supportsCoverPositionCardFeature } from "../../card-features/hui-cover-position-card-feature";
|
import { supportsCoverPositionCardFeature } from "../../card-features/hui-cover-position-card-feature";
|
||||||
import { supportsCoverTiltCardFeature } from "../../card-features/hui-cover-tilt-card-feature";
|
import { supportsCoverTiltCardFeature } from "../../card-features/hui-cover-tilt-card-feature";
|
||||||
import { supportsCoverTiltPositionCardFeature } from "../../card-features/hui-cover-tilt-position-card-feature";
|
import { supportsCoverTiltPositionCardFeature } from "../../card-features/hui-cover-tilt-position-card-feature";
|
||||||
|
import { supportsDateSetCardFeature } from "../../card-features/hui-date-set-card-feature";
|
||||||
import { supportsFanDirectionCardFeature } from "../../card-features/hui-fan-direction-card-feature";
|
import { supportsFanDirectionCardFeature } from "../../card-features/hui-fan-direction-card-feature";
|
||||||
import { supportsFanPresetModesCardFeature } from "../../card-features/hui-fan-preset-modes-card-feature";
|
import { supportsFanPresetModesCardFeature } from "../../card-features/hui-fan-preset-modes-card-feature";
|
||||||
import { supportsFanSpeedCardFeature } from "../../card-features/hui-fan-speed-card-feature";
|
import { supportsFanSpeedCardFeature } from "../../card-features/hui-fan-speed-card-feature";
|
||||||
@@ -78,6 +79,7 @@ const UI_FEATURE_TYPES = [
|
|||||||
"cover-position",
|
"cover-position",
|
||||||
"cover-tilt-position",
|
"cover-tilt-position",
|
||||||
"cover-tilt",
|
"cover-tilt",
|
||||||
|
"date-set",
|
||||||
"fan-direction",
|
"fan-direction",
|
||||||
"fan-preset-modes",
|
"fan-preset-modes",
|
||||||
"fan-speed",
|
"fan-speed",
|
||||||
@@ -141,6 +143,7 @@ const SUPPORTS_FEATURE_TYPES: Record<
|
|||||||
"cover-position": supportsCoverPositionCardFeature,
|
"cover-position": supportsCoverPositionCardFeature,
|
||||||
"cover-tilt-position": supportsCoverTiltPositionCardFeature,
|
"cover-tilt-position": supportsCoverTiltPositionCardFeature,
|
||||||
"cover-tilt": supportsCoverTiltCardFeature,
|
"cover-tilt": supportsCoverTiltCardFeature,
|
||||||
|
"date-set": supportsDateSetCardFeature,
|
||||||
"fan-direction": supportsFanDirectionCardFeature,
|
"fan-direction": supportsFanDirectionCardFeature,
|
||||||
"fan-preset-modes": supportsFanPresetModesCardFeature,
|
"fan-preset-modes": supportsFanPresetModesCardFeature,
|
||||||
"fan-speed": supportsFanSpeedCardFeature,
|
"fan-speed": supportsFanSpeedCardFeature,
|
||||||
|
|||||||
@@ -147,6 +147,9 @@
|
|||||||
"close_tilt_cover": "Close cover tilt",
|
"close_tilt_cover": "Close cover tilt",
|
||||||
"stop_cover": "Stop cover"
|
"stop_cover": "Stop cover"
|
||||||
},
|
},
|
||||||
|
"date": {
|
||||||
|
"set_date": "Set date"
|
||||||
|
},
|
||||||
"fan": {
|
"fan": {
|
||||||
"preset_mode": "Preset mode",
|
"preset_mode": "Preset mode",
|
||||||
"oscillate": "Oscillate",
|
"oscillate": "Oscillate",
|
||||||
@@ -7861,6 +7864,9 @@
|
|||||||
"cover-tilt-position": {
|
"cover-tilt-position": {
|
||||||
"label": "Cover tilt position"
|
"label": "Cover tilt position"
|
||||||
},
|
},
|
||||||
|
"date-set": {
|
||||||
|
"label": "Set date"
|
||||||
|
},
|
||||||
"fan-direction": {
|
"fan-direction": {
|
||||||
"label": "Fan direction"
|
"label": "Fan direction"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user