diff --git a/CHANGELOG.md b/CHANGELOG.md index a3fd6cb..8f39e08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - For example, if the full file path is `My Vault/Notes/How to Take Smart Notes.md` then the replaced file name will be `How to Take Smart Notes`. - Added "Add item" button to rendered queries. This will open the task creation modal. - Added the ability to control which elements of the task metadata render with tasks inside the query with the `show` keyword. +- You can now sort by when the task was added to Todoist using `dateAdded` and `dateAddedAscending` sort options. ### 🔁 Changes diff --git a/src/api/domain/task.ts b/src/api/domain/task.ts index 84803ff..9e66c88 100644 --- a/src/api/domain/task.ts +++ b/src/api/domain/task.ts @@ -1,4 +1,3 @@ -import moment from "moment"; import type { DueDate } from "./dueDate"; import type { ProjectId } from "./project"; import type { SectionId } from "./section"; @@ -7,6 +6,7 @@ export type TaskId = string; export type Task = { id: TaskId, + createdAt: string, content: string, description: string, diff --git a/src/data/index.ts b/src/data/index.ts index cd17c71..b72946c 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -7,6 +7,7 @@ import type { Task } from "./task"; import type { Task as ApiTask, CreateTaskParams, TaskId } from "../api/domain/task"; import { SubscriptionManager, type UnsubscribeCallback } from "./subscriptions"; import { Maybe } from "../utils/maybe"; +import moment from "moment"; type SubscriptionResult = { type: "success", tasks: Task[] } | { type: "error" }; type OnSubscriptionChange = (result: SubscriptionResult) => void; @@ -100,6 +101,7 @@ export class TodoistAdapter { return { id: apiTask.id, + createdAt: apiTask.createdAt, content: apiTask.content, description: apiTask.description, diff --git a/src/data/task.ts b/src/data/task.ts index 17bca59..531b79e 100644 --- a/src/data/task.ts +++ b/src/data/task.ts @@ -1,3 +1,4 @@ +import type moment from "moment"; import type { DueDate } from "../api/domain/dueDate"; import type { Project } from "../api/domain/project"; import type { Section } from "../api/domain/section"; @@ -5,6 +6,7 @@ import type { Priority, TaskId } from "../api/domain/task"; export type Task = { id: TaskId, + createdAt: string, content: string, description: string, diff --git a/src/data/transformations.test.ts b/src/data/transformations.test.ts index 4f90264..c3b1443 100644 --- a/src/data/transformations.test.ts +++ b/src/data/transformations.test.ts @@ -8,6 +8,7 @@ import { SortingVariant } from "../query/query"; function makeTask(id: string, opts?: Partial): Task { return { id, + createdAt: opts?.createdAt, parentId: opts?.parentId, content: "", description: "", @@ -284,6 +285,34 @@ describe("sortTasks", () => { }), ], }, + { + description: "can sort by dateAdded", + input: [ + makeTask("a", { createdAt: "2020-03-03T13:00:00" }), + makeTask("b", { createdAt: "2020-03-02T11:00:00" }), + makeTask("c", { createdAt: "2020-03-02T12:00:00" }), + ], + sortingOpts: [SortingVariant.DateAdded], + expectedOutput: [ + makeTask("b", { createdAt: "2020-03-02T11:00:00" }), + makeTask("c", { createdAt: "2020-03-02T12:00:00" }), + makeTask("a", { createdAt: "2020-03-03T13:00:00" }), + ], + }, + { + description: "can sort by dateAddedDescending", + input: [ + makeTask("a", { createdAt: "2020-03-02T11:00:00" }), + makeTask("b", { createdAt: "2020-03-03T13:00:00" }), + makeTask("c", { createdAt: "2020-03-02T12:00:00" }), + ], + sortingOpts: [SortingVariant.DateAddedDescending], + expectedOutput: [ + makeTask("b", { createdAt: "2020-03-03T13:00:00" }), + makeTask("c", { createdAt: "2020-03-02T12:00:00" }), + makeTask("a", { createdAt: "2020-03-02T11:00:00" }), + ], + }, { description: "will sort using specified parameters in order", input: [ diff --git a/src/data/transformations.ts b/src/data/transformations.ts index ad9e9f2..15a7edf 100644 --- a/src/data/transformations.ts +++ b/src/data/transformations.ts @@ -1,3 +1,4 @@ +import moment from "moment"; import { getDueDateInfo } from "../api/domain/dueDate"; import type { Project } from "../api/domain/project"; import type { TaskId } from "../api/domain/task"; @@ -64,6 +65,10 @@ function compareTask(self: T, other: T, sorting: SortingVariant) return -compareTaskDate(self, other); case SortingVariant.Order: return self.order - other.order; + case SortingVariant.DateAdded: + return compareTaskDateAdded(self, other); + case SortingVariant.DateAddedDescending: + return -compareTaskDateAdded(self, other); default: throw new Error(`Unexpected sorting type: '${sorting}'`) } @@ -106,6 +111,17 @@ function compareTaskDate(self: T, other: T): number { return selfDate.isBefore(otherDate) ? -1 : 1; } +function compareTaskDateAdded(self: T, other: T): number { + const selfDate = moment(self.createdAt); + const otherDate = moment(other.createdAt); + + if (selfDate === otherDate) { + return 0; + } + + return selfDate.isBefore(otherDate) ? -1 : 1; +} + export type TaskTree = Task & { children: TaskTree[] }; // Builds a task tree, preserving the sorting order. diff --git a/src/query/parser.ts b/src/query/parser.ts index 9f389e1..4320717 100644 --- a/src/query/parser.ts +++ b/src/query/parser.ts @@ -160,6 +160,9 @@ const sortingLookup: Record = { "dateAscending": SortingVariant.Date, "dateDescending": SortingVariant.DateDescending, "order": SortingVariant.Order, + "dateAdded": SortingVariant.DateAdded, + "dateAddedAscending": SortingVariant.DateAdded, + "dateAddedDescending": SortingVariant.DateAddedDescending, } const showMetadataVariantLookup: Record = { diff --git a/src/query/query.ts b/src/query/query.ts index 0791ee0..ce3e627 100644 --- a/src/query/query.ts +++ b/src/query/query.ts @@ -3,7 +3,9 @@ export enum SortingVariant { PriorityDescending, Date, DateDescending, - Order + Order, + DateAdded, + DateAddedDescending, }; export enum ShowMetadataVariant {