Bladeren bron

feat(files_reminders): add set reminder actions

Signed-off-by: Christopher Ng <chrng8@gmail.com>
Christopher Ng 9 maanden geleden
bovenliggende
commit
5e4881b90c
1 gewijzigde bestanden met toevoegingen van 225 en 0 verwijderingen
  1. 225 0
      apps/files_reminders/src/components/SetReminderActions.vue

+ 225 - 0
apps/files_reminders/src/components/SetReminderActions.vue

@@ -0,0 +1,225 @@
+<!--
+  - @copyright 2023 Christopher Ng <chrng8@gmail.com>
+  -
+  - @author Christopher Ng <chrng8@gmail.com>
+  -
+  - @license AGPL-3.0-or-later
+  -
+  - This program is free software: you can redistribute it and/or modify
+  - it under the terms of the GNU Affero General Public License as
+  - published by the Free Software Foundation, either version 3 of the
+  - License, or (at your option) any later version.
+  -
+  - This program is distributed in the hope that it will be useful,
+  - but WITHOUT ANY WARRANTY; without even the implied warranty of
+  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  - GNU Affero General Public License for more details.
+  -
+  - You should have received a copy of the GNU Affero General Public License
+  - along with this program. If not, see <http://www.gnu.org/licenses/>.
+  -
+-->
+
+<template>
+	<NcActions class="actions-secondary-vue"
+		:open.sync="open">
+		<NcActionButton @click="$emit('back')">
+			<template #icon>
+				<NcIconSvgWrapper :svg="arrowLeftSvg" />
+			</template>
+			{{ t('files_reminders', 'Back') }}
+		</NcActionButton>
+		<NcActionButton v-if="Boolean(dueDate)"
+			:aria-label="clearAriaLabel"
+			@click="clear">
+			<template #icon>
+				<NcIconSvgWrapper :svg="clearSvg" />
+			</template>
+			{{ t('files_reminders', 'Clear reminder') }} — {{ getDateString(dueDate) }}
+		</NcActionButton>
+		<NcActionSeparator />
+		<NcActionButton v-for="({ icon, label, ariaLabel, dateString, action }) in options"
+			:key="label"
+			:aria-label="ariaLabel"
+			@click="action">
+			<template #icon>
+				<NcIconSvgWrapper :svg="icon" />
+			</template>
+			{{ label }} — {{ dateString }}
+		</NcActionButton>
+	</NcActions>
+</template>
+
+<script lang="ts">
+import Vue, { type PropType } from 'vue'
+import { translate as t } from '@nextcloud/l10n'
+import { showError, showSuccess } from '@nextcloud/dialogs'
+
+import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
+import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
+import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js'
+import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
+
+import arrowLeftSvg from '@mdi/svg/svg/arrow-left.svg?raw'
+import clearSvg from '@mdi/svg/svg/close-circle-outline.svg?raw'
+import laterTodaySvg from '@mdi/svg/svg/update.svg?raw'
+import tomorrowSvg from '@mdi/svg/svg/chevron-right.svg?raw'
+import thisWeekendSvg from '@mdi/svg/svg/calendar-weekend.svg?raw'
+import nextWeekSvg from '@mdi/svg/svg/chevron-double-right.svg?raw'
+
+import { clearReminder, setReminder } from '../services/reminderService.js'
+import {
+	DateTimePreset,
+	getDateString,
+	getDateTime,
+	getVerboseDateString,
+} from '../shared/utils.js'
+import { logger } from '../shared/logger.js'
+
+import type { FileAttributes } from '../shared/types.js'
+
+interface ReminderOption {
+	dateTimePreset: DateTimePreset
+	icon: string
+	label: string
+	ariaLabel: string
+	dateString?: string
+	action?: () => Promise<void>
+}
+
+const laterToday: ReminderOption = {
+	dateTimePreset: DateTimePreset.LaterToday,
+	icon: laterTodaySvg,
+	label: t('files_reminders', 'Later today'),
+	ariaLabel: t('files_reminders', 'Set reminder for later today'),
+}
+
+const tomorrow: ReminderOption = {
+	dateTimePreset: DateTimePreset.Tomorrow,
+	icon: tomorrowSvg,
+	label: t('files_reminders', 'Tomorrow'),
+	ariaLabel: t('files_reminders', 'Set reminder for tomorrow'),
+}
+
+const thisWeekend: ReminderOption = {
+	dateTimePreset: DateTimePreset.ThisWeekend,
+	icon: thisWeekendSvg,
+	label: t('files_reminders', 'This weekend'),
+	ariaLabel: t('files_reminders', 'Set reminder for this weekend'),
+}
+
+const nextWeek: ReminderOption = {
+	dateTimePreset: DateTimePreset.NextWeek,
+	icon: nextWeekSvg,
+	label: t('files_reminders', 'Next week'),
+	ariaLabel: t('files_reminders', 'Set reminder for next week'),
+}
+
+export default Vue.extend({
+	name: 'SetReminderActions',
+
+	components: {
+		NcActionButton,
+		NcActions,
+		NcActionSeparator,
+		NcIconSvgWrapper,
+	},
+
+	props: {
+		file: {
+			type: Object as PropType<FileAttributes>,
+			required: true,
+		},
+
+		dueDate: {
+			type: Date as PropType<null | Date>,
+			default: null,
+		},
+	},
+
+	data() {
+		return {
+			arrowLeftSvg,
+			clearSvg,
+			open: true,
+		}
+	},
+
+	watch: {
+		open(isOpen) {
+			if (!isOpen) {
+				this.$emit('close')
+			}
+		},
+	},
+
+	computed: {
+		fileId(): number {
+			return this.file.id
+		},
+
+		fileName(): string {
+			return this.file.name
+		},
+
+		clearAriaLabel(): string {
+			return `${t('files_reminders', 'Clear reminder')} — ${getVerboseDateString(this.dueDate as Date)}`
+		},
+
+		options(): ReminderOption[] {
+			const computeOption = (option: ReminderOption) => {
+				const dateTime = getDateTime(option.dateTimePreset)
+				return {
+					...option,
+					ariaLabel: `${option.ariaLabel} — ${getVerboseDateString(dateTime)}`,
+					dateString: getDateString(dateTime),
+					action: () => this.set(dateTime),
+				}
+			}
+
+			return [
+				laterToday,
+				tomorrow,
+				thisWeekend,
+				nextWeek,
+			].map(computeOption)
+		},
+	},
+
+	methods: {
+		t,
+		getDateString,
+
+		async set(dueDate: Date): Promise<void> {
+			try {
+				await setReminder(this.fileId, dueDate)
+				showSuccess(t('files_reminders', 'Reminder set for "{fileName}"', { fileName: this.fileName }))
+				this.open = false
+			} catch (error) {
+				logger.error('Failed to set reminder', { error })
+				showError(t('files_reminders', 'Failed to set reminder'))
+			}
+		},
+
+		async clear(): Promise<void> {
+			try {
+				await clearReminder(this.fileId)
+				showSuccess(t('files_reminders', 'Reminder cleared'))
+				this.open = false
+			} catch (error) {
+				logger.error('Failed to clear reminder', { error })
+				showError(t('files_reminders', 'Failed to clear reminder'))
+			}
+		},
+	},
+})
+</script>
+
+<style lang="scss" scoped>
+.actions-secondary-vue {
+	display: block !important;
+    float: right !important;
+    padding: 5px 0 0 4px !important;
+	pointer-events: none !important; // prevent activation of file row
+}
+</style>