From 798e4fe59809f7335dd2cc47e05b4d50fe6935aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Thu, 26 Mar 2026 14:00:21 +0100 Subject: [PATCH 1/2] fix(files_reminder): passed reminder handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- .../lib/Service/ReminderService.php | 8 ++++++++ .../src/components/SetCustomReminderModal.vue | 17 ++++++++++++----- .../files_actions/reminderStatusAction.spec.ts | 15 +++++++++++++-- .../src/files_actions/reminderStatusAction.ts | 5 ++++- .../src/services/reminderService.ts | 6 +++++- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/apps/files_reminders/lib/Service/ReminderService.php b/apps/files_reminders/lib/Service/ReminderService.php index 6ee395620765c..975b320dd85a0 100644 --- a/apps/files_reminders/lib/Service/ReminderService.php +++ b/apps/files_reminders/lib/Service/ReminderService.php @@ -74,11 +74,19 @@ public function getDueForUser(IUser $user, int $fileId, bool $checkNode = true): return null; } if ($cachedReminder instanceof Reminder) { + if ($cachedReminder->getDueDate() < new DateTime()) { + return null; + } return new RichReminder($cachedReminder, $this->root); } try { $reminder = $this->reminderMapper->findDueForUser($user, $fileId); + // If reminder is in the past, do not return it and do not cache it. + if ($reminder->getDueDate() < new DateTime()) { + return null; + } + $this->cache->set("{$user->getUID()}-$fileId", $reminder); return new RichReminder($reminder, $this->root); } catch (DoesNotExistException $e) { diff --git a/apps/files_reminders/src/components/SetCustomReminderModal.vue b/apps/files_reminders/src/components/SetCustomReminderModal.vue index ea2cdc4ec0b6d..c450087468c4e 100644 --- a/apps/files_reminders/src/components/SetCustomReminderModal.vue +++ b/apps/files_reminders/src/components/SetCustomReminderModal.vue @@ -8,10 +8,9 @@ import type { INode } from '@nextcloud/files' import { showError, showSuccess } from '@nextcloud/dialogs' import { emit as emitEventBus } from '@nextcloud/event-bus' -import { t } from '@nextcloud/l10n' -import { onBeforeMount, onMounted, ref } from 'vue' +import { formatRelativeTime, t } from '@nextcloud/l10n' +import { computed, onBeforeMount, onMounted, ref } from 'vue' import NcButton from '@nextcloud/vue/components/NcButton' -import NcDateTime from '@nextcloud/vue/components/NcDateTime' import NcDateTimePickerNative from '@nextcloud/vue/components/NcDateTimePickerNative' import NcDialog from '@nextcloud/vue/components/NcDialog' import NcNoteCard from '@nextcloud/vue/components/NcNoteCard' @@ -33,6 +32,15 @@ const isValid = ref(true) const customDueDate = ref() const nowDate = ref(new Date()) +const informationText = computed(() => { + const relativeDueDate = formatRelativeTime(customDueDate.value ?? 0) + return (nowDate.value.getTime() >= (customDueDate.value?.getTime() ?? 0)) + // TRANSLATORS: {relativeDueDate} will be replaced with a relative time, e.g. "2 hours ago" or "in 3 days". + ? t('files_reminders', 'We reminded you of this file {relativeDueDate}', { relativeDueDate }) + // TRANSLATORS: {relativeDueDate} will be replaced with a relative time, e.g. "2 hours ago" or "in 3 days". + : t('files_reminders', 'We will remind you of this file {relativeDueDate}', { relativeDueDate }) +}) + onBeforeMount(() => { const dueDate = props.node.attributes['reminder-due-date'] ? new Date(props.node.attributes['reminder-due-date']) @@ -132,8 +140,7 @@ function onInput(): void { @input="onInput" /> - {{ t('files_reminders', 'We will remind you of this file') }} - + {{ informationText }} diff --git a/apps/files_reminders/src/files_actions/reminderStatusAction.spec.ts b/apps/files_reminders/src/files_actions/reminderStatusAction.spec.ts index b4735cd6b77ae..6155dee183892 100644 --- a/apps/files_reminders/src/files_actions/reminderStatusAction.spec.ts +++ b/apps/files_reminders/src/files_actions/reminderStatusAction.spec.ts @@ -22,7 +22,7 @@ describe('reminderStatusAction', () => { owner: 'user', source: 'https://example.com/remote.php/dav/files/user/folder', attributes: { - 'reminder-due-date': '2024-12-25T10:00:00Z', + 'reminder-due-date': '2099-12-25T10:00:00Z', }, root: '/files/user', }) @@ -38,6 +38,17 @@ describe('reminderStatusAction', () => { })).toBe(true) }) + it('should be disabled for one node with past due date', () => { + const node = folder.clone() + node.attributes['reminder-due-date'] = '2000-01-01T00:00:00Z' + expect(action.enabled!({ + nodes: [node], + view, + folder: root, + contents: [], + })).toBe(false) + }) + it('should be disabled with more than one node', () => { expect(action.enabled!({ nodes: [folder, folder], @@ -64,6 +75,6 @@ describe('reminderStatusAction', () => { view, folder: root, contents: [], - })).toMatchInlineSnapshot('"Reminder set – Wednesday, December 25, 2024 at 10:00 AM"') + })).toMatchInlineSnapshot('"Reminder set – Friday, December 25, 2099 at 10:00 AM"') }) }) diff --git a/apps/files_reminders/src/files_actions/reminderStatusAction.ts b/apps/files_reminders/src/files_actions/reminderStatusAction.ts index fc672a8630dfa..9bdd9867d0d18 100644 --- a/apps/files_reminders/src/files_actions/reminderStatusAction.ts +++ b/apps/files_reminders/src/files_actions/reminderStatusAction.ts @@ -33,7 +33,10 @@ export const action: IFileAction = { const node = nodes.at(0)! const dueDate = node.attributes['reminder-due-date'] - return Boolean(dueDate) + const now = new Date() + + // Do not show if the reminder is in the past + return Boolean(dueDate) && new Date(dueDate) > now }, async exec({ nodes }) { diff --git a/apps/files_reminders/src/services/reminderService.ts b/apps/files_reminders/src/services/reminderService.ts index 5060e2d0fbb78..fecafac0ab34c 100644 --- a/apps/files_reminders/src/services/reminderService.ts +++ b/apps/files_reminders/src/services/reminderService.ts @@ -48,7 +48,11 @@ export async function setReminder(fileId: number, dueDate: Date): Promise<[]> { */ export async function clearReminder(fileId: number): Promise<[]> { const url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId }) - const response = await axios.delete(url) + const response = await axios.delete(url, { + // We allow 404 as it means there is no reminder to delete, + // which is the desired state after this function is called anyway + validateStatus: (status) => status === 200 || status === 404, + }) return response.data.ocs.data } From 786d3f256bedbce5c80d8f752c1f1d4c0dec0eab Mon Sep 17 00:00:00 2001 From: nextcloud-command Date: Thu, 26 Mar 2026 14:56:16 +0000 Subject: [PATCH 2/2] chore(assets): Recompile assets Signed-off-by: nextcloud-command --- ... => files_reminders-files_reminders-init-CjUvwokK.chunk.css} | 2 +- dist/files_reminders-init.css | 2 +- dist/files_reminders-init.mjs | 2 +- dist/files_reminders-init.mjs.map | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename dist/{files_reminders-files_reminders-init-AoQhTI1A.chunk.css => files_reminders-files_reminders-init-CjUvwokK.chunk.css} (82%) diff --git a/dist/files_reminders-files_reminders-init-AoQhTI1A.chunk.css b/dist/files_reminders-files_reminders-init-CjUvwokK.chunk.css similarity index 82% rename from dist/files_reminders-files_reminders-init-AoQhTI1A.chunk.css rename to dist/files_reminders-files_reminders-init-CjUvwokK.chunk.css index 364a7df967fe8..87386b2a0d27e 100644 --- a/dist/files_reminders-files_reminders-init-AoQhTI1A.chunk.css +++ b/dist/files_reminders-files_reminders-init-CjUvwokK.chunk.css @@ -1 +1 @@ -.custom-reminder-modal[data-v-1cc1857f]{margin:0 12px}.files-list__row-action-set-reminder-custom{margin-top:13px;position:relative}.files-list__row-action-set-reminder-custom:before{content:"";margin-block:3px;margin-inline:15px 10px;border-bottom:1px solid var(--color-border-dark);cursor:default;display:flex;height:0;position:absolute;inset-inline:0;top:-10px} +.custom-reminder-modal[data-v-d7127154]{margin:0 12px}.files-list__row-action-set-reminder-custom{margin-top:13px;position:relative}.files-list__row-action-set-reminder-custom:before{content:"";margin-block:3px;margin-inline:15px 10px;border-bottom:1px solid var(--color-border-dark);cursor:default;display:flex;height:0;position:absolute;inset-inline:0;top:-10px} diff --git a/dist/files_reminders-init.css b/dist/files_reminders-init.css index cd4df56ecf2ea..c29052717f94a 100644 --- a/dist/files_reminders-init.css +++ b/dist/files_reminders-init.css @@ -1,5 +1,5 @@ /* extracted by css-entry-points-plugin */ -@import './files_reminders-files_reminders-init-AoQhTI1A.chunk.css'; +@import './files_reminders-files_reminders-init-CjUvwokK.chunk.css'; @import './createElementId-DhjFt1I9-C_oBIsvc.chunk.css'; @import './autolink-U5pBzLgI-D7L4ZBkR.chunk.css'; @import './NcModal-kyWZ3UFC-CBh34man.chunk.css'; diff --git a/dist/files_reminders-init.mjs b/dist/files_reminders-init.mjs index f1b95dad88c91..15ac88828265a 100644 --- a/dist/files_reminders-init.mjs +++ b/dist/files_reminders-init.mjs @@ -1,2 +1,2 @@ -import{b as l}from"./index-DHYHHtgJ.chunk.mjs";import{c as Q}from"./dav-BZymqOt7.chunk.mjs";import{e as D,g as X}from"./index-Bndk0DrU.chunk.mjs";import{a as B,t as i}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as O}from"./index-2a6kOrDy.chunk.mjs";import{b as W}from"./createElementId-DhjFt1I9-DdwCqgaq.chunk.mjs";import"./PencilOutline-Qk8GS-l0.chunk.mjs";import"./index-DblWoJ6I.chunk.mjs";import{N as J}from"./NcBreadcrumbs-5gl8Syfa-DJcXDkmn.chunk.mjs";import{_ as ee}from"./NcDateTime.vue_vue_type_script_setup_true_lang-B4upiZjL-CDFdx-HI.chunk.mjs";import"./NcModal-kyWZ3UFC-CC38MZrD.chunk.mjs";import"./NcAvatar-ruClKRzS-gxaDTlsM.chunk.mjs";import"./NcContent-D69ktIEB-CM64XV1n.chunk.mjs";import{N as k}from"./autolink-U5pBzLgI-D1NMH9bI.chunk.mjs";import"./Web-DS-WBH9c.chunk.mjs";import"./NcCheckboxRadioSwitch-D0gFwEVl-BbcIGLyw.chunk.mjs";import"./Plus-BtJ3xjfW.chunk.mjs";import"./NcColorPicker-D07Se8Xb-D3qyscwi.chunk.mjs";import"./TrayArrowDown-D7fMRVjO.chunk.mjs";import{N as te,s as re}from"./index-CrY7NZWO.chunk.mjs";import"./NcSelect-B1uITk_3-0e2p8qEi.chunk.mjs";import"./NcEmojiPicker-DGgqTnHp-BmMIlAzR.chunk.mjs";import"./NcEmptyContent-CDgWCt_m-Dz_uR0NU.chunk.mjs";import"./NcRichText-D_ssz6sB-ByGnwwpX.chunk.mjs";/* empty css */import"./NcInputField-CPL-a_MM-R1bsVnGI.chunk.mjs";import{N as A}from"./mdi--cNatcgF.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-CKSnPt2n.chunk.mjs";import"./TrashCanOutline-DmYYOQ4b.chunk.mjs";import"./index-CqVYsIAH.chunk.mjs";import"./ContentCopy-ljx8CODs.chunk.mjs";import"./NcUserBubble-BE6yD-R0-BAJg1c4w.chunk.mjs";import"./NcUserStatusIcon-JWiuiAXe-DUOABbOJ.chunk.mjs";import"./colors-BfjxNgsx-YlZbKUzS.chunk.mjs";import{f as ie,R as ae,k as ne,o as v,g as y,w as d,b as se,M as oe,h as b,u as n,v as m,t as u,e as x,r as c}from"./runtime-dom.esm-bundler-CKxgtjB6.chunk.mjs";import{a as f,d as N}from"./index-C1xmmKTZ-DF4bDPEh.chunk.mjs";import{a as de}from"./index-BgmsSgl5.chunk.mjs";import"./folder-29HuacU_-DcJI3kE4.chunk.mjs";import"./index-sH3U_332.chunk.mjs";import"./index-D4QioFSy.chunk.mjs";const le='';async function E(e,t){const r=W("/apps/files_reminders/api/v1/{fileId}",{fileId:e});return(await O.put(r,{dueDate:t.toISOString()})).data.ocs.data}async function Z(e){const t=W("/apps/files_reminders/api/v1/{fileId}",{fileId:e});return(await O.delete(t)).data.ocs.data}var p=(e=>(e.LaterToday="later-today",e.Tomorrow="tomorrow",e.ThisWeekend="this-weekend",e.NextWeek="next-week",e))(p||{});function F(){const e=new Date;return e.setHours(0,0,0,0),e.setDate(e.getDate()-e.getDay()+1),new Date(e)}function I(e){new Date(e).setHours(0,0,0,0);const t=new Date(e.getFullYear(),0,1,0,0,0,0),r=(e.getTime()-t.getTime())/864e5;return Math.ceil((r+t.getDay()+1)/7)}function me(e,t){return I(e)===I(t)&&e.getFullYear()===t.getFullYear()}function ue(e,t){return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()}function _(e){return{"later-today":()=>{const t=new Date,r=new Date;r.setHours(18,0,0,0);const s=new Date;return s.setHours(17,0,0,0),t>=s?null:r},tomorrow:()=>{const t=new Date,r=new Date;return r.setDate(t.getDate()+1),r.setHours(8,0,0,0),r},"this-weekend":()=>{const t=new Date;if([5,6,0].includes(t.getDay()))return null;const r=new Date,s=F();return r.setDate(s.getDate()+5),r.setHours(8,0,0,0),r},"next-week":()=>{if(new Date().getDay()===0)return null;const t=new Date,r=F();return t.setDate(r.getDate()+7),t.setHours(8,0,0,0),t}}[e]()}function ce(){const e=new Date,t=new Date;return t.setHours(e.getHours()+2,0,0,0),t}function V(e){let t={hour:"numeric",minute:"2-digit"};const r=new Date;return ue(e,r)||(t={...t,weekday:"short"}),me(e,r)||(t={...t,month:"short",day:"numeric"}),e.getFullYear()!==r.getFullYear()&&(t={...t,year:"numeric"}),e.toLocaleString(B(),t)}function L(e){let t={month:"long",day:"numeric",weekday:"long",hour:"numeric",minute:"2-digit"};const r=new Date;return e.getFullYear()!==r.getFullYear()&&(t={...t,year:"numeric"}),e.toLocaleString(B(),t)}const fe={id:"clear-reminder",displayName:()=>i("files_reminders","Clear reminder"),title:({nodes:e})=>{const t=e.at(0),r=new Date(t.attributes["reminder-due-date"]);return`${i("files_reminders","Clear reminder")} – ${L(r)}`},iconSvgInline:()=>le,enabled:({nodes:e})=>e.length!==1?!1:!!e.at(0).attributes["reminder-due-date"],async exec({nodes:e}){const t=e.at(0);if(t.fileid)try{return await Z(t.fileid),t.attributes["reminder-due-date"]="",D("files:node:updated",t),!0}catch{return!1}return null},order:19},U='',h=X().setApp("files_reminders").detectUser().build(),pe=ie({__name:"SetCustomReminderModal",props:{node:{}},emits:["close"],setup(e,{emit:t}){const r=e,s=t,S=c(!1),C=c(!1),g=c(!0),o=c(),H=c(new Date);ae(()=>{const a=r.node.attributes["reminder-due-date"]?new Date(r.node.attributes["reminder-due-date"]):void 0;S.value=!!a,g.value=!0,C.value=!0,o.value=a??ce(),H.value=new Date}),ne(()=>{const a=document.getElementById("set-custom-reminder");a.focus(),S.value||a.showPicker()});async function z(){if(!(o.value instanceof Date)||isNaN(o.value.getTime())){f(i("files_reminders","Please choose a valid date & time"));return}try{await E(r.node.fileid,o.value);const a=r.node.clone();a.attributes["reminder-due-date"]=o.value.toISOString(),D("files:node:updated",a),N(i("files_reminders",'Reminder set for "{fileName}"',{fileName:r.node.displayname})),w()}catch(a){h.error("Failed to set reminder",{error:a}),f(i("files_reminders","Failed to set reminder"))}}async function j(){try{await Z(r.node.fileid);const a=r.node.clone();a.attributes["reminder-due-date"]="",D("files:node:updated",a),N(i("files_reminders",'Reminder cleared for "{fileName}"',{fileName:r.node.displayname})),w()}catch(a){h.error("Failed to clear reminder",{error:a}),f(i("files_reminders","Failed to clear reminder"))}}function w(){C.value=!1,s("close")}function G(){const a=document.getElementById("set-custom-reminder");g.value=a.checkValidity()}return(a,M)=>C.value?(v(),y(n(te),{key:0,name:n(i)("files_reminders","Set reminder for '{fileName}'",{fileName:e.node.displayname}),outTransition:"",size:"small",closeOnClickOutside:"",onClosing:w},{actions:d(()=>[b(n(k),{variant:"tertiary",onClick:w},{default:d(()=>[m(u(n(i)("files_reminders","Cancel")),1)]),_:1}),S.value?(v(),y(n(k),{key:0,onClick:j},{default:d(()=>[m(u(n(i)("files_reminders","Clear reminder")),1)]),_:1})):x("",!0),b(n(k),{disabled:!g.value,variant:"primary",form:"set-custom-reminder-form",type:"submit"},{default:d(()=>[m(u(n(i)("files_reminders","Set reminder")),1)]),_:1},8,["disabled"])]),default:d(()=>[se("form",{id:"set-custom-reminder-form",class:"custom-reminder-modal",onSubmit:oe(z,["prevent"])},[b(n(J),{id:"set-custom-reminder",modelValue:o.value,"onUpdate:modelValue":M[0]||(M[0]=K=>o.value=K),label:n(i)("files_reminders","Reminder at custom date & time"),min:H.value,required:!0,type:"datetime-local",onInput:G},null,8,["modelValue","label","min"]),g.value&&o.value?(v(),y(n(A),{key:0,type:"info"},{default:d(()=>[m(u(n(i)("files_reminders","We will remind you of this file"))+" ",1),b(n(ee),{timestamp:o.value},null,8,["timestamp"])]),_:1})):(v(),y(n(A),{key:1,type:"error"},{default:d(()=>[m(u(n(i)("files_reminders","Please choose a valid date & time")),1)]),_:1}))],32)]),_:1},8,["name"])):x("",!0)}}),ge=de(pe,[["__scopeId","data-v-1cc1857f"]]);async function q(e){await re(ge,{node:e})}const we={id:"reminder-status",inline:()=>!0,displayName:()=>"",title:({nodes:e})=>{const t=e.at(0),r=new Date(t.attributes["reminder-due-date"]);return`${i("files_reminders","Reminder set")} – ${L(r)}`},iconSvgInline:()=>U,enabled:({nodes:e})=>e.length!==1?!1:!!e.at(0).attributes["reminder-due-date"],async exec({nodes:e}){const t=e.at(0);return await q(t),null},order:-15},ve='',T="set-reminder-menu",ye={id:T,displayName:()=>i("files_reminders","Set reminder"),iconSvgInline:()=>U,enabled:({nodes:e,view:t})=>t.id==="trashbin"||e.length!==1?!1:e.at(0).attributes["reminder-due-date"]!==void 0,async exec(){return null},order:20},be={id:"set-reminder-custom",displayName:()=>i("files_reminders","Custom reminder"),title:()=>i("files_reminders","Reminder at custom date & time"),iconSvgInline:()=>ve,enabled:({nodes:e,view:t})=>t.id==="trashbin"||e.length!==1?!1:e.at(0).attributes["reminder-due-date"]!==void 0,parent:T,async exec({nodes:e}){const t=e.at(0);return q(t),null},order:22},P={dateTimePreset:p.LaterToday,label:i("files_reminders","Later today"),ariaLabel:i("files_reminders","Set reminder for later today"),dateString:"",verboseDateString:""},Y={dateTimePreset:p.Tomorrow,label:i("files_reminders","Tomorrow"),ariaLabel:i("files_reminders","Set reminder for tomorrow"),dateString:"",verboseDateString:""},$={dateTimePreset:p.ThisWeekend,label:i("files_reminders","This weekend"),ariaLabel:i("files_reminders","Set reminder for this weekend"),dateString:"",verboseDateString:""},R={dateTimePreset:p.NextWeek,label:i("files_reminders","Next week"),ariaLabel:i("files_reminders","Set reminder for next week"),dateString:"",verboseDateString:""};function De(){return[P,Y,$,R].forEach(e=>{const t=_(e.dateTimePreset);t&&(e.dateString=V(t),e.verboseDateString=L(t),setInterval(()=>{const r=_(e.dateTimePreset);r&&(e.dateString=V(r),e.verboseDateString=L(r))},1e3*30*60))}),[P,Y,$,R].map(_e)}function _e(e){return{id:`set-reminder-${e.dateTimePreset}`,displayName:()=>`${e.label} – ${e.dateString}`,title:()=>`${e.ariaLabel} – ${e.verboseDateString}`,iconSvgInline:()=>"",enabled:({nodes:t,view:r})=>r.id==="trashbin"||t.length!==1?!1:t.at(0).attributes["reminder-due-date"]!==void 0&&!!_(e.dateTimePreset),parent:T,async exec({nodes:t}){const r=t.at(0);if(!r.fileid)return h.error("Failed to set reminder, missing file id"),f(i("files_reminders","Failed to set reminder")),null;try{const s=_(e.dateTimePreset);await E(r.fileid,s),r.attributes["reminder-due-date"]=s.toISOString(),D("files:node:updated",r),N(i("files_reminders",'Reminder set for "{fileName}"',{fileName:r.basename}))}catch(s){h.error("Failed to set reminder",{error:s}),f(i("files_reminders","Failed to set reminder"))}return null},order:21}}Q("nc:reminder-due-date",{nc:"http://nextcloud.org/ns"}),l(we),l(fe),l(ye),l(be),De().forEach(l); +import{b as l}from"./index-DHYHHtgJ.chunk.mjs";import{c as X}from"./dav-BZymqOt7.chunk.mjs";import{e as y,g as K}from"./index-Bndk0DrU.chunk.mjs";import{a as W,t as i}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as B}from"./index-2a6kOrDy.chunk.mjs";import{b as O}from"./createElementId-DhjFt1I9-DdwCqgaq.chunk.mjs";import"./PencilOutline-Qk8GS-l0.chunk.mjs";import"./index-DblWoJ6I.chunk.mjs";import{N as ee}from"./NcBreadcrumbs-5gl8Syfa-DJcXDkmn.chunk.mjs";import"./NcDateTime.vue_vue_type_script_setup_true_lang-B4upiZjL-CDFdx-HI.chunk.mjs";import{f as te}from"./NcModal-kyWZ3UFC-CC38MZrD.chunk.mjs";import"./NcAvatar-ruClKRzS-gxaDTlsM.chunk.mjs";import"./NcContent-D69ktIEB-CM64XV1n.chunk.mjs";import{N as C}from"./autolink-U5pBzLgI-D1NMH9bI.chunk.mjs";import"./Web-DS-WBH9c.chunk.mjs";import"./NcCheckboxRadioSwitch-D0gFwEVl-BbcIGLyw.chunk.mjs";import"./Plus-BtJ3xjfW.chunk.mjs";import"./NcColorPicker-D07Se8Xb-D3qyscwi.chunk.mjs";import"./TrayArrowDown-D7fMRVjO.chunk.mjs";import{N as re,s as ie}from"./index-CrY7NZWO.chunk.mjs";import"./NcSelect-B1uITk_3-0e2p8qEi.chunk.mjs";import"./NcEmojiPicker-DGgqTnHp-BmMIlAzR.chunk.mjs";import"./NcEmptyContent-CDgWCt_m-Dz_uR0NU.chunk.mjs";import"./NcRichText-D_ssz6sB-ByGnwwpX.chunk.mjs";/* empty css */import"./NcInputField-CPL-a_MM-R1bsVnGI.chunk.mjs";import{N as A}from"./mdi--cNatcgF.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-CKSnPt2n.chunk.mjs";import"./TrashCanOutline-DmYYOQ4b.chunk.mjs";import"./index-CqVYsIAH.chunk.mjs";import"./ContentCopy-ljx8CODs.chunk.mjs";import"./NcUserBubble-BE6yD-R0-BAJg1c4w.chunk.mjs";import"./NcUserStatusIcon-JWiuiAXe-DUOABbOJ.chunk.mjs";import"./colors-BfjxNgsx-YlZbKUzS.chunk.mjs";import{f as ne,R as ae,k as se,o as w,g as D,w as d,b as oe,M as de,h as T,u as a,v as m,t as u,e as F,r as c,F as le}from"./runtime-dom.esm-bundler-CKxgtjB6.chunk.mjs";import{a as f,d as N}from"./index-C1xmmKTZ-DF4bDPEh.chunk.mjs";import{a as me}from"./index-BgmsSgl5.chunk.mjs";import"./folder-29HuacU_-DcJI3kE4.chunk.mjs";import"./index-sH3U_332.chunk.mjs";import"./index-D4QioFSy.chunk.mjs";const ue='';async function E(e,t){const r=O("/apps/files_reminders/api/v1/{fileId}",{fileId:e});return(await B.put(r,{dueDate:t.toISOString()})).data.ocs.data}async function Z(e){const t=O("/apps/files_reminders/api/v1/{fileId}",{fileId:e});return(await B.delete(t,{validateStatus:r=>r===200||r===404})).data.ocs.data}var p=(e=>(e.LaterToday="later-today",e.Tomorrow="tomorrow",e.ThisWeekend="this-weekend",e.NextWeek="next-week",e))(p||{});function I(){const e=new Date;return e.setHours(0,0,0,0),e.setDate(e.getDate()-e.getDay()+1),new Date(e)}function M(e){new Date(e).setHours(0,0,0,0);const t=new Date(e.getFullYear(),0,1,0,0,0,0),r=(e.getTime()-t.getTime())/864e5;return Math.ceil((r+t.getDay()+1)/7)}function ce(e,t){return M(e)===M(t)&&e.getFullYear()===t.getFullYear()}function fe(e,t){return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()}function b(e){return{"later-today":()=>{const t=new Date,r=new Date;r.setHours(18,0,0,0);const s=new Date;return s.setHours(17,0,0,0),t>=s?null:r},tomorrow:()=>{const t=new Date,r=new Date;return r.setDate(t.getDate()+1),r.setHours(8,0,0,0),r},"this-weekend":()=>{const t=new Date;if([5,6,0].includes(t.getDay()))return null;const r=new Date,s=I();return r.setDate(s.getDate()+5),r.setHours(8,0,0,0),r},"next-week":()=>{if(new Date().getDay()===0)return null;const t=new Date,r=I();return t.setDate(r.getDate()+7),t.setHours(8,0,0,0),t}}[e]()}function pe(){const e=new Date,t=new Date;return t.setHours(e.getHours()+2,0,0,0),t}function V(e){let t={hour:"numeric",minute:"2-digit"};const r=new Date;return fe(e,r)||(t={...t,weekday:"short"}),ce(e,r)||(t={...t,month:"short",day:"numeric"}),e.getFullYear()!==r.getFullYear()&&(t={...t,year:"numeric"}),e.toLocaleString(W(),t)}function h(e){let t={month:"long",day:"numeric",weekday:"long",hour:"numeric",minute:"2-digit"};const r=new Date;return e.getFullYear()!==r.getFullYear()&&(t={...t,year:"numeric"}),e.toLocaleString(W(),t)}const ge={id:"clear-reminder",displayName:()=>i("files_reminders","Clear reminder"),title:({nodes:e})=>{const t=e.at(0),r=new Date(t.attributes["reminder-due-date"]);return`${i("files_reminders","Clear reminder")} – ${h(r)}`},iconSvgInline:()=>ue,enabled:({nodes:e})=>e.length!==1?!1:!!e.at(0).attributes["reminder-due-date"],async exec({nodes:e}){const t=e.at(0);if(t.fileid)try{return await Z(t.fileid),t.attributes["reminder-due-date"]="",y("files:node:updated",t),!0}catch{return!1}return null},order:19},U='',L=K().setApp("files_reminders").detectUser().build(),ve=ne({__name:"SetCustomReminderModal",props:{node:{}},emits:["close"],setup(e,{emit:t}){const r=e,s=t,_=c(!1),S=c(!1),g=c(!0),o=c(),k=c(new Date),z=le(()=>{const n=te(o.value??0);return k.value.getTime()>=(o.value?.getTime()??0)?i("files_reminders","We reminded you of this file {relativeDueDate}",{relativeDueDate:n}):i("files_reminders","We will remind you of this file {relativeDueDate}",{relativeDueDate:n})});ae(()=>{const n=r.node.attributes["reminder-due-date"]?new Date(r.node.attributes["reminder-due-date"]):void 0;_.value=!!n,g.value=!0,S.value=!0,o.value=n??pe(),k.value=new Date}),se(()=>{const n=document.getElementById("set-custom-reminder");n.focus(),_.value||n.showPicker()});async function j(){if(!(o.value instanceof Date)||isNaN(o.value.getTime())){f(i("files_reminders","Please choose a valid date & time"));return}try{await E(r.node.fileid,o.value);const n=r.node.clone();n.attributes["reminder-due-date"]=o.value.toISOString(),y("files:node:updated",n),N(i("files_reminders",'Reminder set for "{fileName}"',{fileName:r.node.displayname})),v()}catch(n){L.error("Failed to set reminder",{error:n}),f(i("files_reminders","Failed to set reminder"))}}async function G(){try{await Z(r.node.fileid);const n=r.node.clone();n.attributes["reminder-due-date"]="",y("files:node:updated",n),N(i("files_reminders",'Reminder cleared for "{fileName}"',{fileName:r.node.displayname})),v()}catch(n){L.error("Failed to clear reminder",{error:n}),f(i("files_reminders","Failed to clear reminder"))}}function v(){S.value=!1,s("close")}function J(){const n=document.getElementById("set-custom-reminder");g.value=n.checkValidity()}return(n,H)=>S.value?(w(),D(a(re),{key:0,name:a(i)("files_reminders","Set reminder for '{fileName}'",{fileName:e.node.displayname}),outTransition:"",size:"small",closeOnClickOutside:"",onClosing:v},{actions:d(()=>[T(a(C),{variant:"tertiary",onClick:v},{default:d(()=>[m(u(a(i)("files_reminders","Cancel")),1)]),_:1}),_.value?(w(),D(a(C),{key:0,onClick:G},{default:d(()=>[m(u(a(i)("files_reminders","Clear reminder")),1)]),_:1})):F("",!0),T(a(C),{disabled:!g.value,variant:"primary",form:"set-custom-reminder-form",type:"submit"},{default:d(()=>[m(u(a(i)("files_reminders","Set reminder")),1)]),_:1},8,["disabled"])]),default:d(()=>[oe("form",{id:"set-custom-reminder-form",class:"custom-reminder-modal",onSubmit:de(j,["prevent"])},[T(a(ee),{id:"set-custom-reminder",modelValue:o.value,"onUpdate:modelValue":H[0]||(H[0]=Q=>o.value=Q),label:a(i)("files_reminders","Reminder at custom date & time"),min:k.value,required:!0,type:"datetime-local",onInput:J},null,8,["modelValue","label","min"]),g.value&&o.value?(w(),D(a(A),{key:0,type:"info"},{default:d(()=>[m(u(z.value),1)]),_:1})):(w(),D(a(A),{key:1,type:"error"},{default:d(()=>[m(u(a(i)("files_reminders","Please choose a valid date & time")),1)]),_:1}))],32)]),_:1},8,["name"])):F("",!0)}}),we=me(ve,[["__scopeId","data-v-d7127154"]]);async function q(e){await ie(we,{node:e})}const De={id:"reminder-status",inline:()=>!0,displayName:()=>"",title:({nodes:e})=>{const t=e.at(0),r=new Date(t.attributes["reminder-due-date"]);return`${i("files_reminders","Reminder set")} – ${h(r)}`},iconSvgInline:()=>U,enabled:({nodes:e})=>{if(e.length!==1)return!1;const t=e.at(0).attributes["reminder-due-date"],r=new Date;return!!t&&new Date(t)>r},async exec({nodes:e}){const t=e.at(0);return await q(t),null},order:-15},ye='',x="set-reminder-menu",be={id:x,displayName:()=>i("files_reminders","Set reminder"),iconSvgInline:()=>U,enabled:({nodes:e,view:t})=>t.id==="trashbin"||e.length!==1?!1:e.at(0).attributes["reminder-due-date"]!==void 0,async exec(){return null},order:20},he={id:"set-reminder-custom",displayName:()=>i("files_reminders","Custom reminder"),title:()=>i("files_reminders","Reminder at custom date & time"),iconSvgInline:()=>ye,enabled:({nodes:e,view:t})=>t.id==="trashbin"||e.length!==1?!1:e.at(0).attributes["reminder-due-date"]!==void 0,parent:x,async exec({nodes:e}){const t=e.at(0);return q(t),null},order:22},P={dateTimePreset:p.LaterToday,label:i("files_reminders","Later today"),ariaLabel:i("files_reminders","Set reminder for later today"),dateString:"",verboseDateString:""},Y={dateTimePreset:p.Tomorrow,label:i("files_reminders","Tomorrow"),ariaLabel:i("files_reminders","Set reminder for tomorrow"),dateString:"",verboseDateString:""},$={dateTimePreset:p.ThisWeekend,label:i("files_reminders","This weekend"),ariaLabel:i("files_reminders","Set reminder for this weekend"),dateString:"",verboseDateString:""},R={dateTimePreset:p.NextWeek,label:i("files_reminders","Next week"),ariaLabel:i("files_reminders","Set reminder for next week"),dateString:"",verboseDateString:""};function Le(){return[P,Y,$,R].forEach(e=>{const t=b(e.dateTimePreset);t&&(e.dateString=V(t),e.verboseDateString=h(t),setInterval(()=>{const r=b(e.dateTimePreset);r&&(e.dateString=V(r),e.verboseDateString=h(r))},1e3*30*60))}),[P,Y,$,R].map(_e)}function _e(e){return{id:`set-reminder-${e.dateTimePreset}`,displayName:()=>`${e.label} – ${e.dateString}`,title:()=>`${e.ariaLabel} – ${e.verboseDateString}`,iconSvgInline:()=>"",enabled:({nodes:t,view:r})=>r.id==="trashbin"||t.length!==1?!1:t.at(0).attributes["reminder-due-date"]!==void 0&&!!b(e.dateTimePreset),parent:x,async exec({nodes:t}){const r=t.at(0);if(!r.fileid)return L.error("Failed to set reminder, missing file id"),f(i("files_reminders","Failed to set reminder")),null;try{const s=b(e.dateTimePreset);await E(r.fileid,s),r.attributes["reminder-due-date"]=s.toISOString(),y("files:node:updated",r),N(i("files_reminders",'Reminder set for "{fileName}"',{fileName:r.basename}))}catch(s){L.error("Failed to set reminder",{error:s}),f(i("files_reminders","Failed to set reminder"))}return null},order:21}}X("nc:reminder-due-date",{nc:"http://nextcloud.org/ns"}),l(De),l(ge),l(be),l(he),Le().forEach(l); //# sourceMappingURL=files_reminders-init.mjs.map diff --git a/dist/files_reminders-init.mjs.map b/dist/files_reminders-init.mjs.map index c09697baf088e..aee73e17f8b61 100644 --- a/dist/files_reminders-init.mjs.map +++ b/dist/files_reminders-init.mjs.map @@ -1 +1 @@ -{"version":3,"file":"files_reminders-init.mjs","sources":["../node_modules/@mdi/svg/svg/alarm-off.svg?raw","../build/frontend/apps/files_reminders/src/services/reminderService.ts","../build/frontend/apps/files_reminders/src/shared/utils.ts","../build/frontend/apps/files_reminders/src/files_actions/clearReminderAction.ts","../node_modules/@mdi/svg/svg/alarm.svg?raw","../build/frontend/apps/files_reminders/src/shared/logger.ts","../build/frontend/apps/files_reminders/src/components/SetCustomReminderModal.vue","../build/frontend/apps/files_reminders/src/services/customPicker.ts","../build/frontend/apps/files_reminders/src/files_actions/reminderStatusAction.ts","../node_modules/@mdi/svg/svg/calendar-clock.svg?raw","../build/frontend/apps/files_reminders/src/files_actions/setReminderMenuAction.ts","../build/frontend/apps/files_reminders/src/files_actions/setReminderCustomAction.ts","../build/frontend/apps/files_reminders/src/files_actions/setReminderSuggestionActions.ts","../build/frontend/apps/files_reminders/src/files-init.ts"],"sourcesContent":["export default \"\"","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport axios from '@nextcloud/axios'\nimport { generateOcsUrl } from '@nextcloud/router'\n\ninterface Reminder {\n\tdueDate: null | Date\n}\n\n/**\n * Get the reminder for a specific file\n *\n * @param fileId - The file id to get the reminder for\n */\nexport async function getReminder(fileId: number): Promise {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\tconst response = await axios.get(url)\n\tconst dueDate = response.data.ocs.data.dueDate ? new Date(response.data.ocs.data.dueDate) : null\n\n\treturn {\n\t\tdueDate,\n\t}\n}\n\n/**\n * Set a reminder for a specific file\n *\n * @param fileId - The file id to set the reminder for\n * @param dueDate - The due date for the reminder\n */\nexport async function setReminder(fileId: number, dueDate: Date): Promise<[]> {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\n\tconst response = await axios.put(url, {\n\t\tdueDate: dueDate.toISOString(), // timezone of string is always UTC\n\t})\n\n\treturn response.data.ocs.data\n}\n\n/**\n * Clear the reminder for a specific file\n *\n * @param fileId - The file id to clear the reminder for\n */\nexport async function clearReminder(fileId: number): Promise<[]> {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\tconst response = await axios.delete(url)\n\n\treturn response.data.ocs.data\n}\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCanonicalLocale } from '@nextcloud/l10n'\n\nexport enum DateTimePreset {\n\tLaterToday = 'later-today',\n\tTomorrow = 'tomorrow',\n\tThisWeekend = 'this-weekend',\n\tNextWeek = 'next-week',\n}\n\n/**\n *\n */\nfunction getFirstWorkdayOfWeek() {\n\tconst now = new Date()\n\tnow.setHours(0, 0, 0, 0)\n\tnow.setDate(now.getDate() - now.getDay() + 1)\n\treturn new Date(now)\n}\n\n/**\n * @param date - The date to get the week number for\n */\nfunction getWeek(date: Date) {\n\tconst dateClone = new Date(date)\n\tdateClone.setHours(0, 0, 0, 0)\n\tconst firstDayOfYear = new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\n\tconst daysFromFirstDay = (date.getTime() - firstDayOfYear.getTime()) / 86400000\n\treturn Math.ceil((daysFromFirstDay + firstDayOfYear.getDay() + 1) / 7)\n}\n\n/**\n * @param a - First date\n * @param b - Second date\n */\nfunction isSameWeek(a: Date, b: Date) {\n\treturn getWeek(a) === getWeek(b)\n\t\t&& a.getFullYear() === b.getFullYear()\n}\n\n/**\n * @param a - First date\n * @param b - Second date\n */\nfunction isSameDate(a: Date, b: Date) {\n\treturn a.getDate() === b.getDate()\n\t\t&& a.getMonth() === b.getMonth()\n\t\t&& a.getFullYear() === b.getFullYear()\n}\n\n/**\n * @param dateTime - The preset to get the date for\n */\nexport function getDateTime(dateTime: DateTimePreset): null | Date {\n\tconst matchPreset: Record null | Date> = {\n\t\t[DateTimePreset.LaterToday]: () => {\n\t\t\tconst now = new Date()\n\t\t\tconst evening = new Date()\n\t\t\tevening.setHours(18, 0, 0, 0)\n\t\t\tconst cutoff = new Date()\n\t\t\tcutoff.setHours(17, 0, 0, 0)\n\t\t\tif (now >= cutoff) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn evening\n\t\t},\n\n\t\t[DateTimePreset.Tomorrow]: () => {\n\t\t\tconst now = new Date()\n\t\t\tconst day = new Date()\n\t\t\tday.setDate(now.getDate() + 1)\n\t\t\tday.setHours(8, 0, 0, 0)\n\t\t\treturn day\n\t\t},\n\n\t\t[DateTimePreset.ThisWeekend]: () => {\n\t\t\tconst today = new Date()\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\t5, // Friday\n\t\t\t\t\t6, // Saturday\n\t\t\t\t\t0, // Sunday\n\t\t\t\t].includes(today.getDay())\n\t\t\t) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst saturday = new Date()\n\t\t\tconst firstWorkdayOfWeek = getFirstWorkdayOfWeek()\n\t\t\tsaturday.setDate(firstWorkdayOfWeek.getDate() + 5)\n\t\t\tsaturday.setHours(8, 0, 0, 0)\n\t\t\treturn saturday\n\t\t},\n\n\t\t[DateTimePreset.NextWeek]: () => {\n\t\t\tconst today = new Date()\n\t\t\tif (today.getDay() === 0) { // Sunday\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst workday = new Date()\n\t\t\tconst firstWorkdayOfWeek = getFirstWorkdayOfWeek()\n\t\t\tworkday.setDate(firstWorkdayOfWeek.getDate() + 7)\n\t\t\tworkday.setHours(8, 0, 0, 0)\n\t\t\treturn workday\n\t\t},\n\t}\n\n\treturn matchPreset[dateTime]()\n}\n\n/**\n *\n */\nexport function getInitialCustomDueDate(): Date {\n\tconst now = new Date()\n\tconst dueDate = new Date()\n\tdueDate.setHours(now.getHours() + 2, 0, 0, 0)\n\treturn dueDate\n}\n\n/**\n * @param dueDate - The date to format as a string\n */\nexport function getDateString(dueDate: Date): string {\n\tlet formatOptions: Intl.DateTimeFormatOptions = {\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t}\n\n\tconst today = new Date()\n\n\tif (!isSameDate(dueDate, today)) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tweekday: 'short',\n\t\t}\n\t}\n\n\tif (!isSameWeek(dueDate, today)) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t}\n\t}\n\n\tif (dueDate.getFullYear() !== today.getFullYear()) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tyear: 'numeric',\n\t\t}\n\t}\n\n\treturn dueDate.toLocaleString(\n\t\tgetCanonicalLocale(),\n\t\tformatOptions,\n\t)\n}\n\n/**\n * @param dueDate - The date to format as a string\n */\nexport function getVerboseDateString(dueDate: Date): string {\n\tlet formatOptions: Intl.DateTimeFormatOptions = {\n\t\tmonth: 'long',\n\t\tday: 'numeric',\n\t\tweekday: 'long',\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t}\n\n\tconst today = new Date()\n\n\tif (dueDate.getFullYear() !== today.getFullYear()) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tyear: 'numeric',\n\t\t}\n\t}\n\n\treturn dueDate.toLocaleString(\n\t\tgetCanonicalLocale(),\n\t\tformatOptions,\n\t)\n}\n","/*!\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmOffSvg from '@mdi/svg/svg/alarm-off.svg?raw'\nimport { emit } from '@nextcloud/event-bus'\nimport { t } from '@nextcloud/l10n'\nimport { clearReminder } from '../services/reminderService.ts'\nimport { getVerboseDateString } from '../shared/utils.ts'\n\nexport const action: IFileAction = {\n\tid: 'clear-reminder',\n\n\tdisplayName: () => t('files_reminders', 'Clear reminder'),\n\n\ttitle: ({ nodes }) => {\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = new Date(node.attributes['reminder-due-date'])\n\t\treturn `${t('files_reminders', 'Clear reminder')} – ${getVerboseDateString(dueDate)}`\n\t},\n\n\ticonSvgInline: () => AlarmOffSvg,\n\n\tenabled: ({ nodes }) => {\n\t\t// Only allow on a single node\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn Boolean(dueDate)\n\t},\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tif (node.fileid) {\n\t\t\ttry {\n\t\t\t\tawait clearReminder(node.fileid)\n\t\t\t\tnode.attributes['reminder-due-date'] = ''\n\t\t\t\temit('files:node:updated', node)\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn null\n\t},\n\n\torder: 19,\n}\n","export default \"\"","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getLoggerBuilder } from '@nextcloud/logger'\n\nexport const logger = getLoggerBuilder()\n\t.setApp('files_reminders')\n\t.detectUser()\n\t.build()\n","\n\n\n\n\n\n\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { INode } from '@nextcloud/files'\n\nimport { spawnDialog } from '@nextcloud/vue'\nimport SetCustomReminderModal from '../components/SetCustomReminderModal.vue'\n\n/**\n * @param node - The file or folder node to set the custom reminder for\n */\nexport async function pickCustomDate(node: INode): Promise {\n\tawait spawnDialog(SetCustomReminderModal, {\n\t\tnode,\n\t})\n}\n","/*!\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmSvg from '@mdi/svg/svg/alarm.svg?raw'\nimport { t } from '@nextcloud/l10n'\nimport { pickCustomDate } from '../services/customPicker.ts'\nimport { getVerboseDateString } from '../shared/utils.ts'\n\nexport const action: IFileAction = {\n\tid: 'reminder-status',\n\n\tinline: () => true,\n\n\tdisplayName: () => '',\n\n\ttitle: ({ nodes }) => {\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = new Date(node.attributes['reminder-due-date'])\n\t\treturn `${t('files_reminders', 'Reminder set')} – ${getVerboseDateString(dueDate)}`\n\t},\n\n\ticonSvgInline: () => AlarmSvg,\n\n\tenabled: ({ nodes }) => {\n\t\t// Only allow on a single node\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn Boolean(dueDate)\n\t},\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tawait pickCustomDate(node)\n\t\treturn null\n\t},\n\n\torder: -15,\n}\n","export default \"\"","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmSvg from '@mdi/svg/svg/alarm.svg?raw'\nimport { translate as t } from '@nextcloud/l10n'\n\nexport const SET_REMINDER_MENU_ID = 'set-reminder-menu'\n\nexport const action: IFileAction = {\n\tid: SET_REMINDER_MENU_ID,\n\tdisplayName: () => t('files_reminders', 'Set reminder'),\n\ticonSvgInline: () => AlarmSvg,\n\n\tenabled: ({ nodes, view }) => {\n\t\tif (view.id === 'trashbin') {\n\t\t\treturn false\n\t\t}\n\t\t// Only allow on a single INode\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn dueDate !== undefined\n\t},\n\n\tasync exec() {\n\t\treturn null\n\t},\n\n\torder: 20,\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport CalendarClockSvg from '@mdi/svg/svg/calendar-clock.svg?raw'\nimport { t } from '@nextcloud/l10n'\nimport { pickCustomDate } from '../services/customPicker.ts'\nimport { SET_REMINDER_MENU_ID } from './setReminderMenuAction.ts'\n\nexport const action: IFileAction = {\n\tid: 'set-reminder-custom',\n\tdisplayName: () => t('files_reminders', 'Custom reminder'),\n\ttitle: () => t('files_reminders', 'Reminder at custom date & time'),\n\ticonSvgInline: () => CalendarClockSvg,\n\n\tenabled: ({ nodes, view }) => {\n\t\tif (view.id === 'trashbin') {\n\t\t\treturn false\n\t\t}\n\t\t// Only allow on a single INode\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn dueDate !== undefined\n\t},\n\n\tparent: SET_REMINDER_MENU_ID,\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tpickCustomDate(node)\n\t\treturn null\n\t},\n\n\t// After presets\n\torder: 22,\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport { showError, showSuccess } from '@nextcloud/dialogs'\nimport { emit } from '@nextcloud/event-bus'\nimport { t } from '@nextcloud/l10n'\nimport { setReminder } from '../services/reminderService.ts'\nimport { logger } from '../shared/logger.ts'\nimport { DateTimePreset, getDateString, getDateTime, getVerboseDateString } from '../shared/utils.ts'\nimport { SET_REMINDER_MENU_ID } from './setReminderMenuAction.ts'\n\nimport './setReminderSuggestionActions.scss'\n\ninterface ReminderOption {\n\tdateTimePreset: DateTimePreset\n\tlabel: string\n\tariaLabel: string\n\tdateString?: string\n\tverboseDateString?: string\n\taction?: () => Promise\n}\n\nconst laterToday: ReminderOption = {\n\tdateTimePreset: DateTimePreset.LaterToday,\n\tlabel: t('files_reminders', 'Later today'),\n\tariaLabel: t('files_reminders', 'Set reminder for later today'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst tomorrow: ReminderOption = {\n\tdateTimePreset: DateTimePreset.Tomorrow,\n\tlabel: t('files_reminders', 'Tomorrow'),\n\tariaLabel: t('files_reminders', 'Set reminder for tomorrow'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst thisWeekend: ReminderOption = {\n\tdateTimePreset: DateTimePreset.ThisWeekend,\n\tlabel: t('files_reminders', 'This weekend'),\n\tariaLabel: t('files_reminders', 'Set reminder for this weekend'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst nextWeek: ReminderOption = {\n\tdateTimePreset: DateTimePreset.NextWeek,\n\tlabel: t('files_reminders', 'Next week'),\n\tariaLabel: t('files_reminders', 'Set reminder for next week'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\n/**\n * Get all set reminder suggestion actions from presets\n */\nexport function getSetReminderSuggestionActions() {\n\t[laterToday, tomorrow, thisWeekend, nextWeek].forEach((option) => {\n\t\t// Generate the initial date string\n\t\tconst dateTime = getDateTime(option.dateTimePreset)\n\t\tif (!dateTime) {\n\t\t\treturn\n\t\t}\n\t\toption.dateString = getDateString(dateTime)\n\t\toption.verboseDateString = getVerboseDateString(dateTime)\n\n\t\t// Update the date string every 30 minutes\n\t\tsetInterval(() => {\n\t\t\tconst dateTime = getDateTime(option.dateTimePreset)\n\t\t\tif (!dateTime) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// update the submenu remind options strings\n\t\t\toption.dateString = getDateString(dateTime)\n\t\t\toption.verboseDateString = getVerboseDateString(dateTime)\n\t\t}, 1000 * 30 * 60)\n\t})\n\n\t// Generate the default preset actions\n\treturn [laterToday, tomorrow, thisWeekend, nextWeek]\n\t\t.map(generateFileAction)\n}\n\n/**\n * Generate a file action for the given option\n *\n * @param option The option to generate the action for\n * @return The file action or null if the option should not be shown\n */\nfunction generateFileAction(option: ReminderOption): IFileAction {\n\treturn {\n\t\tid: `set-reminder-${option.dateTimePreset}`,\n\t\tdisplayName: () => `${option.label} – ${option.dateString}`,\n\t\ttitle: () => `${option.ariaLabel} – ${option.verboseDateString}`,\n\n\t\t// Empty svg to hide the icon\n\t\ticonSvgInline: () => '',\n\n\t\tenabled: ({ nodes, view }) => {\n\t\t\tif (view.id === 'trashbin') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Only allow on a single INode\n\t\t\tif (nodes.length !== 1) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst node = nodes.at(0)!\n\t\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\t\treturn dueDate !== undefined && Boolean(getDateTime(option.dateTimePreset))\n\t\t},\n\n\t\tparent: SET_REMINDER_MENU_ID,\n\n\t\tasync exec({ nodes }) {\n\t\t\t// Can't really happen, but just in case™\n\t\t\tconst node = nodes.at(0)!\n\t\t\tif (!node.fileid) {\n\t\t\t\tlogger.error('Failed to set reminder, missing file id')\n\t\t\t\tshowError(t('files_reminders', 'Failed to set reminder'))\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Set the reminder\n\t\t\ttry {\n\t\t\t\tconst dateTime = getDateTime(option.dateTimePreset)!\n\t\t\t\tawait setReminder(node.fileid, dateTime)\n\t\t\t\tnode.attributes['reminder-due-date'] = dateTime.toISOString()\n\t\t\t\temit('files:node:updated', node)\n\t\t\t\tshowSuccess(t('files_reminders', 'Reminder set for \"{fileName}\"', { fileName: node.basename }))\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('Failed to set reminder', { error })\n\t\t\t\tshowError(t('files_reminders', 'Failed to set reminder'))\n\t\t\t}\n\t\t\t// Silent success as we display our own notification\n\t\t\treturn null\n\t\t},\n\n\t\torder: 21,\n\t}\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { registerFileAction } from '@nextcloud/files'\nimport { registerDavProperty } from '@nextcloud/files/dav'\nimport { action as clearAction } from './files_actions/clearReminderAction.ts'\nimport { action as statusAction } from './files_actions/reminderStatusAction.ts'\nimport { action as customAction } from './files_actions/setReminderCustomAction.ts'\nimport { action as menuAction } from './files_actions/setReminderMenuAction.ts'\nimport { getSetReminderSuggestionActions } from './files_actions/setReminderSuggestionActions.ts'\n\nregisterDavProperty('nc:reminder-due-date', { nc: 'http://nextcloud.org/ns' })\n\nregisterFileAction(statusAction)\nregisterFileAction(clearAction)\nregisterFileAction(menuAction)\nregisterFileAction(customAction)\ngetSetReminderSuggestionActions()\n\t.forEach(registerFileAction)\n"],"names":["AlarmOffSvg","setReminder","fileId","dueDate","url","generateOcsUrl","axios","clearReminder","DateTimePreset","getFirstWorkdayOfWeek","now","getWeek","date","firstDayOfYear","daysFromFirstDay","isSameWeek","a","b","isSameDate","getDateTime","dateTime","evening","cutoff","day","today","saturday","firstWorkdayOfWeek","workday","getInitialCustomDueDate","getDateString","formatOptions","getCanonicalLocale","getVerboseDateString","action","t","nodes","node","emit","AlarmSvg","logger","getLoggerBuilder","props","__props","__emit","hasDueDate","ref","opened","isValid","customDueDate","nowDate","onBeforeMount","onMounted","input","setCustom","showError","emitEventBus","showSuccess","onClose","error","clear","onInput","_createBlock","_unref","NcDialog","_createVNode","NcButton","_createElementVNode","NcDateTimePickerNative","$event","NcNoteCard","_createTextVNode","_toDisplayString","NcDateTime","pickCustomDate","spawnDialog","SetCustomReminderModal","CalendarClockSvg","SET_REMINDER_MENU_ID","view","laterToday","tomorrow","thisWeekend","nextWeek","getSetReminderSuggestionActions","option","generateFileAction","registerDavProperty","registerFileAction","statusAction","clearAction","menuAction","customAction"],"mappings":"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","x_google_ignoreList":[0,4,9]} \ No newline at end of file +{"version":3,"file":"files_reminders-init.mjs","sources":["../node_modules/@mdi/svg/svg/alarm-off.svg?raw","../build/frontend/apps/files_reminders/src/services/reminderService.ts","../build/frontend/apps/files_reminders/src/shared/utils.ts","../build/frontend/apps/files_reminders/src/files_actions/clearReminderAction.ts","../node_modules/@mdi/svg/svg/alarm.svg?raw","../build/frontend/apps/files_reminders/src/shared/logger.ts","../build/frontend/apps/files_reminders/src/components/SetCustomReminderModal.vue","../build/frontend/apps/files_reminders/src/services/customPicker.ts","../build/frontend/apps/files_reminders/src/files_actions/reminderStatusAction.ts","../node_modules/@mdi/svg/svg/calendar-clock.svg?raw","../build/frontend/apps/files_reminders/src/files_actions/setReminderMenuAction.ts","../build/frontend/apps/files_reminders/src/files_actions/setReminderCustomAction.ts","../build/frontend/apps/files_reminders/src/files_actions/setReminderSuggestionActions.ts","../build/frontend/apps/files_reminders/src/files-init.ts"],"sourcesContent":["export default \"\"","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport axios from '@nextcloud/axios'\nimport { generateOcsUrl } from '@nextcloud/router'\n\ninterface Reminder {\n\tdueDate: null | Date\n}\n\n/**\n * Get the reminder for a specific file\n *\n * @param fileId - The file id to get the reminder for\n */\nexport async function getReminder(fileId: number): Promise {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\tconst response = await axios.get(url)\n\tconst dueDate = response.data.ocs.data.dueDate ? new Date(response.data.ocs.data.dueDate) : null\n\n\treturn {\n\t\tdueDate,\n\t}\n}\n\n/**\n * Set a reminder for a specific file\n *\n * @param fileId - The file id to set the reminder for\n * @param dueDate - The due date for the reminder\n */\nexport async function setReminder(fileId: number, dueDate: Date): Promise<[]> {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\n\tconst response = await axios.put(url, {\n\t\tdueDate: dueDate.toISOString(), // timezone of string is always UTC\n\t})\n\n\treturn response.data.ocs.data\n}\n\n/**\n * Clear the reminder for a specific file\n *\n * @param fileId - The file id to clear the reminder for\n */\nexport async function clearReminder(fileId: number): Promise<[]> {\n\tconst url = generateOcsUrl('/apps/files_reminders/api/v1/{fileId}', { fileId })\n\tconst response = await axios.delete(url, {\n\t\t// We allow 404 as it means there is no reminder to delete,\n\t\t// which is the desired state after this function is called anyway\n\t\tvalidateStatus: (status) => status === 200 || status === 404,\n\t})\n\n\treturn response.data.ocs.data\n}\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCanonicalLocale } from '@nextcloud/l10n'\n\nexport enum DateTimePreset {\n\tLaterToday = 'later-today',\n\tTomorrow = 'tomorrow',\n\tThisWeekend = 'this-weekend',\n\tNextWeek = 'next-week',\n}\n\n/**\n *\n */\nfunction getFirstWorkdayOfWeek() {\n\tconst now = new Date()\n\tnow.setHours(0, 0, 0, 0)\n\tnow.setDate(now.getDate() - now.getDay() + 1)\n\treturn new Date(now)\n}\n\n/**\n * @param date - The date to get the week number for\n */\nfunction getWeek(date: Date) {\n\tconst dateClone = new Date(date)\n\tdateClone.setHours(0, 0, 0, 0)\n\tconst firstDayOfYear = new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\n\tconst daysFromFirstDay = (date.getTime() - firstDayOfYear.getTime()) / 86400000\n\treturn Math.ceil((daysFromFirstDay + firstDayOfYear.getDay() + 1) / 7)\n}\n\n/**\n * @param a - First date\n * @param b - Second date\n */\nfunction isSameWeek(a: Date, b: Date) {\n\treturn getWeek(a) === getWeek(b)\n\t\t&& a.getFullYear() === b.getFullYear()\n}\n\n/**\n * @param a - First date\n * @param b - Second date\n */\nfunction isSameDate(a: Date, b: Date) {\n\treturn a.getDate() === b.getDate()\n\t\t&& a.getMonth() === b.getMonth()\n\t\t&& a.getFullYear() === b.getFullYear()\n}\n\n/**\n * @param dateTime - The preset to get the date for\n */\nexport function getDateTime(dateTime: DateTimePreset): null | Date {\n\tconst matchPreset: Record null | Date> = {\n\t\t[DateTimePreset.LaterToday]: () => {\n\t\t\tconst now = new Date()\n\t\t\tconst evening = new Date()\n\t\t\tevening.setHours(18, 0, 0, 0)\n\t\t\tconst cutoff = new Date()\n\t\t\tcutoff.setHours(17, 0, 0, 0)\n\t\t\tif (now >= cutoff) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn evening\n\t\t},\n\n\t\t[DateTimePreset.Tomorrow]: () => {\n\t\t\tconst now = new Date()\n\t\t\tconst day = new Date()\n\t\t\tday.setDate(now.getDate() + 1)\n\t\t\tday.setHours(8, 0, 0, 0)\n\t\t\treturn day\n\t\t},\n\n\t\t[DateTimePreset.ThisWeekend]: () => {\n\t\t\tconst today = new Date()\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\t5, // Friday\n\t\t\t\t\t6, // Saturday\n\t\t\t\t\t0, // Sunday\n\t\t\t\t].includes(today.getDay())\n\t\t\t) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst saturday = new Date()\n\t\t\tconst firstWorkdayOfWeek = getFirstWorkdayOfWeek()\n\t\t\tsaturday.setDate(firstWorkdayOfWeek.getDate() + 5)\n\t\t\tsaturday.setHours(8, 0, 0, 0)\n\t\t\treturn saturday\n\t\t},\n\n\t\t[DateTimePreset.NextWeek]: () => {\n\t\t\tconst today = new Date()\n\t\t\tif (today.getDay() === 0) { // Sunday\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst workday = new Date()\n\t\t\tconst firstWorkdayOfWeek = getFirstWorkdayOfWeek()\n\t\t\tworkday.setDate(firstWorkdayOfWeek.getDate() + 7)\n\t\t\tworkday.setHours(8, 0, 0, 0)\n\t\t\treturn workday\n\t\t},\n\t}\n\n\treturn matchPreset[dateTime]()\n}\n\n/**\n *\n */\nexport function getInitialCustomDueDate(): Date {\n\tconst now = new Date()\n\tconst dueDate = new Date()\n\tdueDate.setHours(now.getHours() + 2, 0, 0, 0)\n\treturn dueDate\n}\n\n/**\n * @param dueDate - The date to format as a string\n */\nexport function getDateString(dueDate: Date): string {\n\tlet formatOptions: Intl.DateTimeFormatOptions = {\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t}\n\n\tconst today = new Date()\n\n\tif (!isSameDate(dueDate, today)) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tweekday: 'short',\n\t\t}\n\t}\n\n\tif (!isSameWeek(dueDate, today)) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t}\n\t}\n\n\tif (dueDate.getFullYear() !== today.getFullYear()) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tyear: 'numeric',\n\t\t}\n\t}\n\n\treturn dueDate.toLocaleString(\n\t\tgetCanonicalLocale(),\n\t\tformatOptions,\n\t)\n}\n\n/**\n * @param dueDate - The date to format as a string\n */\nexport function getVerboseDateString(dueDate: Date): string {\n\tlet formatOptions: Intl.DateTimeFormatOptions = {\n\t\tmonth: 'long',\n\t\tday: 'numeric',\n\t\tweekday: 'long',\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t}\n\n\tconst today = new Date()\n\n\tif (dueDate.getFullYear() !== today.getFullYear()) {\n\t\tformatOptions = {\n\t\t\t...formatOptions,\n\t\t\tyear: 'numeric',\n\t\t}\n\t}\n\n\treturn dueDate.toLocaleString(\n\t\tgetCanonicalLocale(),\n\t\tformatOptions,\n\t)\n}\n","/*!\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmOffSvg from '@mdi/svg/svg/alarm-off.svg?raw'\nimport { emit } from '@nextcloud/event-bus'\nimport { t } from '@nextcloud/l10n'\nimport { clearReminder } from '../services/reminderService.ts'\nimport { getVerboseDateString } from '../shared/utils.ts'\n\nexport const action: IFileAction = {\n\tid: 'clear-reminder',\n\n\tdisplayName: () => t('files_reminders', 'Clear reminder'),\n\n\ttitle: ({ nodes }) => {\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = new Date(node.attributes['reminder-due-date'])\n\t\treturn `${t('files_reminders', 'Clear reminder')} – ${getVerboseDateString(dueDate)}`\n\t},\n\n\ticonSvgInline: () => AlarmOffSvg,\n\n\tenabled: ({ nodes }) => {\n\t\t// Only allow on a single node\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn Boolean(dueDate)\n\t},\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tif (node.fileid) {\n\t\t\ttry {\n\t\t\t\tawait clearReminder(node.fileid)\n\t\t\t\tnode.attributes['reminder-due-date'] = ''\n\t\t\t\temit('files:node:updated', node)\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn null\n\t},\n\n\torder: 19,\n}\n","export default \"\"","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getLoggerBuilder } from '@nextcloud/logger'\n\nexport const logger = getLoggerBuilder()\n\t.setApp('files_reminders')\n\t.detectUser()\n\t.build()\n","\n\n\n\n\n\n\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { INode } from '@nextcloud/files'\n\nimport { spawnDialog } from '@nextcloud/vue'\nimport SetCustomReminderModal from '../components/SetCustomReminderModal.vue'\n\n/**\n * @param node - The file or folder node to set the custom reminder for\n */\nexport async function pickCustomDate(node: INode): Promise {\n\tawait spawnDialog(SetCustomReminderModal, {\n\t\tnode,\n\t})\n}\n","/*!\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmSvg from '@mdi/svg/svg/alarm.svg?raw'\nimport { t } from '@nextcloud/l10n'\nimport { pickCustomDate } from '../services/customPicker.ts'\nimport { getVerboseDateString } from '../shared/utils.ts'\n\nexport const action: IFileAction = {\n\tid: 'reminder-status',\n\n\tinline: () => true,\n\n\tdisplayName: () => '',\n\n\ttitle: ({ nodes }) => {\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = new Date(node.attributes['reminder-due-date'])\n\t\treturn `${t('files_reminders', 'Reminder set')} – ${getVerboseDateString(dueDate)}`\n\t},\n\n\ticonSvgInline: () => AlarmSvg,\n\n\tenabled: ({ nodes }) => {\n\t\t// Only allow on a single node\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\tconst now = new Date()\n\n\t\t// Do not show if the reminder is in the past\n\t\treturn Boolean(dueDate) && new Date(dueDate) > now\n\t},\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tawait pickCustomDate(node)\n\t\treturn null\n\t},\n\n\torder: -15,\n}\n","export default \"\"","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport AlarmSvg from '@mdi/svg/svg/alarm.svg?raw'\nimport { translate as t } from '@nextcloud/l10n'\n\nexport const SET_REMINDER_MENU_ID = 'set-reminder-menu'\n\nexport const action: IFileAction = {\n\tid: SET_REMINDER_MENU_ID,\n\tdisplayName: () => t('files_reminders', 'Set reminder'),\n\ticonSvgInline: () => AlarmSvg,\n\n\tenabled: ({ nodes, view }) => {\n\t\tif (view.id === 'trashbin') {\n\t\t\treturn false\n\t\t}\n\t\t// Only allow on a single INode\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn dueDate !== undefined\n\t},\n\n\tasync exec() {\n\t\treturn null\n\t},\n\n\torder: 20,\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport CalendarClockSvg from '@mdi/svg/svg/calendar-clock.svg?raw'\nimport { t } from '@nextcloud/l10n'\nimport { pickCustomDate } from '../services/customPicker.ts'\nimport { SET_REMINDER_MENU_ID } from './setReminderMenuAction.ts'\n\nexport const action: IFileAction = {\n\tid: 'set-reminder-custom',\n\tdisplayName: () => t('files_reminders', 'Custom reminder'),\n\ttitle: () => t('files_reminders', 'Reminder at custom date & time'),\n\ticonSvgInline: () => CalendarClockSvg,\n\n\tenabled: ({ nodes, view }) => {\n\t\tif (view.id === 'trashbin') {\n\t\t\treturn false\n\t\t}\n\t\t// Only allow on a single INode\n\t\tif (nodes.length !== 1) {\n\t\t\treturn false\n\t\t}\n\t\tconst node = nodes.at(0)!\n\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\treturn dueDate !== undefined\n\t},\n\n\tparent: SET_REMINDER_MENU_ID,\n\n\tasync exec({ nodes }) {\n\t\tconst node = nodes.at(0)!\n\t\tpickCustomDate(node)\n\t\treturn null\n\t},\n\n\t// After presets\n\torder: 22,\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFileAction } from '@nextcloud/files'\n\nimport { showError, showSuccess } from '@nextcloud/dialogs'\nimport { emit } from '@nextcloud/event-bus'\nimport { t } from '@nextcloud/l10n'\nimport { setReminder } from '../services/reminderService.ts'\nimport { logger } from '../shared/logger.ts'\nimport { DateTimePreset, getDateString, getDateTime, getVerboseDateString } from '../shared/utils.ts'\nimport { SET_REMINDER_MENU_ID } from './setReminderMenuAction.ts'\n\nimport './setReminderSuggestionActions.scss'\n\ninterface ReminderOption {\n\tdateTimePreset: DateTimePreset\n\tlabel: string\n\tariaLabel: string\n\tdateString?: string\n\tverboseDateString?: string\n\taction?: () => Promise\n}\n\nconst laterToday: ReminderOption = {\n\tdateTimePreset: DateTimePreset.LaterToday,\n\tlabel: t('files_reminders', 'Later today'),\n\tariaLabel: t('files_reminders', 'Set reminder for later today'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst tomorrow: ReminderOption = {\n\tdateTimePreset: DateTimePreset.Tomorrow,\n\tlabel: t('files_reminders', 'Tomorrow'),\n\tariaLabel: t('files_reminders', 'Set reminder for tomorrow'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst thisWeekend: ReminderOption = {\n\tdateTimePreset: DateTimePreset.ThisWeekend,\n\tlabel: t('files_reminders', 'This weekend'),\n\tariaLabel: t('files_reminders', 'Set reminder for this weekend'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\nconst nextWeek: ReminderOption = {\n\tdateTimePreset: DateTimePreset.NextWeek,\n\tlabel: t('files_reminders', 'Next week'),\n\tariaLabel: t('files_reminders', 'Set reminder for next week'),\n\tdateString: '',\n\tverboseDateString: '',\n}\n\n/**\n * Get all set reminder suggestion actions from presets\n */\nexport function getSetReminderSuggestionActions() {\n\t[laterToday, tomorrow, thisWeekend, nextWeek].forEach((option) => {\n\t\t// Generate the initial date string\n\t\tconst dateTime = getDateTime(option.dateTimePreset)\n\t\tif (!dateTime) {\n\t\t\treturn\n\t\t}\n\t\toption.dateString = getDateString(dateTime)\n\t\toption.verboseDateString = getVerboseDateString(dateTime)\n\n\t\t// Update the date string every 30 minutes\n\t\tsetInterval(() => {\n\t\t\tconst dateTime = getDateTime(option.dateTimePreset)\n\t\t\tif (!dateTime) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// update the submenu remind options strings\n\t\t\toption.dateString = getDateString(dateTime)\n\t\t\toption.verboseDateString = getVerboseDateString(dateTime)\n\t\t}, 1000 * 30 * 60)\n\t})\n\n\t// Generate the default preset actions\n\treturn [laterToday, tomorrow, thisWeekend, nextWeek]\n\t\t.map(generateFileAction)\n}\n\n/**\n * Generate a file action for the given option\n *\n * @param option The option to generate the action for\n * @return The file action or null if the option should not be shown\n */\nfunction generateFileAction(option: ReminderOption): IFileAction {\n\treturn {\n\t\tid: `set-reminder-${option.dateTimePreset}`,\n\t\tdisplayName: () => `${option.label} – ${option.dateString}`,\n\t\ttitle: () => `${option.ariaLabel} – ${option.verboseDateString}`,\n\n\t\t// Empty svg to hide the icon\n\t\ticonSvgInline: () => '',\n\n\t\tenabled: ({ nodes, view }) => {\n\t\t\tif (view.id === 'trashbin') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Only allow on a single INode\n\t\t\tif (nodes.length !== 1) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst node = nodes.at(0)!\n\t\t\tconst dueDate = node.attributes['reminder-due-date']\n\t\t\treturn dueDate !== undefined && Boolean(getDateTime(option.dateTimePreset))\n\t\t},\n\n\t\tparent: SET_REMINDER_MENU_ID,\n\n\t\tasync exec({ nodes }) {\n\t\t\t// Can't really happen, but just in case™\n\t\t\tconst node = nodes.at(0)!\n\t\t\tif (!node.fileid) {\n\t\t\t\tlogger.error('Failed to set reminder, missing file id')\n\t\t\t\tshowError(t('files_reminders', 'Failed to set reminder'))\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Set the reminder\n\t\t\ttry {\n\t\t\t\tconst dateTime = getDateTime(option.dateTimePreset)!\n\t\t\t\tawait setReminder(node.fileid, dateTime)\n\t\t\t\tnode.attributes['reminder-due-date'] = dateTime.toISOString()\n\t\t\t\temit('files:node:updated', node)\n\t\t\t\tshowSuccess(t('files_reminders', 'Reminder set for \"{fileName}\"', { fileName: node.basename }))\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('Failed to set reminder', { error })\n\t\t\t\tshowError(t('files_reminders', 'Failed to set reminder'))\n\t\t\t}\n\t\t\t// Silent success as we display our own notification\n\t\t\treturn null\n\t\t},\n\n\t\torder: 21,\n\t}\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { registerFileAction } from '@nextcloud/files'\nimport { registerDavProperty } from '@nextcloud/files/dav'\nimport { action as clearAction } from './files_actions/clearReminderAction.ts'\nimport { action as statusAction } from './files_actions/reminderStatusAction.ts'\nimport { action as customAction } from './files_actions/setReminderCustomAction.ts'\nimport { action as menuAction } from './files_actions/setReminderMenuAction.ts'\nimport { getSetReminderSuggestionActions } from './files_actions/setReminderSuggestionActions.ts'\n\nregisterDavProperty('nc:reminder-due-date', { nc: 'http://nextcloud.org/ns' })\n\nregisterFileAction(statusAction)\nregisterFileAction(clearAction)\nregisterFileAction(menuAction)\nregisterFileAction(customAction)\ngetSetReminderSuggestionActions()\n\t.forEach(registerFileAction)\n"],"names":["AlarmOffSvg","setReminder","fileId","dueDate","url","generateOcsUrl","axios","clearReminder","status","DateTimePreset","getFirstWorkdayOfWeek","now","getWeek","date","firstDayOfYear","daysFromFirstDay","isSameWeek","a","b","isSameDate","getDateTime","dateTime","evening","cutoff","day","today","saturday","firstWorkdayOfWeek","workday","getInitialCustomDueDate","getDateString","formatOptions","getCanonicalLocale","getVerboseDateString","action","t","nodes","node","emit","AlarmSvg","logger","getLoggerBuilder","props","__props","__emit","hasDueDate","ref","opened","isValid","customDueDate","nowDate","informationText","computed","relativeDueDate","formatRelativeTime","onBeforeMount","onMounted","input","setCustom","showError","emitEventBus","showSuccess","onClose","error","clear","onInput","_createBlock","_unref","NcDialog","_createVNode","NcButton","_createElementVNode","NcDateTimePickerNative","$event","NcNoteCard","pickCustomDate","spawnDialog","SetCustomReminderModal","CalendarClockSvg","SET_REMINDER_MENU_ID","view","laterToday","tomorrow","thisWeekend","nextWeek","getSetReminderSuggestionActions","option","generateFileAction","registerDavProperty","registerFileAction","statusAction","clearAction","menuAction","customAction"],"mappings":"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","x_google_ignoreList":[0,4,9]} \ No newline at end of file