Skip to content
Merged
Show file tree
Hide file tree
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
32 changes: 25 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@nextcloud/axios": "^2.5.2",
"@nextcloud/calendar-availability-vue": "^3.0.0",
"@nextcloud/calendar-js": "^8.1.6",
"@nextcloud/cdav-library": "^2.1.1",
"@nextcloud/cdav-library": "^2.2.0",
"@nextcloud/dialogs": "^7.3.0",
"@nextcloud/event-bus": "^3.3.3",
"@nextcloud/initial-state": "^3.0.0",
Expand Down
147 changes: 146 additions & 1 deletion src/components/AppNavigation/EditCalendarModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@
{{ $t('calendar', 'Never show me as busy (set this calendar to transparent)') }}
</NcCheckboxRadioSwitch>
</template>
<template v-if="!calendar.isSharedWithMe && isAfterVersion">
<div class="edit-calendar-modal__default-alarm">
<label for="default-alarm-select" class="edit-calendar-modal__default-alarm__label">
{{ $t('calendar', 'Default reminder') }}
</label>
<NcSelect
id="default-alarm-select"
v-model="selectedDefaultAlarm"
:options="defaultAlarmOptions"
:clearable="false"
:placeholder="$t('calendar', 'Select default reminder')"
class="edit-calendar-modal__default-alarm__select"
@update:modelValue="defaultAlarmChanged = true" />
<p class="edit-calendar-modal__default-alarm__hint">
{{ $t('calendar', 'This reminder will be automatically added to all new events created in this calendar') }}
</p>
</div>
</template>
<template v-if="canBeShared">
<h3 class="edit-calendar-modal__sharing-header">
{{ $t('calendar', 'Share calendar') }}
Expand Down Expand Up @@ -93,7 +111,7 @@
<script>
import { showError } from '@nextcloud/dialogs'
import { getLanguage } from '@nextcloud/l10n'
import { NcAppNavigationSpacer, NcButton, NcCheckboxRadioSwitch, NcColorPicker, NcModal, NcTextField } from '@nextcloud/vue'
import { NcAppNavigationSpacer, NcButton, NcCheckboxRadioSwitch, NcColorPicker, NcModal, NcSelect, NcTextField } from '@nextcloud/vue'
import { mapStores } from 'pinia'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import CloseIcon from 'vue-material-design-icons/Close.vue'
Expand All @@ -103,8 +121,16 @@ import InternalLink from './EditCalendarModal/InternalLink.vue'
import PublishCalendar from './EditCalendarModal/PublishCalendar.vue'
import ShareItem from './EditCalendarModal/ShareItem.vue'
import SharingSearch from './EditCalendarModal/SharingSearch.vue'
import { getDefaultAlarms } from '../../defaults/defaultAlarmProvider.js'
import alarmFormat from '../../filters/alarmFormat.js'
import useCalendarsStore from '../../store/calendars.js'
import useSettingsStore from '../../store/settings.js'
import {
getAmountAndUnitForTimedEvents,
getAmountHoursMinutesAndUnitForAllDayEvents,
} from '../../utils/alarms.js'
import logger from '../../utils/logger.js'
import { isAfterVersion } from '../../utils/nextcloudVersion.ts'

export default {
name: 'EditCalendarModal',
Expand All @@ -113,6 +139,7 @@ export default {
NcColorPicker,
NcButton,
NcTextField,
NcSelect,
PublishCalendar,
SharingSearch,
ShareItem,
Expand All @@ -132,6 +159,8 @@ export default {
isTransparent: false,
calendarName: undefined,
calendarNameChanged: false,
selectedDefaultAlarm: null,
defaultAlarmChanged: false,
}
},

Expand Down Expand Up @@ -220,6 +249,45 @@ export default {
{ types: localizedTypes },
)
},

/**
* Get the default alarm options for the select dropdown
*
* @return {Array}
*/
defaultAlarmOptions() {
const settingsStore = useSettingsStore()
const currentUserTimezone = settingsStore.getResolvedTimezone
const locale = settingsStore.momentLocale

const options = [
{
label: this.$t('calendar', 'None'),
value: null,
},
]

// Add standard alarm options for timed events
const alarms = getDefaultAlarms(false)
for (const alarm of alarms) {
const alarmObject = this.getAlarmObjectFromTriggerTime(alarm)
options.push({
label: alarmFormat(alarmObject, false, currentUserTimezone, locale),
value: alarm,
})
}

return options
},

/**
* Whether the default alarm feature is supported (Nextcloud 34+)
*
* @return {boolean}
*/
isAfterVersion() {
return isAfterVersion(34)
},
},

