Skip to content

Commit 514abbb

Browse files
committed
feat: allow calendar-wide only-availability share setting
First shot at implementing the `CALDAV:read-free-busy` privilege setting. Should allow sharing a whole calendar with only availability knowledge (without event details) instead of setting this flag for each event individually. Signed-off-by: MiragonMx <80544476+MiragonMx@users.noreply.github.com>
1 parent f41650c commit 514abbb

File tree

4 files changed

+65
-0
lines changed

4 files changed

+65
-0
lines changed

src/components/AppNavigation/EditCalendarModal.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
{{ $t('calendar', 'Never show me as busy (set this calendar to transparent)') }}
3535
</NcCheckboxRadioSwitch>
3636
</template>
37+
<template v-if="canBeShared">
38+
<NcCheckboxRadioSwitch :checked.sync="isOnlyAvailability">
39+
{{ $t('calendar', 'Don’t show event details to others') }}
40+
</NcCheckboxRadioSwitch>
41+
</template>
3742
<template v-if="canBeShared">
3843
<h3 class="edit-calendar-modal__sharing-header">
3944
{{ $t('calendar', 'Share calendar') }}
@@ -119,6 +124,7 @@ export default {
119124
calendarColor: undefined,
120125
calendarColorChanged: false,
121126
isTransparent: false,
127+
isOnlyAvailability: false,
122128
calendarName: undefined,
123129
calendarNameChanged: false,
124130
}
@@ -180,6 +186,7 @@ export default {
180186
this.calendarNameChanged = false
181187
this.calendarColorChanged = false
182188
this.isTransparent = calendar.transparency === 'transparent'
189+
this.isOnlyAvailability = calendar.onlyAvailability
183190
},
184191
},
185192
@@ -227,6 +234,24 @@ export default {
227234
}
228235
},
229236
237+
/**
238+
* Save the calendar share property of only showing availability
239+
*/
240+
async saveShareOnlyAvailability() {
241+
try {
242+
await this.calendarsStore.changeCalendarShareOnlyAvailability({
243+
calendar: this.calendar,
244+
onlyAvailability: this.isOnlyAvailability,
245+
})
246+
} catch (error) {
247+
logger.error('Failed to save calendar transparency', {
248+
calendar: this.calendar,
249+
onlyAvailability: this.isOnlyAvailability,
250+
})
251+
throw error
252+
}
253+
},
254+
230255
/**
231256
* Save the calendar name.
232257
*/
@@ -256,6 +281,7 @@ export default {
256281
await this.saveColor()
257282
}
258283
await this.saveTransparency()
284+
await this.saveShareOnlyAvailability()
259285
if (this.calendarNameChanged) {
260286
await this.saveName()
261287
}

src/models/calendar.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ function getDefaultCalendarObject(props = {}) {
5656
fetchedTimeRanges: [],
5757
// Scheduling transparency
5858
transparency: 'opaque',
59+
// Shared option to only show free/busy
60+
onlyAvailability: false,
5961
...props,
6062
}
6163
}
@@ -130,6 +132,8 @@ function mapDavCollectionToCalendar(calendar, currentUserPrincipal) {
130132
}
131133
}
132134

135+
const onlyAvailability = false
136+
133137
return getDefaultCalendarObject({
134138
id,
135139
displayName,
@@ -149,6 +153,7 @@ function mapDavCollectionToCalendar(calendar, currentUserPrincipal) {
149153
shares,
150154
timezone,
151155
transparency,
156+
onlyAvailability,
152157
dav: calendar,
153158
})
154159
}

