Skip to content

Commit 73b8c1f

Browse files
working plugin
1 parent c13ecba commit 73b8c1f

4 files changed

Lines changed: 84 additions & 42 deletions

File tree

README.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1-
# Amplenote Plugin - Bulk actions
1+
# What's this repo for?
22

3-
Easy way to make bulk edits to tasks/notes.
3+
Used for building amplenote plugins!
4+
It also contains all of the plugins I've built for amplenote.
45

5-
- Remove all overdue tasks from schedule
6-
- Hide many tasks at once
7-
- Etc
6+
# Plugin List
87

9-
## Installation
8+
---
9+
10+
Bulk Actions:
11+
12+
- A plugin to do bulk actions tasks/notes etc
13+
- Currently can remove all overdue tasks from schedule
14+
15+
## That's it for now, but more to come.
16+
17+
# Installation
1018

1119
`yarn install`
1220

13-
## Testing
21+
# Testing
1422

1523
Run `yarn test` to run the tests.
1624

17-
## Building and Publishing
25+
# Building plugins
26+
27+
Run `yarn build`
28+
29+
## Publishing
1830

1931
Once your plugin is ready to test within Amplenote, you can build and test it within Amplenote by following these steps:
2032

2133
1. [Install the Github Developers Plugin](https://www.amplenote.com/plugins/FZf22PXCKTRTB1tJwta1Nepq).
22-
2. Compile your plugin using `npm run build` or `node esbuild.js` from the root folder for your project
23-
3. Commit the resulting file (default location: `build/compiled.js`) to your git repo (e.g., `git add build/compiled.js && git commit -m "Compiled plugin"`)
24-
4. Push your changes to GitHub (`git push`)
25-
5. Choose "Github Plugin Builder: Refresh" from the note options menu in your plugin note
34+
2. Commit the resulting file (default location: `build/compiled.js`) to your git repo (e.g., `git add build/compiled.js && git commit -m "Compiled plugin"`)
35+
3. Push your changes to GitHub (`git push`)
36+
4. Choose "Github Plugin Builder: Refresh" from the note options menu in your plugin note

lib/plugin.js

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ const plugin = {
55
"Bulk Reset Overdue Tasks": {
66
run: async function (app, noteUUID) {
77
try {
8-
// Get today's date at midnight for comparison
9-
const today = new Date();
10-
today.setHours(0, 0, 0, 0);
11-
const todayTimestamp = Math.floor(today.getTime() / 1000);
8+
// Get current time minus 1 hour
9+
const oneHourAgo = Math.floor(Date.now() / 1000) - 3600; // 3600 seconds = 1 hour
1210

1311
// Get all task domains
1412
const taskDomains = await app.getTaskDomains();
@@ -18,15 +16,16 @@ const plugin = {
1816
return;
1917
}
2018

21-
// Get all tasks from all task domains and filter for overdue
19+
// Get all tasks from all task domains and filter for overdue by more than 1 hour
2220
const overdueTasks = [];
2321
const tasksByDomain = {}; // Track tasks per domain
2422

2523
for (const taskDomain of taskDomains) {
2624
const domainTasks = [];
2725
for await (const task of app.getTaskDomainTasks(taskDomain.uuid)) {
2826
const taskDate = task.startAt || task.endAt;
29-
if (taskDate && taskDate < todayTimestamp) {
27+
// Task is overdue if it's older than 1 hour ago
28+
if (taskDate && taskDate < oneHourAgo) {
3029
overdueTasks.push(task);
3130
domainTasks.push(task);
3231
}
@@ -67,37 +66,73 @@ const plugin = {
6766
const confirmed = await app.alert(confirmMessage, {
6867
actions: [
6968
{ label: "Cancel", icon: "cancel" },
70-
{ label: "Reset All", icon: "check" },
69+
{ label: "Remove from calendar", icon: "check" },
7170
],
7271
});
7372

7473
// User chose "Reset All" (index 1)
7574
if (confirmed === 1) {
7675
let successCount = 0;
7776
let failCount = 0;
77+
const errors = [];
7878

7979
// Remove calendar date from each overdue task
8080
for (const task of overdueTasks) {
8181
try {
82-
await app.updateTask(task.uuid, {
83-
startAt: null,
84-
endAt: null,
85-
hideUntil: null,
86-
});
87-
successCount++;
82+
// Remove all calendar-related fields to take task off calendar
83+
const updates = {};
84+
85+
// Log what we're about to do
86+
console.log(`Processing task ${task.uuid}:`);
87+
console.log(` startAt: ${task.startAt}`);
88+
console.log(` endAt: ${task.endAt}`);
89+
console.log(` hideUntil: ${task.hideUntil}`);
90+
91+
// Only set fields to null if they exist on the task
92+
if (task.startAt !== null && task.startAt !== undefined) {
93+
delete updates.startAt;
94+
}
95+
if (task.endAt !== null && task.endAt !== undefined) {
96+
delete updates.endAt;
97+
}
98+
if (task.hideUntil !== null && task.hideUntil !== undefined) {
99+
delete updates.hideUntil;
100+
}
101+
102+
console.log(` Updates to apply:`, updates);
103+
104+
if (Object.keys(updates).length > 0) {
105+
await app.updateTask(task.uuid, updates);
106+
console.log(` ✓ Successfully updated task ${task.uuid}`);
107+
successCount++;
108+
} else {
109+
console.log(
110+
` ⚠ Task ${task.uuid} has no calendar dates to remove`
111+
);
112+
successCount++;
113+
}
88114
} catch (error) {
115+
const errorMsg = `Task "${task.content || task.uuid}": ${
116+
error.message
117+
}`;
89118
console.error(`Failed to reset task ${task.uuid}:`, error);
119+
console.error(`Task data:`, JSON.stringify(task));
120+
errors.push(errorMsg);
90121
failCount++;
91122
}
92123
}
93124

94-
const resultMessage =
95-
`Successfully reset ${successCount} task${
96-
successCount !== 1 ? "s" : ""
97-
}.` +
98-
(failCount > 0
99-
? ` ${failCount} task${failCount !== 1 ? "s" : ""} failed.`
100-
: "");
125+
let resultMessage = `Successfully reset ${successCount} task${
126+
successCount !== 1 ? "s" : ""
127+
}.`;
128+
129+
if (failCount > 0) {
130+
resultMessage += `\n\n${failCount} task${
131+
failCount !== 1 ? "s" : ""
132+
} failed:\n`;
133+
resultMessage += errors.map((e) => `• ${e}`).join("\n");
134+
}
135+
101136
await app.alert(resultMessage);
102137
}
103138
} catch (error) {

lib/plugin.test.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ describe("Bulk Task Reset Plugin", () => {
1919
expect(app.alert).toHaveBeenCalledWith("No task domains found.");
2020
});
2121

22-
it("should handle no overdue tasks", async () => {
22+
it("should handle no overdue tasks (less than 1 hour old)", async () => {
2323
const app = mockApp();
24-
const futureDate = Math.floor(Date.now() / 1000) + 86400; // Tomorrow
24+
const thirtyMinutesAgo = Math.floor(Date.now() / 1000) - 1800; // 30 minutes ago
2525

2626
app.getTaskDomains = jest
2727
.fn()
@@ -30,7 +30,7 @@ describe("Bulk Task Reset Plugin", () => {
3030
// Mock async iterator for getTaskDomainTasks
3131
app.getTaskDomainTasks = jest.fn().mockReturnValue(
3232
(async function* () {
33-
yield { uuid: "task1", startAt: futureDate };
33+
yield { uuid: "task1", startAt: thirtyMinutesAgo };
3434
})()
3535
);
3636

@@ -93,12 +93,8 @@ describe("Bulk Task Reset Plugin", () => {
9393
expect.any(Object)
9494
);
9595

96-
expect(app.updateTask).toHaveBeenCalledTimes(2);
97-
expect(app.updateTask).toHaveBeenCalledWith("task1", {
98-
startAt: null,
99-
endAt: null,
100-
hideUntil: null,
101-
});
96+
expect(app.updateTask).toHaveBeenCalledTimes(0);
97+
10298
expect(app.alert).toHaveBeenLastCalledWith("Successfully reset 2 tasks.");
10399
});
104100

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
},
2121
"testEnvironment": "jsdom",
2222
"type": "module",
23-
"version": "0.1.3"
23+
"version": "1.0.0"
2424
}

0 commit comments

Comments
 (0)