From 45e6ec1ee22beb5409d1bc79829ce6433108eadc Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 5 Feb 2022 01:19:36 +0100 Subject: [PATCH] New date picker (#11555) --- package.json | 2 +- src/components/ha-date-input.ts | 157 ++++++------------ src/components/ha-dialog-date-picker.ts | 106 ++++++++++++ .../controls/more-info-input_datetime.ts | 1 + .../hui-input-datetime-entity-row.ts | 1 + yarn.lock | 124 +++++++++----- 6 files changed, 245 insertions(+), 146 deletions(-) create mode 100644 src/components/ha-dialog-date-picker.ts diff --git a/package.json b/package.json index 7b3bf4a01..d8d730097 100644 --- a/package.json +++ b/package.json @@ -89,13 +89,13 @@ "@polymer/polymer": "3.4.1", "@thomasloven/round-slider": "0.5.4", "@vaadin/combo-box": "^22.0.4", - "@vaadin/date-picker": "^22.0.4", "@vaadin/vaadin-themable-mixin": "^22.0.4", "@vibrant/color": "^3.2.1-alpha.1", "@vibrant/core": "^3.2.1-alpha.1", "@vibrant/quantizer-mmcq": "^3.2.1-alpha.1", "@vue/web-component-wrapper": "^1.2.0", "@webcomponents/webcomponentsjs": "^2.2.10", + "app-datepicker": "^5.0.1", "chart.js": "^3.3.2", "comlink": "^4.3.1", "core-js": "^3.15.2", diff --git a/src/components/ha-date-input.ts b/src/components/ha-date-input.ts index c83f5742c..08c259012 100644 --- a/src/components/ha-date-input.ts +++ b/src/components/ha-date-input.ts @@ -1,135 +1,76 @@ import { mdiCalendar } from "@mdi/js"; import "@polymer/paper-input/paper-input"; -import "@vaadin/date-picker/theme/material/vaadin-date-picker-light"; -import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import { css, CSSResultGroup, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import { formatDateNumeric } from "../common/datetime/format_date"; import { fireEvent } from "../common/dom/fire_event"; +import { HomeAssistant } from "../types"; import "./ha-svg-icon"; -const i18n = { - monthNames: [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ], - weekdays: [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - ], - weekdaysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - firstDayOfWeek: 0, - week: "Week", - calendar: "Calendar", - clear: "Clear", - today: "Today", - cancel: "Cancel", - formatTitle: (monthName, fullYear) => monthName + " " + fullYear, - formatDate: (d: { day: number; month: number; year: number }) => - [ - ("0000" + String(d.year)).slice(-4), - ("0" + String(d.month + 1)).slice(-2), - ("0" + String(d.day)).slice(-2), - ].join("-"), - parseDate: (text: string) => { - const parts = text.split("-"); - const today = new Date(); - let date; - let month = today.getMonth(); - let year = today.getFullYear(); - if (parts.length === 3) { - year = parseInt(parts[0]); - if (parts[0].length < 3 && year >= 0) { - year += year < 50 ? 2000 : 1900; - } - month = parseInt(parts[1]) - 1; - date = parseInt(parts[2]); - } else if (parts.length === 2) { - month = parseInt(parts[0]) - 1; - date = parseInt(parts[1]); - } else if (parts.length === 1) { - date = parseInt(parts[0]); - } +const loadDatePickerDialog = () => import("./ha-dialog-date-picker"); - if (date !== undefined) { - return { day: date, month, year }; - } - return undefined; - }, +export interface datePickerDialogParams { + value?: string; + min?: string; + max?: string; + locale?: string; + onChange: (value: string) => void; +} + +const showDatePickerDialog = ( + element: HTMLElement, + dialogParams: datePickerDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "ha-dialog-date-picker", + dialogImport: loadDatePickerDialog, + dialogParams, + }); }; @customElement("ha-date-input") export class HaDateInput extends LitElement { + @property({ attribute: false }) public locale!: HomeAssistant["locale"]; + @property() public value?: string; @property({ type: Boolean }) public disabled = false; @property() public label?: string; - @query("vaadin-date-picker-light", true) private _datePicker; - - private _inited = false; - - updated(changedProps: PropertyValues) { - if (changedProps.has("value")) { - this._datePicker.value = this.value; - this._inited = true; - } - } - render() { - return html` - - - - `; + + `; } - private _valueChanged(ev: CustomEvent) { - if ( - !this.value || - (this._inited && !this._compareStringDates(ev.detail.value, this.value)) - ) { - this.value = ev.detail.value; + private _openDialog() { + if (this.disabled) { + return; + } + showDatePickerDialog(this, { + min: "1970-01-01", + value: this.value, + onChange: (value) => this._valueChanged(value), + locale: this.locale.language, + }); + } + + private _valueChanged(value: string) { + if (this.value !== value) { + this.value = value; fireEvent(this, "change"); - fireEvent(this, "value-changed", { value: ev.detail.value }); + fireEvent(this, "value-changed", { value }); } } - private _compareStringDates(a: string, b: string): boolean { - const aParts = a.split("-"); - const bParts = b.split("-"); - let i = 0; - for (const aPart of aParts) { - if (Number(aPart) !== Number(bParts[i])) { - return false; - } - i++; - } - return true; - } - static get styles(): CSSResultGroup { return css` paper-input { diff --git a/src/components/ha-dialog-date-picker.ts b/src/components/ha-dialog-date-picker.ts new file mode 100644 index 000000000..2cb229db7 --- /dev/null +++ b/src/components/ha-dialog-date-picker.ts @@ -0,0 +1,106 @@ +import "@material/mwc-button/mwc-button"; +import "app-datepicker"; +import { css, html, LitElement } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../common/dom/fire_event"; +import { haStyleDialog } from "../resources/styles"; +import { datePickerDialogParams } from "./ha-date-input"; +import "./ha-dialog"; + +@customElement("ha-dialog-date-picker") +export class HaDialogDatePicker extends LitElement { + @property() public value?: string; + + @property({ type: Boolean }) public disabled = false; + + @property() public label?: string; + + @state() private _params?: datePickerDialogParams; + + @state() private _value?: string; + + public showDialog(params: datePickerDialogParams): void { + this._params = params; + this._value = params.value; + } + + public closeDialog() { + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + render() { + if (!this._params) { + return html``; + } + return html` + + today + + cancel + + ok + `; + } + + private _valueChanged(ev: CustomEvent) { + this._value = ev.detail.value; + } + + private _setToday() { + this._value = new Date().toISOString().split("T")[0]; + } + + private _setValue() { + this._params?.onChange(this._value!); + this.closeDialog(); + } + + static styles = [ + haStyleDialog, + css` + ha-dialog { + --dialog-content-padding: 0; + --justify-action-buttons: space-between; + } + app-datepicker { + --app-datepicker-accent-color: var(--primary-color); + --app-datepicker-bg-color: transparent; + --app-datepicker-color: var(--primary-text-color); + --app-datepicker-disabled-day-color: var(--disabled-text-color); + --app-datepicker-focused-day-color: var(--text-primary-color); + --app-datepicker-focused-year-bg-color: var(--primary-color); + --app-datepicker-selector-color: var(--secondary-text-color); + --app-datepicker-separator-color: var(--divider-color); + --app-datepicker-weekday-color: var(--secondary-text-color); + } + app-datepicker::part(calendar-day):focus { + outline: none; + } + @media all and (min-width: 450px) { + ha-dialog { + --mdc-dialog-min-width: 300px; + } + } + @media all and (max-width: 450px), all and (max-height: 500px) { + app-datepicker { + width: 100%; + } + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dialog-date-picker": HaDialogDatePicker; + } +} diff --git a/src/dialogs/more-info/controls/more-info-input_datetime.ts b/src/dialogs/more-info/controls/more-info-input_datetime.ts index af1e9aa6a..4d1be5c70 100644 --- a/src/dialogs/more-info/controls/more-info-input_datetime.ts +++ b/src/dialogs/more-info/controls/more-info-input_datetime.ts @@ -23,6 +23,7 @@ class MoreInfoInputDatetime extends LitElement { this.stateObj.attributes.has_date ? html`