src/store/calendars.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,25 @@ export default defineStore('calendars', {
591591
this.calendarsById[calendar.id].transparency = transparency
592592
},
593593

594+
/**
595+
* Change if a calendar share only shows availability (instead of full event details)
596+
*
597+
* @param {object} data destructuring object
598+
* @param {object} data.calendar the calendar to modify
599+
* @param {string} data.shareOnlyAvailability the new value for sharing only avaliability
600+
* @return {Promise}
601+
*/
602+
async changeCalendarShareOnlyAvailability({ calendar, shareOnlyAvailability }) {
603+
if (calendar.dav.onlyAvailability === shareOnlyAvailability) {
604+
return
605+
}
606+
607+
calendar.dav.onlyAvailability = shareOnlyAvailability
608+
609+
await calendar.dav.update()
610+
this.calendarsById[calendar.id].onlyAvailability = shareOnlyAvailability
611+
},
612+
594613
/**
595614
* Share calendar with User or Group
596615
*

tests/javascript/unit/models/calendar.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
3939
calendarObjects: [],
4040
fetchedTimeRanges: [],
4141
transparency: 'opaque',
42+
onlyAvailability: false,
4243
})
4344
})
4445

@@ -70,6 +71,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
7071
calendarObjects: [],
7172
fetchedTimeRanges: [],
7273
transparency: 'opaque',
74+
onlyAvailability: false,
7375
})
7476
})
7577

@@ -88,6 +90,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
8890
enabled: true,
8991
timezone: 'BEGIN:VCALENDAR...END:VCALENDAR',
9092
transparency: 'opaque',
93+
onlyAvailability: false,
9194
}
9295

9396
expect(mapDavCollectionToCalendar(cdavObject, {
@@ -111,6 +114,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
111114
isSharedWithMe: false,
112115
timezone: 'BEGIN:VCALENDAR...END:VCALENDAR',
113116
transparency: 'opaque',
117+
onlyAvailability: false,
114118
url: '/foo/bar',
115119
calendarObjects: [],
116120
fetchedTimeRanges: [],
@@ -134,6 +138,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
134138
publishURL: undefined,
135139
timezone: 'BEGIN:VCALENDAR...END:VCALENDAR',
136140
transparency: 'transparent',
141+
onlyAvailability: false,
137142
enabled: false,
138143
}
139144

@@ -158,6 +163,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
158163
isSharedWithMe: false,
159164
timezone: 'BEGIN:VCALENDAR...END:VCALENDAR',
160165
transparency: 'transparent',
166+
onlyAvailability: false,
161167
url: '/foo/bar',
162168
calendarObjects: [],
163169
fetchedTimeRanges: [],
@@ -203,6 +209,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
203209
isSharedWithMe: false,
204210
timezone: null,
205211
transparency: 'opaque',
212+
onlyAvailability: false,
206213
url: '/foo/bar',
207214
calendarObjects: [],
208215
fetchedTimeRanges: [],
@@ -248,6 +255,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
248255
isSharedWithMe: true,
249256
timezone: null,
250257
transparency: 'opaque',
258+
onlyAvailability: false,
251259
url: '/foo/bar',
252260
calendarObjects: [],
253261
fetchedTimeRanges: [],
@@ -293,6 +301,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
293301
isSharedWithMe: false,
294302
timezone: null,
295303
transparency: 'opaque',
304+
onlyAvailability: false,
296305
url: '/foo/bar',
297306
calendarObjects: [],
298307
fetchedTimeRanges: [],
@@ -338,6 +347,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
338347
isSharedWithMe: false,
339348
timezone: null,
340349
transparency: 'opaque',
350+
onlyAvailability: false,
341351
url: '/foo/bar',
342352
calendarObjects: [],
343353
fetchedTimeRanges: [],
@@ -383,6 +393,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
383393
isSharedWithMe: false,
384394
timezone: null,
385395
transparency: 'opaque',
396+
onlyAvailability: false,
386397
url: '/foo/bar',
387398
calendarObjects: [],
388399
fetchedTimeRanges: [],
@@ -428,6 +439,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
428439
isSharedWithMe: false,
429440
timezone: null,
430441
transparency: 'opaque',
442+
onlyAvailability: false,
431443
url: '/foo/bar',
432444
calendarObjects: [],
433445
fetchedTimeRanges: [],
@@ -529,6 +541,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
529541
isSharedWithMe: false,
530542
timezone: null,
531543
transparency: 'opaque',
544+
onlyAvailability: false,
532545
url: '/foo/bar',
533546
calendarObjects: [],
534547
fetchedTimeRanges: [],
@@ -646,6 +659,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
646659
isSharedWithMe: true,
647660
timezone: null,
648661
transparency: 'opaque',
662+
onlyAvailability: false,
649663
url: '/foo/bar',
650664
calendarObjects: [],
651665
fetchedTimeRanges: [],
@@ -692,6 +706,7 @@ describe('Test suite: Calendar model (models/calendar.js)', () => {
692706
isSharedWithMe: false,
693707
timezone: 'BEGIN:VCALENDAR...END:VCALENDAR',
694708
transparency: 'opaque',
709+
onlyAvailability: false,
695710
url: '/remote.php/dav/calendars/admin/personal/',
696711
calendarObjects: [],
697712
fetchedTimeRanges: [],

0 commit comments

Comments
 (0)