Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### ✨ Features

- You can now sort tasks alphabetically by name using `alphabetical` or `alphabeticalDescending` in the sorting field
- You can now provide 'time' to the show field on a query. This will only render the time of the task (unless the end of the task is on a different day than the start).

### 🐛 Bug Fixes
Expand Down
13 changes: 13 additions & 0 deletions docs/docs/query-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ autorefresh: 120

The `sorting` property allows you to specify the ordering for how your tasks are rendered. This is specified as a list, where we sort in the order of the properties in the list. The possible values are:

- `alphabetical` or `alphabeticalAscending`: sorts tasks alphabetically by name (A→Z, case-insensitive)
- `alphabeticalDescending`: sorts tasks alphabetically by name (Z→A, case-insensitive)
- `date` or `dateAscending`: sorts tasks in ascending order based on due date
- `dateDescending`: sorts tasks in descending order based on due date
- `priority` or `priorityAscending`: sorting tasks in ascending order based on priority
Expand All @@ -82,6 +84,17 @@ sorting:
```
````

You can also sort tasks alphabetically:

````
```todoist
filter: "#work"
sorting:
- priority
- alphabetical
```
````

### `groupBy`

The `groupBy` property controls how tasks are grouped when they are rendered. If omitted, there will be no grouping. The possible values are:
Expand Down
92 changes: 91 additions & 1 deletion plugin/src/data/transformations/sorting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function makeTask(id: string, opts?: Partial<Task>): Task {
id,
createdAt: opts?.createdAt ?? "1970-01-01",
parentId: opts?.parentId,
content: "",
content: opts?.content ?? "",
description: "",
labels: [],
priority: opts?.priority ?? 1,
Expand Down Expand Up @@ -340,6 +340,96 @@ describe("sortTasks", () => {
}),
],
},
{
description: "can sort alphabetically (ascending)",
input: [
makeTask("a", { content: "zebra" }),
makeTask("b", { content: "apple" }),
makeTask("c", { content: "Banana" }),
makeTask("d", { content: "cherry" }),
],
sortingOpts: [SortingVariant.Alphabetical],
expectedOutput: [
makeTask("b", { content: "apple" }),
makeTask("c", { content: "Banana" }),
makeTask("d", { content: "cherry" }),
makeTask("a", { content: "zebra" }),
],
},
{
description: "can sort alphabetically descending",
input: [
makeTask("a", { content: "apple" }),
makeTask("b", { content: "Banana" }),
makeTask("c", { content: "zebra" }),
],
sortingOpts: [SortingVariant.AlphabeticalDescending],
expectedOutput: [
makeTask("c", { content: "zebra" }),
makeTask("b", { content: "Banana" }),
makeTask("a", { content: "apple" }),
],
},
{
description: "alphabetical sort is case-insensitive",
input: [
makeTask("a", { content: "APPLE" }),
makeTask("b", { content: "banana" }),
makeTask("c", { content: "Apple" }),
makeTask("d", { content: "BANANA" }),
],
sortingOpts: [SortingVariant.Alphabetical],
expectedOutput: [
makeTask("a", { content: "APPLE" }),
makeTask("c", { content: "Apple" }),
makeTask("b", { content: "banana" }),
makeTask("d", { content: "BANANA" }),
],
},
{
description: "alphabetical sort handles special characters",
input: [
makeTask("a", { content: "2. Second task" }),
makeTask("b", { content: "1. First task" }),
makeTask("c", { content: "@mention task" }),
makeTask("d", { content: "#hashtag task" }),
],
sortingOpts: [SortingVariant.Alphabetical],
expectedOutput: [
makeTask("c", { content: "@mention task" }),
makeTask("d", { content: "#hashtag task" }),
makeTask("b", { content: "1. First task" }),
makeTask("a", { content: "2. Second task" }),
],
},
{
description: "alphabetical sort handles empty strings",
input: [
makeTask("a", { content: "" }),
makeTask("b", { content: "apple" }),
makeTask("c", { content: "" }),
],
sortingOpts: [SortingVariant.Alphabetical],
expectedOutput: [
makeTask("a", { content: "" }),
makeTask("c", { content: "" }),
makeTask("b", { content: "apple" }),
],
},
{
description: "can combine alphabetical sort with priority sorting",
input: [
makeTask("a", { content: "Task B", priority: 2 }),
makeTask("b", { content: "Task A", priority: 2 }),
makeTask("c", { content: "Task C", priority: 3 }),
],
sortingOpts: [SortingVariant.Priority, SortingVariant.Alphabetical],
expectedOutput: [
makeTask("c", { content: "Task C", priority: 3 }),
makeTask("b", { content: "Task A", priority: 2 }),
makeTask("a", { content: "Task B", priority: 2 }),
],
},
];

for (const tc of testcases) {
Expand Down
8 changes: 8 additions & 0 deletions plugin/src/data/transformations/sorting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ function compareTask<T extends Task>(self: T, other: T, sorting: SortingVariant)
return compareTaskDateAdded(self, other);
case SortingVariant.DateAddedDescending:
return -compareTaskDateAdded(self, other);
case SortingVariant.Alphabetical:
return compareTaskAlphabetical(self, other);
case SortingVariant.AlphabeticalDescending:
return -compareTaskAlphabetical(self, other);
default:
throw new Error(`Unexpected sorting type: '${sorting}'`);
}
Expand Down Expand Up @@ -94,6 +98,10 @@ function compareTaskDateAdded<T extends Task>(self: T, other: T): number {
return selfDate.compare(otherDate) < 0 ? -1 : 1;
}

function compareTaskAlphabetical<T extends Task>(self: T, other: T): number {
return self.content.localeCompare(other.content, undefined, { sensitivity: "base" });
}

function isSameDay(a: Date, b: Date): boolean {
return (
a.getFullYear() === b.getFullYear() &&
Expand Down
12 changes: 6 additions & 6 deletions plugin/src/query/__snapshots__/parser.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`parseQuery - error message snapshots > array with mixed valid and invalid enum values 1`] = `
[Error: Field 'sorting' elements have the following issues:
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
`;

exports[`parseQuery - error message snapshots > autorefresh must be a number 1`] = `
Expand Down Expand Up @@ -87,9 +87,9 @@ Field 'show' elements have the following issues:

exports[`parseQuery - error message snapshots > sorting array must contain strings 1`] = `
[Error: Field 'sorting' elements have the following issues:
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
Item 'sorting[2]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
Item 'sorting[2]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
`;

exports[`parseQuery - error message snapshots > sorting must be an array 1`] = `
Expand All @@ -99,6 +99,6 @@ exports[`parseQuery - error message snapshots > sorting must be an array 1`] = `

exports[`parseQuery - error message snapshots > sorting must have valid enum values 1`] = `
[Error: Field 'sorting' elements have the following issues:
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
`;
3 changes: 3 additions & 0 deletions plugin/src/query/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ const sortingSchema = lookupToEnum({
dateAdded: SortingVariant.DateAdded,
dateAddedAscending: SortingVariant.DateAdded,
dateAddedDescending: SortingVariant.DateAddedDescending,
alphabetical: SortingVariant.Alphabetical,
alphabeticalAscending: SortingVariant.Alphabetical,
alphabeticalDescending: SortingVariant.AlphabeticalDescending,
});

const showSchema = lookupToEnum({
Expand Down
2 changes: 2 additions & 0 deletions plugin/src/query/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export enum SortingVariant {
Order = 4,
DateAdded = 5,
DateAddedDescending = 6,
Alphabetical = 7,
AlphabeticalDescending = 8,
}

export enum ShowMetadataVariant {
Expand Down