Skip to content

Commit 706e37e

Browse files
task option
1 parent d750423 commit 706e37e

2 files changed

Lines changed: 114 additions & 34 deletions

File tree

lib/plugin.js

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
11
const plugin = {
22
constants: {},
3-
// https://www.amplenote.com/help/developing_amplenote_plugins#appOption
4-
appOption: {
3+
// https://www.amplenote.com/help/developing_amplenote_plugins#noteOption
4+
taskOption: {
55
"Bulk Reset Overdue Tasks": {
6-
run: async function (app) {
6+
run: async function (app, noteUUID) {
77
try {
88
// Get today's date at midnight for comparison
99
const today = new Date();
1010
today.setHours(0, 0, 0, 0);
1111
const todayTimestamp = Math.floor(today.getTime() / 1000);
1212

13-
// Find all tasks with calendar dates
14-
const tasksWithDates = await app.filterTasks({
15-
score: { min: 0 }, // Get all scored tasks (tasks with calendar dates have scores)
16-
});
13+
// Get all task domains
14+
const taskDomains = await app.getTaskDomains();
1715

18-
if (!tasksWithDates || tasksWithDates.length === 0) {
19-
await app.alert("No tasks with calendar dates found.");
16+
if (!taskDomains || taskDomains.length === 0) {
17+
await app.alert("No task domains found.");
2018
return;
2119
}
2220

23-
// Filter for overdue tasks (tasks with dates before today)
21+
// Get all tasks from all task domains and filter for overdue
2422
const overdueTasks = [];
25-
for (const task of tasksWithDates) {
26-
const taskDate = task.startAt || task.endAt;
27-
if (taskDate && taskDate < todayTimestamp) {
28-
overdueTasks.push(task);
23+
const tasksByDomain = {}; // Track tasks per domain
24+
25+
for (const taskDomain of taskDomains) {
26+
const domainTasks = [];
27+
for await (const task of app.getTaskDomainTasks(taskDomain.uuid)) {
28+
const taskDate = task.startAt || task.endAt;
29+
if (taskDate && taskDate < todayTimestamp) {
30+
overdueTasks.push(task);
31+
domainTasks.push(task);
32+
}
33+
}
34+
if (domainTasks.length > 0) {
35+
tasksByDomain[taskDomain.name] = domainTasks;
2936
}
3037
}
3138

@@ -34,10 +41,29 @@ const plugin = {
3441
return;
3542
}
3643

44+
// Build domain breakdown message with task names
45+
const domainBreakdown = Object.entries(tasksByDomain)
46+
.map(([domainName, tasks]) => {
47+
const taskList = tasks
48+
.map((task) => {
49+
// Get task content without markdown formatting
50+
const content = task.content || "Untitled task";
51+
// Truncate long task names
52+
const truncated =
53+
content.length > 60
54+
? content.substring(0, 57) + "..."
55+
: content;
56+
return ` - ${truncated}`;
57+
})
58+
.join("\n");
59+
return ` ${domainName} (${tasks.length}):\n${taskList}`;
60+
})
61+
.join("\n\n");
62+
3763
// Confirm with user
3864
const confirmMessage = `Found ${overdueTasks.length} overdue task${
3965
overdueTasks.length > 1 ? "s" : ""
40-
}. Remove from calendar?`;
66+
}:\n\n${domainBreakdown}\n\nRemove from calendar?`;
4167
const confirmed = await app.alert(confirmMessage, {
4268
actions: [
4369
{ label: "Cancel", icon: "cancel" },
@@ -84,8 +110,6 @@ const plugin = {
84110

85111
insertText: {},
86112

87-
noteOption: {},
88-
89113
replaceText: {},
90114
};
91115
export default plugin;

lib/plugin.test.js

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,40 @@ describe("Bulk Task Reset Plugin", () => {
66
const plugin = mockPlugin();
77
plugin.constants.isTestEnvironment = true;
88

9-
it("should handle no tasks with dates", async () => {
9+
it("should handle no task domains", async () => {
1010
const app = mockApp();
11-
app.filterTasks = jest.fn().mockResolvedValue([]);
11+
app.getTaskDomains = jest.fn().mockResolvedValue([]);
1212
app.alert = jest.fn();
1313

14-
await plugin.appOption["Bulk Reset Overdue Tasks"].run(app);
15-
16-
expect(app.alert).toHaveBeenCalledWith(
17-
"No tasks with calendar dates found."
14+
await plugin.taskOption["Bulk Reset Overdue Tasks"].run(
15+
app,
16+
"test-note-uuid"
1817
);
18+
19+
expect(app.alert).toHaveBeenCalledWith("No task domains found.");
1920
});
2021

2122
it("should handle no overdue tasks", async () => {
2223
const app = mockApp();
2324
const futureDate = Math.floor(Date.now() / 1000) + 86400; // Tomorrow
2425

25-
app.filterTasks = jest
26+
app.getTaskDomains = jest
2627
.fn()
27-
.mockResolvedValue([{ uuid: "task1", startAt: futureDate }]);
28+
.mockResolvedValue([{ uuid: "domain1", name: "My Tasks" }]);
29+
30+
// Mock async iterator for getTaskDomainTasks
31+
app.getTaskDomainTasks = jest.fn().mockReturnValue(
32+
(async function* () {
33+
yield { uuid: "task1", startAt: futureDate };
34+
})()
35+
);
36+
2837
app.alert = jest.fn();
2938

30-
await plugin.appOption["Bulk Reset Overdue Tasks"].run(app);
39+
await plugin.taskOption["Bulk Reset Overdue Tasks"].run(
40+
app,
41+
"test-note-uuid"
42+
);
3143

3244
expect(app.alert).toHaveBeenCalledWith("No overdue tasks found.");
3345
});
@@ -36,17 +48,50 @@ describe("Bulk Task Reset Plugin", () => {
3648
const app = mockApp();
3749
const yesterday = Math.floor(Date.now() / 1000) - 86400;
3850

39-
app.filterTasks = jest.fn().mockResolvedValue([
40-
{ uuid: "task1", startAt: yesterday },
41-
{ uuid: "task2", endAt: yesterday },
42-
]);
51+
app.getTaskDomains = jest
52+
.fn()
53+
.mockResolvedValue([{ uuid: "domain1", name: "My Tasks" }]);
54+
55+
// Mock async iterator for getTaskDomainTasks
56+
app.getTaskDomainTasks = jest.fn().mockReturnValue(
57+
(async function* () {
58+
yield { uuid: "task1", startAt: yesterday, content: "Buy groceries" };
59+
yield { uuid: "task2", endAt: yesterday, content: "Call dentist" };
60+
})()
61+
);
62+
4363
app.updateTask = jest.fn().mockResolvedValue(true);
4464
app.alert = jest
4565
.fn()
4666
.mockResolvedValueOnce(1) // User clicks "Reset All"
4767
.mockResolvedValueOnce(undefined); // Success message
4868

49-
await plugin.appOption["Bulk Reset Overdue Tasks"].run(app);
69+
await plugin.taskOption["Bulk Reset Overdue Tasks"].run(
70+
app,
71+
"test-note-uuid"
72+
);
73+
74+
// Check that confirmation message includes domain name, count, and task names
75+
expect(app.alert).toHaveBeenNthCalledWith(
76+
1,
77+
expect.stringContaining("Found 2 overdue tasks"),
78+
expect.any(Object)
79+
);
80+
expect(app.alert).toHaveBeenNthCalledWith(
81+
1,
82+
expect.stringContaining("My Tasks (2)"),
83+
expect.any(Object)
84+
);
85+
expect(app.alert).toHaveBeenNthCalledWith(
86+
1,
87+
expect.stringContaining("Buy groceries"),
88+
expect.any(Object)
89+
);
90+
expect(app.alert).toHaveBeenNthCalledWith(
91+
1,
92+
expect.stringContaining("Call dentist"),
93+
expect.any(Object)
94+
);
5095

5196
expect(app.updateTask).toHaveBeenCalledTimes(2);
5297
expect(app.updateTask).toHaveBeenCalledWith("task1", {
@@ -61,13 +106,24 @@ describe("Bulk Task Reset Plugin", () => {
61106
const app = mockApp();
62107
const yesterday = Math.floor(Date.now() / 1000) - 86400;
63108

64-
app.filterTasks = jest
109+
app.getTaskDomains = jest
65110
.fn()
66-
.mockResolvedValue([{ uuid: "task1", startAt: yesterday }]);
111+
.mockResolvedValue([{ uuid: "domain1", name: "My Tasks" }]);
112+
113+
// Mock async iterator for getTaskDomainTasks
114+
app.getTaskDomainTasks = jest.fn().mockReturnValue(
115+
(async function* () {
116+
yield { uuid: "task1", startAt: yesterday };
117+
})()
118+
);
119+
67120
app.updateTask = jest.fn();
68121
app.alert = jest.fn().mockResolvedValue(0); // User clicks "Cancel"
69122

70-
await plugin.appOption["Bulk Reset Overdue Tasks"].run(app);
123+
await plugin.taskOption["Bulk Reset Overdue Tasks"].run(
124+
app,
125+
"test-note-uuid"
126+
);
71127

72128
expect(app.updateTask).not.toHaveBeenCalled();
73129
});

0 commit comments

Comments
 (0)