aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_reminders
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2024-02-14 17:05:38 -0800
committerChristopher Ng <chrng8@gmail.com>2024-03-08 03:46:55 -0800
commitc9139c64ffde394a00ae5aed6bc95949b4f8a076 (patch)
tree02401bead49041966dd2dc487bbf60e78ce45b17 /apps/files_reminders
parent5ae3556178dcaa8b80d58ac0e9ca35a857768650 (diff)
downloadnextcloud-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.ts62
-rw-r--r--apps/files_reminders/src/components/SetCustomReminderModal.vue100
-rw-r--r--apps/files_reminders/src/init.ts4
-rw-r--r--apps/files_reminders/src/services/customPicker.ts4
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)
})
}