diff options
author | Christopher Ng <chrng8@gmail.com> | 2024-02-14 17:05:38 -0800 |
---|---|---|
committer | Christopher Ng <chrng8@gmail.com> | 2024-03-08 03:46:55 -0800 |
commit | c9139c64ffde394a00ae5aed6bc95949b4f8a076 (patch) | |
tree | 02401bead49041966dd2dc487bbf60e78ce45b17 /apps/files_reminders | |
parent | 5ae3556178dcaa8b80d58ac0e9ca35a857768650 (diff) | |
download | nextcloud-server-c9139c64ffde394a00ae5aed6bc95949b4f8a076.tar.gz nextcloud-server-c9139c64ffde394a00ae5aed6bc95949b4f8a076.zip |
feat(files_reminders): Add reminder status indicator
Signed-off-by: Christopher Ng <chrng8@gmail.com>
Diffstat (limited to 'apps/files_reminders')
-rw-r--r-- | apps/files_reminders/src/actions/reminderStatusAction.ts | 62 | ||||
-rw-r--r-- | apps/files_reminders/src/components/SetCustomReminderModal.vue | 100 | ||||
-rw-r--r-- | apps/files_reminders/src/init.ts | 4 | ||||
-rw-r--r-- | apps/files_reminders/src/services/customPicker.ts | 4 |
4 files changed, 122 insertions, 48 deletions
diff --git a/apps/files_reminders/src/actions/reminderStatusAction.ts b/apps/files_reminders/src/actions/reminderStatusAction.ts new file mode 100644 index 00000000000..ec82f52cfc2 --- /dev/null +++ b/apps/files_reminders/src/actions/reminderStatusAction.ts @@ -0,0 +1,62 @@ +/** + * @copyright 2024 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/>. + * + */ + +import { FileAction, type Node } from '@nextcloud/files' +import { translate as t } from '@nextcloud/l10n' + +import AlarmSvg from '@mdi/svg/svg/alarm.svg?raw' + +import { pickCustomDate } from '../services/customPicker.ts' +import { getVerboseDateString } from '../shared/utils.ts' + +export const action = new FileAction({ + id: 'reminder-status', + + inline: () => true, + + displayName: () => '', + + title: (nodes: Node[]) => { + const node = nodes.at(0)! + const dueDate = new Date(node.attributes['reminder-due-date']) + return `${t('files_reminders', 'Reminder set')} – ${getVerboseDateString(dueDate)}` + }, + + iconSvgInline: () => AlarmSvg, + + enabled: (nodes: Node[]) => { + // Only allow on a single node + if (nodes.length !== 1) { + return false + } + const node = nodes.at(0)! + const dueDate = node.attributes['reminder-due-date'] + return Boolean(dueDate) + }, + + async exec(node: Node) { + pickCustomDate(node) + return null + }, + + order: -15, +}) diff --git a/apps/files_reminders/src/components/SetCustomReminderModal.vue b/apps/files_reminders/src/components/SetCustomReminderModal.vue index 40895fec7a9..fdbe5d24855 100644 --- a/apps/files_reminders/src/components/SetCustomReminderModal.vue +++ b/apps/files_reminders/src/components/SetCustomReminderModal.vue @@ -21,15 +21,15 @@ --> <template> - <NcModal v-if="opened" + <NcDialog v-if="opened" + :name="name" :out-transition="true" size="small" - @close="onClose"> - <form class="custom-reminder-modal" @submit.prevent="setCustom"> - <h2 class="custom-reminder-modal__title"> - {{ title }} - </h2> - + close-on-click-outside + @closing="onClose"> + <form id="set-custom-reminder-form" + class="custom-reminder-modal" + @submit.prevent="setCustom"> <NcDateTimePickerNative id="set-custom-reminder" v-model="customDueDate" :label="label" @@ -46,21 +46,27 @@ <NcNoteCard v-else type="error"> {{ t('files_reminders', 'Please choose a valid date & time') }} </NcNoteCard> - - <!-- Buttons --> - <div class="custom-reminder-modal__buttons"> - <!-- Cancel pick --> - <NcButton @click="onClose"> - {{ t('files_reminders', 'Cancel') }} - </NcButton> - - <!-- Set reminder --> - <NcButton :disabled="!isValid" native-type="submit" type="primary"> - {{ t('files_reminders', 'Set reminder') }} - </NcButton> - </div> </form> - </NcModal> + <template #actions> + <!-- Cancel pick --> + <NcButton type="tertiary" @click="onClose"> + {{ t('files_reminders', 'Cancel') }} + </NcButton> + + <!-- Clear reminder --> + <NcButton v-if="hasDueDate" @click="clear"> + {{ t('files_reminders', 'Clear reminder') }} + </NcButton> + + <!-- Set reminder --> + <NcButton :disabled="!isValid" + type="primary" + form="set-custom-reminder-form" + native-type="submit"> + {{ t('files_reminders', 'Set reminder') }} + </NcButton> + </template> + </NcDialog> </template> <script lang="ts"> @@ -73,12 +79,12 @@ import { translate as t } from '@nextcloud/l10n' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import NcDateTime from '@nextcloud/vue/dist/Components/NcDateTime.js' import NcDateTimePickerNative from '@nextcloud/vue/dist/Components/NcDateTimePickerNative.js' -import NcModal from '@nextcloud/vue/dist/Components/NcModal.js' +import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js' import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' import { getDateString, getInitialCustomDueDate } from '../shared/utils.ts' import { logger } from '../shared/logger.ts' -import { setReminder } from '../services/reminderService.ts' +import { clearReminder, setReminder } from '../services/reminderService.ts' export default Vue.extend({ name: 'SetCustomReminderModal', @@ -87,17 +93,18 @@ export default Vue.extend({ NcButton, NcDateTime, NcDateTimePickerNative, - NcModal, + NcDialog, NcNoteCard, }, data() { return { node: undefined as Node | undefined, + hasDueDate: false, opened: false, isValid: true, - customDueDate: getInitialCustomDueDate() as '' | Date, + customDueDate: null as null | Date, nowDate: new Date(), } }, @@ -111,7 +118,7 @@ export default Vue.extend({ return this.node.basename }, - title() { + name() { return t('files_reminders', 'Set reminder for "{fileName}"', { fileName: this.fileName }) }, @@ -133,18 +140,23 @@ export default Vue.extend({ * and reset the state. * @param node The node to set a reminder for */ - async open(node: Node): Promise<void> { + open(node: Node): void { + const dueDate = node.attributes['reminder-due-date'] ? new Date(node.attributes['reminder-due-date']) : null + this.node = node + this.hasDueDate = Boolean(dueDate) this.isValid = true this.opened = true - this.customDueDate = getInitialCustomDueDate() + this.customDueDate = dueDate ?? getInitialCustomDueDate() this.nowDate = new Date() // Focus the input and show the picker after the animation setTimeout(() => { const input = document.getElementById('set-custom-reminder') as HTMLInputElement input.focus() - input.showPicker() + if (!this.hasDueDate) { + input.showPicker() + } }, 300) }, @@ -167,6 +179,19 @@ export default Vue.extend({ } }, + async clear(): Promise<void> { + try { + await clearReminder(this.fileId) + Vue.set(this.node.attributes, 'reminder-due-date', '') + emit('files:node:updated', this.node) + showSuccess(t('files_reminders', 'Reminder cleared for "{fileName}"', { fileName: this.fileName })) + this.onClose() + } catch (error) { + logger.error('Failed to clear reminder', { error }) + showError(t('files_reminders', 'Failed to clear reminder')) + } + }, + onClose(): void { this.opened = false this.$emit('close') @@ -182,21 +207,6 @@ export default Vue.extend({ <style lang="scss" scoped> .custom-reminder-modal { - margin: 30px; - - &__title { - font-size: 16px; - line-height: 2em; - } - - &__buttons { - display: flex; - justify-content: flex-end; - margin-top: 30px; - - button { - margin-left: 10px; - } - } + margin: 0 12px; } </style> diff --git a/apps/files_reminders/src/init.ts b/apps/files_reminders/src/init.ts index d1642626f10..74063dbff4c 100644 --- a/apps/files_reminders/src/init.ts +++ b/apps/files_reminders/src/init.ts @@ -21,13 +21,15 @@ */ import { registerDavProperty, registerFileAction } from '@nextcloud/files' -import { action as menuAction } from './actions/setReminderMenuAction' +import { action as statusAction } from './actions/reminderStatusAction' import { action as clearAction } from './actions/clearReminderAction' +import { action as menuAction } from './actions/setReminderMenuAction' import { actions as suggestionActions } from './actions/setReminderSuggestionActions' import { action as customAction } from './actions/setReminderCustomAction' registerDavProperty('nc:reminder-due-date', { nc: 'http://nextcloud.org/ns' }) +registerFileAction(statusAction) registerFileAction(clearAction) registerFileAction(menuAction) registerFileAction(customAction) diff --git a/apps/files_reminders/src/services/customPicker.ts b/apps/files_reminders/src/services/customPicker.ts index 46a0f917c0c..1f52a7b2b55 100644 --- a/apps/files_reminders/src/services/customPicker.ts +++ b/apps/files_reminders/src/services/customPicker.ts @@ -36,11 +36,11 @@ const CustomReminderModal = new View({ el: mount, }) -export const pickCustomDate = async (node: Node): Promise<void> => { +export const pickCustomDate = (node: Node): Promise<void> => { CustomReminderModal.open(node) // Wait for the modal to close return new Promise((resolve) => { - CustomReminderModal.$on('close', resolve) + CustomReminderModal.$once('close', resolve) }) } |