Skip to content

Commit

Permalink
Complete recurring tasks by setting their start date to the next recu…
Browse files Browse the repository at this point in the history
…rrence date
  • Loading branch information
sunkup committed Jun 21, 2023
1 parent 9b27260 commit 0acd5ae
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
35 changes: 32 additions & 3 deletions src/models/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ export default class Task {
this._completed = !!comp
this._completedDate = comp ? comp.toJSDate() : null
this._completedDateMoment = moment(this._completedDate, 'YYYYMMDDTHHmmss')
const recur = this.vtodo.getFirstPropertyValue('rrule')
this._recurring = !!recur
this._recurrence = this.vtodo.getFirstPropertyValue('rrule')
this._status = this.vtodo.getFirstPropertyValue('status')
this._note = this.vtodo.getFirstPropertyValue('description') || ''
this._related = this.getParent()?.getFirstValue() || null
Expand Down Expand Up @@ -331,8 +330,17 @@ export default class Task {
return this._completedDateMoment.clone()
}

get recurrence() {
return this._recurrence
}

get recurring() {
return this._recurring
if (this._start === null || this._recurrence === null) {

This comment has been minimized.

Copy link
@meichthys

meichthys Aug 3, 2023

I think it may be possible to have a recurring task without a start date. In the Tasks.org client, it lets you do it, although i'm not sure if the 'Start Date' field in the Tasks.org client corresponds to this._start.

return false
}
const iter = this._recurrence.iterator(this.start);
iter.next();
return iter.next() !== null
}

get status() {
Expand Down Expand Up @@ -680,6 +688,27 @@ export default class Task {
).toSeconds()
}

/**
* For completing a recurring task, tries to set the task start date to the next recurrence date.
*
* Does nothing if we are at the end of the recurrence (RRULE:UNTIL was reached).
*/
completeRecurring() {
// Get recurrence iterator, starting at start date
const iter = this.recurrence.iterator(this.start);
// Skip the start date itself
iter.next();
// If there is a next recurrence, update the start date to next recurrence date
let nextRecurrence = iter.next();
if (nextRecurrence !== null) {
this.start = nextRecurrence;
// If the due date now lies before start date, clear it
if (this.due !== null && this.due.compare(this.start) < 0) {
this.due = null
}
}
}

/**
* Checks if the task matches the search query
*
Expand Down
6 changes: 6 additions & 0 deletions src/store/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,12 @@ const actions = {
if (task.calendar.isSharedWithMe && task.class !== 'PUBLIC') {
return
}
// Don't complete a task if it is still recurring, but update its start date instead
if (task.recurring) {
task.completeRecurring()
await context.dispatch('updateTask', task)
return
}
if (task.completed) {
await context.dispatch('setPercentComplete', { task, complete: 0 })
} else {
Expand Down

0 comments on commit 0acd5ae

Please sign in to comment.