Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable3.7] fix: send imip when importing an event in mail #10030

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 61 additions & 42 deletions src/components/Imip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,30 +86,32 @@
<template v-if="isRequest && userIsAttendee">
<div v-if="!wasProcessed && eventIsInFuture && existingEventFetched"
class="imip__actions imip__actions--buttons">
<ButtonVue type="secondary"
:loading="loading"
<NcButton type="secondary"
:disabled="loading"
:aria-label="t('mail', 'Accept')"
@click="accept">
{{ t('mail', 'Accept') }}
</ButtonVue>
<ButtonVue type="tertiary"
:loading="loading"
</NcButton>
<NcButton type="tertiary"
:disabled="loading"
:aria-label="t('mail', 'Decline')"
@click="decline">
{{ t('mail', 'Decline') }}
</ButtonVue>
<ButtonVue type="tertiary"
:loading="loading"
</NcButton>
<NcButton type="tertiary"
:disabled="loading"
:aria-label="t('mail', 'Tentatively accept')"
@click="acceptTentatively">
{{ t('mail', 'Tentatively accept') }}
</ButtonVue>
<ButtonVue v-if="!showMoreOptions"
</NcButton>
<NcButton v-if="!showMoreOptions"
type="tertiary"
:disabled="loading"
:aria-label="t('mail', 'More options')"
@click="showMoreOptions = true">
{{ t('mail', 'More options') }}
</ButtonVue>
</NcButton>
<NcLoadingIcon v-if="loading" />
</div>
<p v-else-if="!eventIsInFuture" class="imip__actions imip__actions--hint">
{{ t('mail', 'This event is in the past.') }}
Expand All @@ -120,7 +122,7 @@

<script>
import EventData from './imip/EventData.vue'
import { NcButton as ButtonVue, NcSelect } from '@nextcloud/vue'
import { NcButton, NcSelect, NcLoadingIcon } from '@nextcloud/vue'
import CloseIcon from 'vue-material-design-icons/Close.vue'
import CalendarIcon from 'vue-material-design-icons/Calendar.vue'
import { getParserManager, Parameter, Property } from '@nextcloud/calendar-js'
Expand Down Expand Up @@ -149,9 +151,9 @@
/**
* Search a vEvent for an attendee by mail.
*
* @param {EventComponent|undefined|null} vEvent The event providing the attendee haystack.

Check warning on line 154 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'EventComponent' is undefined
* @param {string} email The email address (with or without a mailto prefix) to use as the needle.
* @return {AttendeeProperty|undefined} The attendee property or undefined if the given email is not matching an attendee.

Check warning on line 156 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'AttendeeProperty' is undefined
*/
function findAttendee(vEvent, email) {
if (!vEvent) {
Expand All @@ -171,11 +173,12 @@
export default {
name: 'Imip',
components: {
EventData,
ButtonVue,
CloseIcon,
CalendarIcon,
CalendarPickerOption,
CloseIcon,
EventData,
NcButton,
NcLoadingIcon,
NcSelect,
},
props: {
Expand Down Expand Up @@ -255,7 +258,7 @@
},

/**
* @return {CalendarComponent|undefined}

Check warning on line 261 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'CalendarComponent' is undefined
*/
attachedVCalendar() {
const parserManager = getParserManager()
Expand All @@ -267,14 +270,14 @@
},

/**
* @return {EventComponent|undefined}

Check warning on line 273 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'EventComponent' is undefined
*/
attachedVEvent() {
return this.attachedVCalendar?.getFirstComponent('VEVENT') ?? undefined
},

/**
* @return {CalendarComponent|undefined}

Check warning on line 280 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'CalendarComponent' is undefined
*/
existingVCalendar() {
if (!this.existingEvent) {
Expand All @@ -290,7 +293,7 @@
},

/**
* @return {EventComponent|undefined}

Check warning on line 296 in src/components/Imip.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The type 'EventComponent' is undefined
*/
existingVEvent() {
return this.existingVCalendar?.getFirstComponent('VEVENT') ?? undefined
Expand Down Expand Up @@ -431,44 +434,60 @@
return
}

attendee.participationStatus = status
if (this.comment) {
attendee.setParameter(new Parameter('X-RESPONSE-COMMENT', this.comment))
vEvent.addProperty(new Property('COMMENT', this.comment))
this.loading = true

if (!this.isExistingEvent) {
try {
await calendar.createVObject(vCalendar.toICS())
await this.fetchExistingEvent(vEvent.uid, true)
} catch (error) {
showError(this.t('mail', 'Failed to save your participation status'))
logger.error('Failed to save event to calendar', {
error,
attendee,
calendar,
vEvent,
vCalendar,
existingEvent: this.existingEvent,
})
}
}
// TODO: implement an input for guests and save it to the attendee via X-NUM-GUESTS

this.loading = true
try {
if (this.isExistingEvent) {
if (this.isExistingEvent) {
attendee.participationStatus = status
if (this.comment) {
attendee.setParameter(new Parameter('X-RESPONSE-COMMENT', this.comment))
vEvent.addProperty(new Property('COMMENT', this.comment))
}

// TODO: implement an input for guests and save it to the attendee via X-NUM-GUESTS

try {
// TODO: don't show buttons if calendar is not writable
this.existingEvent.data = vCalendar.toICS()
await this.existingEvent.update()
} else {
await calendar.createVObject(vCalendar.toICS())
this.showMoreOptions = false
} catch (error) {
showError(this.t('mail', 'Failed to save your participation status'))
logger.error('Failed to save event to calendar', {
error,
attendee,
calendar,
vEvent,
vCalendar,
existingEvent: this.existingEvent,
})
}
this.showMoreOptions = false
} catch (error) {
showError(this.t('mail', 'Failed to save your participation status'))
logger.error('Failed to save event to calendar', {
error,
attendee,
calendar,
vEvent,
vCalendar,
existingEvent: this.existingEvent,
})
} finally {
this.loading = false
}

// Refetch the event to update the shown status message or reset the event in the case
// of an error.
this.existingEventFetched = false
await this.fetchExistingEvent(vEvent.uid)
await this.fetchExistingEvent(vEvent.uid, true)

this.loading = false
},
async fetchExistingEvent(uid) {
if (this.existingEventFetched) {
async fetchExistingEvent(uid, force = false) {
if (!force && this.existingEventFetched) {
return
}

Expand Down
Loading