Skip to content

Commit aabb768

Browse files
Merge pull request #8901 from nextcloud/backport/7600/stable6.5
[stable6.5] fix: update, delete, accept, devline all occurrences
2 parents 782dc48 + 9b4e09c commit aabb768

16 files changed

Lines changed: 2314 additions & 184 deletions

src/components/Editor/InvitationResponseButtons.vue

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,23 @@
1313
class="invitation-response-buttons__button"
1414
:disabled="loading"
1515
@click="accept">
16-
{{ t('calendar', 'Accept') }}
16+
{{ acceptLabel }}
1717
</NcButton>
1818
<NcButton
1919
v-if="!isDeclined"
2020
variant="error"
2121
class="invitation-response-buttons__button"
2222
:disabled="loading"
2323
@click="decline">
24-
{{ t('calendar', 'Decline') }}
24+
{{ declineLabel }}
2525
</NcButton>
2626
<template v-if="!isTentative">
2727
<NcButton
2828
v-if="!narrow"
2929
class="invitation-response-buttons__button"
3030
:disabled="loading"
3131
@click="tentative">
32-
{{ t('calendar', 'Tentative') }}
32+
{{ tentativeLabel }}
3333
</NcButton>
3434
<Actions v-else>
3535
<ActionButton
@@ -38,7 +38,7 @@
3838
<template #icon>
3939
<CalendarQuestionIcon :size="20" />
4040
</template>
41-
{{ t('calendar', 'Tentative') }}
41+
{{ tentativeLabel }}
4242
</ActionButton>
4343
</Actions>
4444
</template>
@@ -72,11 +72,6 @@ export default {
7272
required: true,
7373
},
7474
75-
calendarId: {
76-
type: String,
77-
required: true,
78-
},
79-
8075
narrow: {
8176
type: Boolean,
8277
default: false,
@@ -107,6 +102,45 @@ export default {
107102
isTentative() {
108103
return this.attendee.participationStatus === 'TENTATIVE'
109104
},
105+
106+
responseScope() {
107+
const eventComponent = this.calendarObjectInstanceStore.calendarObjectInstance?.eventComponent
108+
if (!eventComponent?.isPartOfRecurrenceSet()) {
109+
return null
110+
}
111+
112+
return eventComponent.isRecurrenceException() ? 'occurrence' : 'series'
113+
},
114+
115+
acceptLabel() {
116+
if (this.responseScope === 'occurrence') {
117+
return this.t('calendar', 'Accept this occurrence')
118+
}
119+
if (this.responseScope === 'series') {
120+
return this.t('calendar', 'Accept entire series')
121+
}
122+
return this.t('calendar', 'Accept')
123+
},
124+
125+
declineLabel() {
126+
if (this.responseScope === 'occurrence') {
127+
return this.t('calendar', 'Decline this occurrence')
128+
}
129+
if (this.responseScope === 'series') {
130+
return this.t('calendar', 'Decline entire series')
131+
}
132+
return this.t('calendar', 'Decline')
133+
},
134+
135+
tentativeLabel() {
136+
if (this.responseScope === 'occurrence') {
137+
return this.t('calendar', 'Tentative for this occurrence')
138+
}
139+
if (this.responseScope === 'series') {
140+
return this.t('calendar', 'Tentative for entire series')
141+
}
142+
return this.t('calendar', 'Tentative')
143+
},
110144
},
111145
112146
methods: {
@@ -149,16 +183,10 @@ export default {
149183
async setParticipationStatus(participationStatus) {
150184
this.loading = true
151185
try {
152-
this.calendarObjectInstanceStore.changeAttendeesParticipationStatus({
186+
await this.calendarObjectInstanceStore.saveAttendeeParticipationResponse({
153187
attendee: this.attendee,
154188
participationStatus,
155189
})
156-
// TODO: What about recurring events? Add new buttons like "Accept this and all future"?
157-
// Currently, this will only accept a single occurrence.
158-
await this.calendarObjectInstanceStore.saveCalendarObjectInstance({
159-
thisAndAllFuture: false,
160-
calendarId: this.calendarId,
161-
})
162190
} catch (error) {
163191
logger.error('Failed to set participation status', { error, participationStatus })
164192
throw error

src/components/Editor/Repeat/Repeat.vue

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,18 @@
3333
<div class="property-repeat__options">
3434
<h2>{{ $t('calendar', 'Repeat event') }}</h2>
3535
<RepeatFreqInterval
36-
v-if="!isRecurrenceException && !isReadOnly"
36+
v-if="!isEditingExceptionInstance && !isReadOnly"
3737
:frequency="recurrenceRule.frequency"
3838
:interval="recurrenceRule.interval"
3939
@changeInterval="changeInterval"
4040
@changeFrequency="changeFrequency" />
4141
<RepeatFreqWeeklyOptions
42-
v-if="isFreqWeekly && !isRecurrenceException && !isReadOnly"
42+
v-if="isFreqWeekly && !isEditingExceptionInstance && !isReadOnly"
4343
:byDay="recurrenceRule.byDay"
4444
@addByDay="addByDay"
4545
@removeByDay="removeByDay" />
4646
<RepeatFreqMonthlyOptions
47-
v-if="isFreqMonthly && !isRecurrenceException && !isReadOnly"
47+
v-if="isFreqMonthly && !isEditingExceptionInstance && !isReadOnly"
4848
:byDay="recurrenceRule.byDay"
4949
:byMonthDay="recurrenceRule.byMonthDay"
5050
:bySetPosition="recurrenceRule.bySetPosition"
@@ -55,7 +55,7 @@
5555
@changeToBySetPosition="changeToBySetPositionMonthly"
5656
@changeToByMonthDay="changeToByDayMonthly" />
5757
<RepeatFreqYearlyOptions
58-
v-if="isFreqYearly && !isRecurrenceException && !isReadOnly"
58+
v-if="isFreqYearly && !isEditingExceptionInstance && !isReadOnly"
5959
:byDay="recurrenceRule.byDay"
6060
:byMonth="recurrenceRule.byMonth"
6161
:byMonthDay="recurrenceRule.byMonthDay"
@@ -69,7 +69,7 @@
6969
@changeToBySetPosition="changeToBySetPositionYearly"
7070
@changeToByMonthDay="changeToByDayYearly" />
7171
<RepeatEndRepeat
72-
v-if="isRepeating && !isRecurrenceException && !isReadOnly"
72+
v-if="isRepeating && !isEditingExceptionInstance && !isReadOnly"
7373
:calendarObjectInstance="calendarObjectInstance"
7474
:until="recurrenceRule.until"
7575
:count="recurrenceRule.count"
@@ -78,11 +78,11 @@
7878
@setCount="setCount"
7979
@changeToCount="changeToCount"
8080
@changeToUntil="changeToUntil" />
81-
<RepeatUnsupportedWarning v-if="recurrenceRule.isUnsupported && !isRecurrenceException" />
82-
<RepeatExceptionWarning v-if="isRecurrenceException" />
81+
<RepeatUnsupportedWarning v-if="recurrenceRule.isUnsupported && !isEditingExceptionInstance" />
82+
<RepeatExceptionWarning v-if="isEditingExceptionInstance" />
8383
</div>
8484
<div
85-
v-if="!isRecurrenceException && !isReadOnly"
85+
v-if="!isEditingExceptionInstance && !isReadOnly"
8686
class="property-repeat__options__footer">
8787
<NcButton variant="primary" @click="saveAndClose">
8888
{{ $t('calendar', 'Set repetition') }}
@@ -154,25 +154,26 @@ export default {
154154
},
155155
156156
/**
157-
* Whether or not the user is editing the master-item
158-
* If so, we are enforcing "This and all future" and
159-
* don't allow to just save this occurrence
157+
* Whether or not the user is editing the base instance.
158+
* Recurrence-rule changes on a non-base instance require a future update.
160159
*/
161-
isEditingMasterItem: {
160+
isEditingBaseInstance: {
162161
type: Boolean,
163162
required: true,
164163
},
165164
166165
/**
167-
* Whether or not this instance of the event is a recurrence-exception.
166+
* Whether or not the user is editing a recurrence-exception.
168167
* If yes, you can't modify the recurrence-rule
169168
*/
170-
isRecurrenceException: {
169+
isEditingExceptionInstance: {
171170
type: Boolean,
172171
required: true,
173172
},
174173
},
175174
175+
emits: ['requireFutureUpdate'],
176+
176177
data() {
177178
return {
178179
showOptions: false,
@@ -485,8 +486,8 @@ export default {
485486
})
486487
}
487488
488-
if (!this.isEditingMasterItem) {
489-
this.$emit('forceThisAndAllFuture')
489+
if (!this.isEditingBaseInstance) {
490+
this.$emit('requireFutureUpdate')
490491
}
491492
492493
this.calendarObjectInstanceStore.calendarObjectInstance.canModifyAllDay = this.calendarObjectInstanceStore.calendarObjectInstance.eventComponent.canModifyAllDay()

src/components/Editor/SaveButtons.vue

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
v-if="showSaveButton"
1717
variant="primary"
1818
:disabled="disabled"
19-
@click="saveThisOnly">
19+
@click="saveOccurrence">
2020
<template #icon>
2121
<CheckIcon :size="20" />
2222
</template>
@@ -26,38 +26,43 @@
2626
v-if="showUpdateButton"
2727
variant="primary"
2828
:disabled="disabled"
29-
@click="saveThisOnly">
29+
@click="saveOccurrence">
3030
<template #icon>
3131
<CheckIcon :size="20" />
3232
</template>
3333
{{ $t('calendar', 'Update') }}
3434
</NcButton>
3535
<NcButton
36-
v-if="showUpdateThisAndFutureButton && !showUpdateOnlyThisButton"
36+
v-if="showUpdateSeriesButton"
3737
variant="primary"
3838
:disabled="disabled"
39-
@click="saveThisAndAllFuture">
40-
{{ $t('calendar', 'Update this and all future') }}
39+
@click="saveSeries">
40+
{{ $t('calendar', 'Update entire series') }}
4141
</NcButton>
4242
<NcButton
43-
v-if="showUpdateOnlyThisButton && !showUpdateThisAndFutureButton"
43+
v-if="showUpdateFutureButton"
4444
variant="primary"
4545
:disabled="disabled"
46-
@click="saveThisOnly">
47-
{{ $t('calendar', 'Update this occurrence') }}
46+
@click="saveFuture">
47+
{{ $t('calendar', 'Update this and future occurrences') }}
4848
</NcButton>
49-
50-
<NcActions v-if="showUpdateThisAndFutureButton && showUpdateOnlyThisButton" :primary="true" :menuName="t('calendar', 'Update')">
49+
<NcActions v-if="showUpdateMenu" :primary="true" :menuName="t('calendar', 'Update')">
5150
<template #icon>
5251
<CheckIcon :size="20" />
5352
</template>
54-
<NcActionButton @click="saveThisAndAllFuture">
53+
<NcActionButton v-if="canUpdateSeries" @click="saveSeries">
54+
<template #icon>
55+
<CheckIcon :size="20" />
56+
</template>
57+
{{ $t('calendar', 'Update entire series') }}
58+
</NcActionButton>
59+
<NcActionButton v-if="canUpdateFuture" @click="saveFuture">
5560
<template #icon>
5661
<CheckAllIcon :size="20" />
5762
</template>
58-
{{ $t('calendar', 'Update this and all future') }}
63+
{{ $t('calendar', 'Update this and future occurrences') }}
5964
</NcActionButton>
60-
<NcActionButton @click="saveThisOnly">
65+
<NcActionButton v-if="canUpdateOccurrence" @click="saveOccurrence">
6166
<template #icon>
6267
<CheckIcon :size="20" />
6368
</template>
@@ -86,22 +91,27 @@ export default {
8691
},
8792
8893
props: {
89-
canCreateRecurrenceException: {
94+
canUpdateOccurrence: {
9095
type: Boolean,
9196
required: true,
9297
},
9398
94-
isNew: {
99+
canUpdateFuture: {
95100
type: Boolean,
96101
required: true,
97102
},
98103
99-
isReadOnly: {
104+
canUpdateSeries: {
105+
type: Boolean,
106+
required: true,
107+
},
108+
109+
isNew: {
100110
type: Boolean,
101111
required: true,
102112
},
103113
104-
forceThisAndAllFuture: {
114+
isReadOnly: {
105115
type: Boolean,
106116
required: true,
107117
},
@@ -122,31 +132,45 @@ export default {
122132
},
123133
},
124134
135+
emits: ['saveOccurrence', 'saveFuture', 'saveSeries', 'showMore'],
136+
125137
computed: {
126138
showSaveButton() {
127-
return !this.isReadOnly && this.isNew && !this.canCreateRecurrenceException
139+
return !this.isReadOnly && this.isNew
128140
},
129141
130142
showUpdateButton() {
131-
return !this.isReadOnly && !this.isNew && !this.canCreateRecurrenceException
143+
return !this.isReadOnly && !this.isNew && this.allowedUpdateScopeCount === 1 && this.canUpdateOccurrence
144+
},
145+
146+
allowedUpdateScopeCount() {
147+
return [this.canUpdateOccurrence, this.canUpdateFuture, this.canUpdateSeries].filter(Boolean).length
148+
},
149+
150+
showUpdateFutureButton() {
151+
return !this.isReadOnly && !this.isNew && this.allowedUpdateScopeCount === 1 && this.canUpdateFuture
132152
},
133153
134-
showUpdateOnlyThisButton() {
135-
return !this.isReadOnly && this.canCreateRecurrenceException && !this.forceThisAndAllFuture
154+
showUpdateSeriesButton() {
155+
return !this.isReadOnly && !this.isNew && this.allowedUpdateScopeCount === 1 && this.canUpdateSeries
136156
},
137157
138-
showUpdateThisAndFutureButton() {
139-
return !this.isReadOnly && this.canCreateRecurrenceException
158+
showUpdateMenu() {
159+
return !this.isReadOnly && !this.isNew && this.allowedUpdateScopeCount > 1
140160
},
141161
},
142162
143163
methods: {
144-
saveThisOnly() {
145-
this.$emit('saveThisOnly')
164+
saveOccurrence() {
165+
this.$emit('saveOccurrence')
166+
},
167+
168+
saveFuture() {
169+
this.$emit('saveFuture')
146170
},
147171
148-
saveThisAndAllFuture() {
149-
this.$emit('saveThisAndAllFuture')
172+
saveSeries() {
173+
this.$emit('saveSeries')
150174
},
151175
152176
showMore() {

0 commit comments

Comments
 (0)