Add edit/update support for calendar events (#14814)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Allen Porter 2022-12-27 12:47:42 -08:00 committed by GitHub
parent 2575d35f2c
commit e175c7ba3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 6 deletions

View File

@ -50,6 +50,7 @@ export enum RecurrenceRange {
export const enum CalendarEntityFeature {
CREATE_EVENT = 1,
DELETE_EVENT = 2,
UPDATE_EVENT = 4,
}
export const fetchCalendarEvents = async (
@ -161,12 +162,18 @@ export const createCalendarEvent = (
export const updateCalendarEvent = (
hass: HomeAssistant,
entityId: string,
event: CalendarEventMutableParams
uid: string,
event: CalendarEventMutableParams,
recurrence_id?: string,
recurrence_range?: RecurrenceRange
) =>
hass.callWS<void>({
type: "calendar/event/update",
entity_id: entityId,
event: event,
uid,
recurrence_id,
recurrence_range,
event,
});
export const deleteCalendarEvent = (

View File

@ -25,6 +25,8 @@ import {
CalendarEventMutableParams,
createCalendarEvent,
deleteCalendarEvent,
updateCalendarEvent,
RecurrenceRange,
} from "../../data/calendar";
import { haStyleDialog } from "../../resources/styles";
import { HomeAssistant } from "../../types";
@ -87,10 +89,10 @@ class DialogCalendarEventEditor extends LitElement {
this._summary = entry.summary;
this._rrule = entry.rrule;
if (this._allDay) {
this._dtstart = new Date(entry.dtstart);
this._dtstart = new Date(entry.dtstart + "T00:00:00");
// Calendar event end dates are exclusive, but not shown that way in the UI. The
// reverse happens when persisting the event.
this._dtend = addDays(new Date(entry.dtend), -1);
this._dtend = addDays(new Date(entry.dtend + "T00:00:00"), -1);
} else {
this._dtstart = new Date(entry.dtstart);
this._dtend = new Date(entry.dtend);
@ -168,6 +170,7 @@ class DialogCalendarEventEditor extends LitElement {
class="summary"
name="summary"
.label=${this.hass.localize("ui.components.calendar.event.summary")}
.value=${this._summary}
required
@change=${this._handleSummaryChanged}
error-message=${this.hass.localize("ui.common.error_required")}
@ -179,6 +182,7 @@ class DialogCalendarEventEditor extends LitElement {
.label=${this.hass.localize(
"ui.components.calendar.event.description"
)}
.value=${this._description}
@change=${this._handleDescriptionChanged}
autogrow
></ha-textarea>
@ -412,6 +416,13 @@ class DialogCalendarEventEditor extends LitElement {
this._calendarId = ev.detail.value;
}
private _isValidStartEnd(): boolean {
if (this._allDay) {
return this._dtend! >= this._dtstart!;
}
return this._dtend! > this._dtstart!;
}
private async _createEvent() {
if (!this._summary || !this._calendarId) {
this._error = this.hass.localize(
@ -420,7 +431,7 @@ class DialogCalendarEventEditor extends LitElement {
return;
}
if (this._dtend! <= this._dtstart!) {
if (!this._isValidStartEnd()) {
this._error = this.hass.localize(
"ui.components.calendar.event.invalid_duration"
);
@ -445,7 +456,61 @@ class DialogCalendarEventEditor extends LitElement {
}
private async _saveEvent() {
// to be implemented
if (!this._summary || !this._calendarId) {
this._error = this.hass.localize(
"ui.components.calendar.event.not_all_required_fields"
);
return;
}
if (!this._isValidStartEnd()) {
this._error = this.hass.localize(
"ui.components.calendar.event.invalid_duration"
);
return;
}
this._submitting = true;
const entry = this._params!.entry!;
let range: RecurrenceRange | undefined = RecurrenceRange.THISEVENT;
if (entry.recurrence_id) {
range = await showConfirmEventDialog(this, {
title: this.hass.localize(
"ui.components.calendar.event.confirm_update.update"
),
text: this.hass.localize(
"ui.components.calendar.event.confirm_update.recurring_prompt"
),
confirmText: this.hass.localize(
"ui.components.calendar.event.confirm_update.update_this"
),
confirmFutureText: this.hass.localize(
"ui.components.calendar.event.confirm_update.update_future"
),
});
}
if (range === undefined) {
// Cancel
this._submitting = false;
return;
}
try {
await updateCalendarEvent(
this.hass!,
this._calendarId!,
entry.uid!,
this._calculateData(),
entry.recurrence_id || "",
range!
);
} catch (err: any) {
this._error = err ? err.message : "Unknown error";
return;
} finally {
this._submitting = false;
}
await this._params!.updated();
this.closeDialog();
}
private async _deleteEvent() {

View File

@ -302,6 +302,9 @@ export class HAFullCalendar extends LitElement {
private _handleEventClick(info): void {
const entityStateObj = this.hass.states[info.event.extendedProps.calendar];
const canEdit =
entityStateObj &&
supportsFeature(entityStateObj, CalendarEntityFeature.UPDATE_EVENT);
const canDelete =
entityStateObj &&
supportsFeature(entityStateObj, CalendarEntityFeature.DELETE_EVENT);
@ -312,6 +315,7 @@ export class HAFullCalendar extends LitElement {
updated: () => {
this._fireViewChanged();
},
canEdit: canEdit,
canDelete: canDelete,
});
}

View File

@ -623,6 +623,12 @@
"prompt": "Do you want to delete this event?",
"recurring_prompt": "Do you want to delete only this event, or this and all future occurrences of the event?"
},
"confirm_update": {
"update": "Update Event",
"update_this": "Update Only This Event",
"update_future": "Update All Future Events",
"recurring_prompt": "Do you want to update only this event, or this and all future occurrences of the event?"
},
"repeat": {
"label": "Repeat",
"freq": {