aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/src/components/AvailabilityForm.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/src/components/AvailabilityForm.vue')
-rw-r--r--apps/dav/src/components/AvailabilityForm.vue205
1 files changed, 205 insertions, 0 deletions
diff --git a/apps/dav/src/components/AvailabilityForm.vue b/apps/dav/src/components/AvailabilityForm.vue
new file mode 100644
index 00000000000..27bd71c6ca4
--- /dev/null
+++ b/apps/dav/src/components/AvailabilityForm.vue
@@ -0,0 +1,205 @@
+<template>
+ <div>
+ <div class="time-zone">
+ <label :for="`vs${timeZonePickerId}__combobox`" class="time-zone__heading">
+ {{ $t('dav', 'Time zone:') }}
+ </label>
+ <span class="time-zone-text">
+ <NcTimezonePicker v-model="timezone" :uid="timeZonePickerId" />
+ </span>
+ </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')" />
+
+ <NcCheckboxRadioSwitch :checked.sync="automated">
+ {{ $t('dav', 'Automatically set user status to "Do not disturb" outside of availability to mute all notifications.') }}
+ </NcCheckboxRadioSwitch>
+
+ <NcButton :disabled="loading || saving"
+ type="primary"
+ @click="save">
+ {{ $t('dav', 'Save') }}
+ </NcButton>
+ </div>
+</template>
+
+<script>
+import { CalendarAvailability } from '@nextcloud/calendar-availability-vue'
+import { loadState } from '@nextcloud/initial-state'
+import {
+ showError,
+ showSuccess,
+} from '@nextcloud/dialogs'
+import {
+ findScheduleInboxAvailability,
+ getEmptySlots,
+ saveScheduleInboxAvailability,
+} from '../service/CalendarService.js'
+import {
+ enableUserStatusAutomation,
+ disableUserStatusAutomation,
+} from '../service/PreferenceService.js'
+import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
+import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
+import NcTimezonePicker from '@nextcloud/vue/dist/Components/NcTimezonePicker.js'
+
+export default {
+ name: 'AvailabilityForm',
+ components: {
+ NcButton,
+ NcCheckboxRadioSwitch,
+ CalendarAvailability,
+ NcTimezonePicker,
+ },
+ data() {
+ // Try to determine the current timezone, and fall back to UTC otherwise
+ const defaultTimezoneId = (new Intl.DateTimeFormat())?.resolvedOptions()?.timeZone ?? 'UTC'
+
+ return {
+ loading: true,
+ saving: false,
+ timezone: defaultTimezoneId,
+ slots: getEmptySlots(),
+ automated: loadState('dav', 'user_status_automation') === 'yes',
+ }
+ },
+ computed: {
+ timeZonePickerId() {
+ return `tz-${(Math.random() + 1).toString(36).substring(7)}`
+ },
+ },
+ async mounted() {
+ try {
+ 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)
+ }
+ } catch (e) {
+ console.error('could not load existing availability', e)
+
+ showError(t('dav', 'Failed to load availability'))
+ } finally {
+ this.loading = false
+ }
+ },
+ methods: {
+ async save() {
+ try {
+ this.saving = true
+
+ await saveScheduleInboxAvailability(this.slots, this.timezone)
+ if (this.automated) {
+ await enableUserStatusAutomation()
+ } else {
+ await disableUserStatusAutomation()
+ }
+
+ showSuccess(t('dav', 'Saved availability'))
+ } catch (e) {
+ console.error('could not save availability', e)
+
+ showError(t('dav', 'Failed to save availability'))
+ } finally {
+ this.saving = false
+ }
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+:deep(.availability-day) {
+ padding: 0 10px 0 10px;
+ position: absolute;
+}
+:deep(.availability-slots) {
+ display: flex;
+ white-space: normal;
+}
+:deep(.availability-slot) {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ flex-wrap: wrap;
+}
+:deep(.availability-slot-group) {
+ display: flex;
+ flex-direction: column;
+}
+:deep(.mx-input-wrapper) {
+ width: 85px;
+}
+:deep(.mx-datepicker) {
+ width: 97px;
+}
+:deep(.multiselect) {
+ border: 1px solid var(--color-border-dark);
+ width: 120px;
+}
+.time-zone {
+ padding: 32px 12px 12px 0;
+ display: flex;
+ flex-wrap: wrap;
+
+ &__heading {
+ margin-right: calc(var(--default-grid-baseline) * 2);
+ line-height: var(--default-clickable-area);
+ font-weight: bold;
+ }
+}
+.grid-table {
+ display: grid;
+ margin-bottom: 32px;
+ grid-column-gap: 24px;
+ grid-row-gap: 6px;
+ grid-template-columns: min-content auto min-content;
+ max-width: 500px;
+}
+.button {
+ align-self: flex-end;
+}
+:deep(.label-weekday) {
+ position: relative;
+ display: inline-flex;
+ padding-top: 4px;
+ align-self: center;
+}
+
+:deep(.delete-slot) {
+ padding-bottom: unset;
+}
+
+:deep(.add-another) {
+ align-self: center;
+}
+
+.to-text {
+ padding-right: 12px;
+}
+
+.empty-content {
+ color: var(--color-text-lighter);
+ margin-top: 4px;
+ align-self: center;
+}
+</style>