Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2021-11-19 18:45:30 +0300
committerChristoph Wurst <christoph@winzerhof-wurst.at>2022-02-17 11:38:42 +0300
commitdaf1b5f6a3b35279b4a23046ba51690920f62fec (patch)
treef8920304ef3f4b6486334ab0f791fe668e9c0397 /apps/dav/src
parent5ee0fb3acb918d16c78addaa54d3a581f9e4f982 (diff)
Replace CalDAV availability component with component lib
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'apps/dav/src')
-rw-r--r--apps/dav/src/service/CalendarService.js117
-rw-r--r--apps/dav/src/views/Availability.vue140
2 files changed, 37 insertions, 220 deletions
diff --git a/apps/dav/src/service/CalendarService.js b/apps/dav/src/service/CalendarService.js
index 10d3e252465..2b416d6b670 100644
--- a/apps/dav/src/service/CalendarService.js
+++ b/apps/dav/src/service/CalendarService.js
@@ -19,11 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { getClient } from '../dav/client'
-import ICAL from 'ical.js'
import logger from './logger'
import { parseXML } from 'webdav/dist/node/tools/dav'
-import { getZoneString } from 'icalzone'
-import { v4 as uuidv4 } from 'uuid'
+
+import {
+ slotsToVavailability,
+ vavailabilityToSlots,
+} from '@nextcloud/calendar-availability-vue'
/**
*
@@ -67,44 +69,7 @@ export async function findScheduleInboxAvailability() {
return undefined
}
- const parsedIcal = ICAL.parse(availability)
-
- const vcalendarComp = new ICAL.Component(parsedIcal)
- const vavailabilityComp = vcalendarComp.getFirstSubcomponent('vavailability')
-
- let timezoneId
- const timezoneComp = vcalendarComp.getFirstSubcomponent('vtimezone')
- if (timezoneComp) {
- timezoneId = timezoneComp.getFirstProperty('tzid').getFirstValue()
- }
-
- const availableComps = vavailabilityComp.getAllSubcomponents('available')
- // Combine all AVAILABLE blocks into a week of slots
- const slots = getEmptySlots()
- availableComps.forEach((availableComp) => {
- const start = availableComp.getFirstProperty('dtstart').getFirstValue().toJSDate()
- const end = availableComp.getFirstProperty('dtend').getFirstValue().toJSDate()
- const rrule = availableComp.getFirstProperty('rrule')
-
- if (rrule.getFirstValue().freq !== 'WEEKLY') {
- logger.warn('rrule not supported', {
- rrule: rrule.toICALString(),
- })
- return
- }
-
- rrule.getFirstValue().getComponent('BYDAY').forEach(day => {
- slots[day].push({
- start,
- end,
- })
- })
- })
-
- return {
- slots,
- timezoneId,
- }
+ return vavailabilityToSlots(availability)
}
/**
@@ -117,74 +82,10 @@ export async function saveScheduleInboxAvailability(slots, timezoneId) {
day: dayId,
})))]
- const vcalendarComp = new ICAL.Component('vcalendar')
- vcalendarComp.addPropertyWithValue('prodid', 'Nextcloud DAV app')
-
- // Store time zone info
- // If possible we use the info from a time zone database
- const predefinedTimezoneIcal = getZoneString(timezoneId)
- if (predefinedTimezoneIcal) {
- const timezoneComp = new ICAL.Component(ICAL.parse(predefinedTimezoneIcal))
- vcalendarComp.addSubcomponent(timezoneComp)
- } else {
- // Fall back to a simple markup
- const timezoneComp = new ICAL.Component('vtimezone')
- timezoneComp.addPropertyWithValue('tzid', timezoneId)
- vcalendarComp.addSubcomponent(timezoneComp)
- }
-
- // Store availability info
- const vavailabilityComp = new ICAL.Component('vavailability')
-
- // Deduplicate by start and end time
- const deduplicated = all.reduce((acc, slot) => {
- const key = [
- slot.start.getHours(),
- slot.start.getMinutes(),
- slot.end.getHours(),
- slot.end.getMinutes(),
- ].join('-')
-
- return {
- ...acc,
- [key]: [...(acc[key] ?? []), slot],
- }
- }, {})
-
- // Create an AVAILABILITY component for every recurring slot
- Object.keys(deduplicated).map(key => {
- const slots = deduplicated[key]
- const start = slots[0].start
- const end = slots[0].end
- // Combine days but make them also unique
- const days = slots.map(slot => slot.day).filter((day, index, self) => self.indexOf(day) === index)
-
- const availableComp = new ICAL.Component('available')
-
- // Define DTSTART and DTEND
- const startTimeProp = availableComp.addPropertyWithValue('dtstart', ICAL.Time.fromJSDate(start, false))
- startTimeProp.setParameter('tzid', timezoneId)
- const endTimeProp = availableComp.addPropertyWithValue('dtend', ICAL.Time.fromJSDate(end, false))
- endTimeProp.setParameter('tzid', timezoneId)
-
- // Add mandatory UID
- availableComp.addPropertyWithValue('uid', uuidv4())
-
- // TODO: add optional summary
-
- // Define RRULE
- availableComp.addPropertyWithValue('rrule', {
- freq: 'WEEKLY',
- byday: days,
- })
-
- return availableComp
- }).map(vavailabilityComp.addSubcomponent.bind(vavailabilityComp))
+ const vavailability = slotsToVavailability(all, timezoneId)
- vcalendarComp.addSubcomponent(vavailabilityComp)
logger.debug('New availability ical created', {
- asObject: vcalendarComp,
- asString: vcalendarComp.toString(),
+ vavailability,
})
const client = getClient('calendars')
@@ -194,7 +95,7 @@ export async function saveScheduleInboxAvailability(slots, timezoneId) {
<x0:propertyupdate xmlns:x0="DAV:">
<x0:set>
<x0:prop>
- <x1:calendar-availability xmlns:x1="urn:ietf:params:xml:ns:caldav">${vcalendarComp.toString()}</x1:calendar-availability>
+ <x1:calendar-availability xmlns:x1="urn:ietf:params:xml:ns:caldav">${vavailability}</x1:calendar-availability>
</x0:prop>
</x0:set>
</x0:propertyupdate>`,
diff --git a/apps/dav/src/views/Availability.vue b/apps/dav/src/views/Availability.vue
index 62915810042..bba35f35b1f 100644
--- a/apps/dav/src/views/Availability.vue
+++ b/apps/dav/src/views/Availability.vue
@@ -12,45 +12,19 @@
<TimezonePicker v-model="timezone" />
</span>
</div>
- <div class="grid-table">
- <template v-for="day in daysOfTheWeek">
- <div :key="`day-label-${day.id}`" class="label-weekday">
- {{ day.displayName }}
- </div>
- <div :key="`day-slots-${day.id}`" class="availability-slots">
- <div class="availability-slot-group">
- <template v-for="(slot, idx) in day.slots">
- <div :key="`slot-${day.id}-${idx}`" class="availability-slot">
- <DatetimePicker v-model="slot.start"
- type="time"
- class="start-date"
- format="H:mm" />
- <span class="to-text">
- {{ $t('dav', 'to') }}
- </span>
- <DatetimePicker v-model="slot.end"
- type="time"
- class="end-date"
- format="H:mm" />
- <button :key="`slot-${day.id}-${idx}-btn`"
- class="icon-delete delete-slot button"
- :title="$t('dav', 'Delete slot')"
- @click="deleteSlot(day, idx)" />
- </div>
- </template>
- </div>
- <span v-if="day.slots.length === 0"
- class="empty-content">
- {{ $t('dav', 'No working hours set') }}
- </span>
- </div>
- <button :key="`add-slot-${day.id}`"
- :disabled="loading"
- class="icon-add add-another button"
- :title="$t('dav', 'Add slot')"
- @click="addSlot(day)" />
- </template>
- </div>
+ <CalendarAvailability :slots.sync="slots"
+ :loading="loading"
+ :l10n-to="$t('dav', 'to')"
+ :l10n-delete-slot="$t('dav', 'Delete slot')"
+ :l10n-empty-day="$t('dav', 'No working hours set')"
+ :l10n-add-slot="$t('dav', 'Add slot')"
+ :l10n-monday="$t('dav', 'Monday')"
+ :l10n-tuesday="$t('dav', 'Tuesday')"
+ :l10n-wednesday="$t('dav', 'Wednesday')"
+ :l10n-thursday="$t('dav', 'Thursday')"
+ :l10n-friday="$t('dav', 'Friday')"
+ :l10n-saturday="$t('dav', 'Saturday')"
+ :l10n-sunday="$t('dav', 'Sunday')" />
<button :disabled="loading || saving"
class="button primary"
@click="save">
@@ -60,19 +34,18 @@
</template>
<script>
-import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker'
+import { CalendarAvailability } from '@nextcloud/calendar-availability-vue'
import {
findScheduleInboxAvailability,
getEmptySlots,
saveScheduleInboxAvailability,
} from '../service/CalendarService'
-import { getFirstDay } from '@nextcloud/l10n'
import jstz from 'jstimezonedetect'
import TimezonePicker from '@nextcloud/vue/dist/Components/TimezonePicker'
export default {
name: 'Availability',
components: {
- DatetimePicker,
+ CalendarAvailability,
TimezonePicker,
},
data() {
@@ -80,63 +53,27 @@ export default {
const defaultTimezone = jstz.determine()
const defaultTimezoneId = defaultTimezone ? defaultTimezone.name() : 'UTC'
- const moToSa = [
- {
- id: 'MO',
- displayName: this.$t('dav', 'Monday'),
- slots: [],
- },
- {
- id: 'TU',
- displayName: this.$t('dav', 'Tuesday'),
- slots: [],
- },
- {
- id: 'WE',
- displayName: this.$t('dav', 'Wednesday'),
- slots: [],
- },
- {
- id: 'TH',
- displayName: this.$t('dav', 'Thursday'),
- slots: [],
- },
- {
- id: 'FR',
- displayName: this.$t('dav', 'Friday'),
- slots: [],
- },
- {
- id: 'SA',
- displayName: this.$t('dav', 'Saturday'),
- slots: [],
- },
- ]
- const sunday = {
- id: 'SU',
- displayName: this.$t('dav', 'Sunday'),
- slots: [],
- }
- const daysOfTheWeek = getFirstDay() === 1 ? [...moToSa, sunday] : [sunday, ...moToSa]
return {
loading: true,
saving: false,
timezone: defaultTimezoneId,
- daysOfTheWeek,
+ slots: getEmptySlots(),
}
},
async mounted() {
try {
- const { slots, timezoneId } = await findScheduleInboxAvailability()
- if (slots) {
- this.daysOfTheWeek.forEach(day => {
- day.slots.push(...slots[day.id])
- })
- }
- if (timezoneId) {
- this.timezone = timezoneId
+ const slotData = await findScheduleInboxAvailability()
+ if (!slotData) {
+ console.info('no availability is set')
+ this.slots = getEmptySlots()
+ } else {
+ const { slots, timezoneId } = slotData
+ this.slots = slots
+ if (timezoneId) {
+ this.timezone = timezoneId
+ }
+ console.info('availability loaded', this.slots, this.timezoneId)
}
- console.info('availability loaded', this.daysOfTheWeek)
} catch (e) {
console.error('could not load existing availability', e)
@@ -146,32 +83,11 @@ export default {
}
},
methods: {
- addSlot(day) {
- const start = new Date()
- start.setHours(9)
- start.setMinutes(0)
- start.setSeconds(0)
- const end = new Date()
- end.setHours(17)
- end.setMinutes(0)
- end.setSeconds(0)
- day.slots.push({
- start,
- end,
- })
- },
- deleteSlot(day, idx) {
- day.slots.splice(idx, 1)
- },
async save() {
try {
this.saving = true
- const slots = getEmptySlots()
- this.daysOfTheWeek.forEach(day => {
- day.slots.forEach(slot => slots[day.id].push(slot))
- })
- await saveScheduleInboxAvailability(slots, this.timezone)
+ await saveScheduleInboxAvailability(this.slots, this.timezone)
// TODO: show a nice toast
} catch (e) {