mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Prevent invalid event durations in calendar (#14545)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
745753c526
commit
ff64dc2631
@ -1,7 +1,13 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { mdiClose } from "@mdi/js";
|
import { mdiClose } from "@mdi/js";
|
||||||
import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
||||||
import { addDays, addHours, startOfHour } from "date-fns/esm";
|
import {
|
||||||
|
addDays,
|
||||||
|
addHours,
|
||||||
|
addMilliseconds,
|
||||||
|
differenceInMilliseconds,
|
||||||
|
startOfHour,
|
||||||
|
} from "date-fns/esm";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, 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";
|
||||||
@ -35,6 +41,8 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
|
@state() private _info?: string;
|
||||||
|
|
||||||
@state() private _params?: CalendarEventDetailDialogParams;
|
@state() private _params?: CalendarEventDetailDialogParams;
|
||||||
|
|
||||||
@state() private _calendars: Calendar[] = [];
|
@state() private _calendars: Calendar[] = [];
|
||||||
@ -57,6 +65,7 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
|
|
||||||
public showDialog(params: CalendarEventEditDialogParams): void {
|
public showDialog(params: CalendarEventEditDialogParams): void {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
|
this._info = undefined;
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._calendars = params.calendars;
|
this._calendars = params.calendars;
|
||||||
this._calendarId = params.calendarId || this._calendars[0].entity_id;
|
this._calendarId = params.calendarId || this._calendars[0].entity_id;
|
||||||
@ -120,6 +129,14 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
${this._error
|
${this._error
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
: ""}
|
: ""}
|
||||||
|
${this._info
|
||||||
|
? html`<ha-alert
|
||||||
|
alert-type="info"
|
||||||
|
dismissable
|
||||||
|
@alert-dismissed-clicked=${this._clearInfo}
|
||||||
|
>${this._info}</ha-alert
|
||||||
|
>`
|
||||||
|
: ""}
|
||||||
|
|
||||||
<ha-textfield
|
<ha-textfield
|
||||||
class="summary"
|
class="summary"
|
||||||
@ -260,6 +277,10 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private _clearInfo() {
|
||||||
|
this._info = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
private _handleSummaryChanged(ev) {
|
private _handleSummaryChanged(ev) {
|
||||||
this._summary = ev.target.value;
|
this._summary = ev.target.value;
|
||||||
}
|
}
|
||||||
@ -277,9 +298,30 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _startDateChanged(ev: CustomEvent) {
|
private _startDateChanged(ev: CustomEvent) {
|
||||||
|
// Store previous event duration
|
||||||
|
const duration = differenceInMilliseconds(this._dtend!, this._dtstart!);
|
||||||
|
|
||||||
this._dtstart = new Date(
|
this._dtstart = new Date(
|
||||||
ev.detail.value + "T" + this._dtstart!.toISOString().split("T")[1]
|
ev.detail.value + "T" + this._dtstart!.toISOString().split("T")[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Prevent that the end time can be before the start time. Try to keep the
|
||||||
|
// duration the same.
|
||||||
|
if (this._dtend! <= this._dtstart!) {
|
||||||
|
const newEnd = addMilliseconds(this._dtstart, duration);
|
||||||
|
// en-CA locale used for date format YYYY-MM-DD
|
||||||
|
// en-GB locale used for 24h time format HH:MM:SS
|
||||||
|
this._dtend = new Date(
|
||||||
|
`${newEnd.toLocaleDateString("en-CA", {
|
||||||
|
timeZone: this.hass.config.time_zone,
|
||||||
|
})}T${newEnd.toLocaleTimeString("en-GB", {
|
||||||
|
timeZone: this.hass.config.time_zone,
|
||||||
|
})}`
|
||||||
|
);
|
||||||
|
this._info = this.hass.localize(
|
||||||
|
"ui.components.calendar.event.end_auto_adjusted"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _endDateChanged(ev: CustomEvent) {
|
private _endDateChanged(ev: CustomEvent) {
|
||||||
@ -289,9 +331,28 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _startTimeChanged(ev: CustomEvent) {
|
private _startTimeChanged(ev: CustomEvent) {
|
||||||
|
// Store previous event duration
|
||||||
|
const duration = differenceInMilliseconds(this._dtend!, this._dtstart!);
|
||||||
|
|
||||||
this._dtstart = new Date(
|
this._dtstart = new Date(
|
||||||
this._dtstart!.toISOString().split("T")[0] + "T" + ev.detail.value
|
this._dtstart!.toISOString().split("T")[0] + "T" + ev.detail.value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Prevent that the end time can be before the start time. Try to keep the
|
||||||
|
// duration the same.
|
||||||
|
if (this._dtend! <= this._dtstart!) {
|
||||||
|
const newEnd = addMilliseconds(new Date(this._dtstart), duration);
|
||||||
|
this._dtend = new Date(
|
||||||
|
`${newEnd.toLocaleDateString("en-CA", {
|
||||||
|
timeZone: this.hass.config.time_zone,
|
||||||
|
})}T${newEnd.toLocaleTimeString("en-GB", {
|
||||||
|
timeZone: this.hass.config.time_zone,
|
||||||
|
})}`
|
||||||
|
);
|
||||||
|
this._info = this.hass.localize(
|
||||||
|
"ui.components.calendar.event.end_auto_adjusted"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _endTimeChanged(ev: CustomEvent) {
|
private _endTimeChanged(ev: CustomEvent) {
|
||||||
@ -337,6 +398,13 @@ class DialogCalendarEventEditor extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._dtend! <= this._dtstart!) {
|
||||||
|
this._error = this.hass.localize(
|
||||||
|
"ui.components.calendar.event.invalid_duration"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._submitting = true;
|
this._submitting = true;
|
||||||
try {
|
try {
|
||||||
await createCalendarEvent(
|
await createCalendarEvent(
|
||||||
|
@ -642,7 +642,9 @@
|
|||||||
"all_day": "All Day",
|
"all_day": "All Day",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
"end": "End",
|
"end": "End",
|
||||||
"not_all_required_fields": "Not all required fields are filled in.",
|
"invalid_duration": "The duration of the event is not valid. Please check start and end date.",
|
||||||
|
"not_all_required_fields": "Not all required fields are filled in",
|
||||||
|
"end_auto_adjusted": "Event end was adjusted to prevent negative duration",
|
||||||
"confirm_delete": {
|
"confirm_delete": {
|
||||||
"delete": "Delete Event",
|
"delete": "Delete Event",
|
||||||
"delete_this": "Delete Only This Event",
|
"delete_this": "Delete Only This Event",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user