watch: {
Expand All @@ -233,6 +301,16 @@ export default {
this.calendarNameChanged = false
this.calendarColorChanged = false
this.isTransparent = calendar.transparency === 'transparent'

// Initialize default alarm
if (calendar.defaultAlarm === null) {
this.selectedDefaultAlarm = this.defaultAlarmOptions[0]
} else {
const value = parseInt(calendar.defaultAlarm)
const option = this.defaultAlarmOptions.find((opt) => opt.value === value)
this.selectedDefaultAlarm = option || this.defaultAlarmOptions[0]
}
this.defaultAlarmChanged = false
},
},

Expand Down Expand Up @@ -298,6 +376,25 @@ export default {
}
},

/**
* Save the calendar default alarm.
*/
async saveDefaultAlarm() {
try {
const defaultAlarmValue = this.selectedDefaultAlarm ? this.selectedDefaultAlarm.value : null
await this.calendarsStore.changeCalendarDefaultAlarm({
calendar: this.calendar,
defaultAlarm: defaultAlarmValue,
})
} catch (error) {
logger.error('Failed to save calendar default alarm', {
calendar: this.calendar,
defaultAlarm: this.selectedDefaultAlarm,
})
throw error
}
},

/**
* Save unsaved changes and close the modal.
*
Expand All @@ -315,6 +412,9 @@ export default {
if (this.calendarNameChanged) {
await this.saveName()
}
if (this.isAfterVersion && this.defaultAlarmChanged) {
await this.saveDefaultAlarm()
}
} catch (error) {
showError(this.$t('calendar', 'Failed to save calendar name and color'))
}
Expand All @@ -331,6 +431,32 @@ export default {
})
this.closeModal()
},

/**
* Create alarm object from trigger time for formatting
*
* @param {number} time Total amount of seconds for the trigger
* @return {object} The alarm object
*/
getAlarmObjectFromTriggerTime(time) {
const timedData = getAmountAndUnitForTimedEvents(time)
const allDayData = getAmountHoursMinutesAndUnitForAllDayEvents(time)

return {
isRelative: true,
absoluteDate: null,
absoluteTimezoneId: null,
relativeIsBefore: time < 0,
relativeIsRelatedToStart: true,
relativeUnitTimed: timedData.unit,
relativeAmountTimed: timedData.amount,
relativeUnitAllDay: allDayData.unit,
relativeAmountAllDay: allDayData.amount,
relativeHoursAllDay: allDayData.hours,
relativeMinutesAllDay: allDayData.minutes,
relativeTrigger: time,
}
},
},
}
</script>
Expand Down Expand Up @@ -397,6 +523,25 @@ export default {
gap: 5px;
}

&__default-alarm {
margin-bottom: calc(var(--default-grid-baseline) * 2);

&__label {
display: block;
margin-bottom: var(--default-grid-baseline);
font-weight: bold;
}

&__select {
width: 100%;
}

&__hint {
margin-top: var(--default-grid-baseline);
color: var(--color-text-maxcontrast);
}
}

.checkbox-content {
margin-inline-start: 25px;
}
Expand Down
6 changes: 1 addition & 5 deletions src/components/AppNavigation/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -338,10 +338,6 @@ export default {
return generateUrl('/settings/user/availability')
},

nextcloudVersion() {
return parseInt(OC.config.version.split('.')[0])
},

defaultCalendarOptions() {
return this.calendarsStore.calendars
.filter((calendar) => !calendar.readOnly
Expand All @@ -350,7 +346,7 @@ export default {
},

/**
* The default calendarci for incoming inivitations
* The default calendar for incoming inivitations
*
* @return {object|undefined} The default calendar or undefined if none is available
*/
Expand Down
4 changes: 2 additions & 2 deletions src/components/AppointmentConfigModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ import useAppointmentConfigsStore from '../store/appointmentConfigs.js'
import useCalendarsStore from '../store/calendars.js'
import useSettingsStore from '../store/settings.js'
import logger from '../utils/logger.js'
import { isAfterVersion } from '@/utils/nextcloudVersion'

export default {
name: 'AppointmentConfigModal',
Expand Down Expand Up @@ -259,8 +260,7 @@ export default {

// TODO: Can be removed after NC version 30 support is dropped
availableCalendars() {
const nextcloudMajorVersion = parseInt(window.OC.config.version.split('.')[0])
if (nextcloudMajorVersion >= 31) {
if (isAfterVersion(31)) {
return this.sortedCalendars
}
return this.ownSortedCalendars
Expand Down
2 changes: 2 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
*/

import type { getCSPNonce } from '@nextcloud/auth'
import type { OC } from './types/oc.ts'

declare global {
let __webpack_nonce__: ReturnType<typeof getCSPNonce>
let __webpack_public_path__: string
const OC: OC
}

export {}
Loading
Loading