fix: clear all cached series rows on recurring delete + render star for any important task

- deleteCachedEvent now removes every cached row that belongs to the same
  recurring series (master id + all "<masterId>::*" instances + rows whose
  recurringEventId matches the master), so deleting "all occurrences" no
  longer leaves orphan rows that resurface on the next read.
- getPriorityBadge: surface the yellow star whenever a task is marked
  important (e.g. a starred Outlook To-Do task pulled in via sync), even
  when the active priority style is Eisenhower / ABCDE / Ivy Lee.

v1.103.1

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
mARTin-B78 2026-05-03 20:08:59 +02:00
parent 42905641cd
commit bf2819ce67
4 changed files with 38 additions and 8 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "my-weekly-todo-list", "name": "my-weekly-todo-list",
"version": "1.103.0", "version": "1.103.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "my-weekly-todo-list", "name": "my-weekly-todo-list",
"version": "1.103.0", "version": "1.103.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@auth/prisma-adapter": "^2.11.1", "@auth/prisma-adapter": "^2.11.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "my-weekly-todo-list", "name": "my-weekly-todo-list",
"version": "1.103.0", "version": "1.103.1",
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -9836,13 +9836,26 @@ function makeBadgeCircle(text: string, color: string, size: number, label: strin
} }
export function getPriorityBadge(task: Task, style: string, size = 12): PriorityBadge | null { export function getPriorityBadge(task: Task, style: string, size = 12): PriorityBadge | null {
// Universal "important" star — shown for any task explicitly marked important
// (e.g. Outlook To-Do tasks with the star flag) regardless of the active priority style.
const importantStar = (): PriorityBadge => ({
label: "Important",
node: <Star size={size + 1} fill="#eab308" color="#eab308" style={{ flexShrink: 0 }} />,
});
if (style === "abcde") { if (style === "abcde") {
if (!task.priority || !PRIORITY_LETTER_COLORS[task.priority]) return null; if (task.priority && PRIORITY_LETTER_COLORS[task.priority]) {
return makeBadgeCircle(task.priority, PRIORITY_LETTER_COLORS[task.priority], size + 2, task.priority); return makeBadgeCircle(task.priority, PRIORITY_LETTER_COLORS[task.priority], size + 2, task.priority);
}
if (task.importance === true) return importantStar();
return null;
} }
if (style === "ivylee") { if (style === "ivylee") {
if (!task.priority || !PRIORITY_NUMBER_COLORS[task.priority]) return null; if (task.priority && PRIORITY_NUMBER_COLORS[task.priority]) {
return makeBadgeCircle(task.priority, PRIORITY_NUMBER_COLORS[task.priority], size + 2, `Ivy Lee #${task.priority}`); return makeBadgeCircle(task.priority, PRIORITY_NUMBER_COLORS[task.priority], size + 2, `Ivy Lee #${task.priority}`);
}
if (task.importance === true) return importantStar();
return null;
} }
if (style === "pareto") { if (style === "pareto") {
if (task.importance !== true && task.priority !== "A" && task.priority !== "B") return null; if (task.importance !== true && task.priority !== "A" && task.priority !== "B") return null;
@ -9861,6 +9874,8 @@ export function getPriorityBadge(task: Task, style: string, size = 12): Priority
return { label: "Delegieren", node: <CornerUpRight size={size} color="#f97316" style={{ flexShrink: 0 }} /> }; return { label: "Delegieren", node: <CornerUpRight size={size} color="#f97316" style={{ flexShrink: 0 }} /> };
return { label: "Eliminieren", node: <Archive size={size} color="#9ca3af" style={{ flexShrink: 0 }} /> }; return { label: "Eliminieren", node: <Archive size={size} color="#9ca3af" style={{ flexShrink: 0 }} /> };
} }
// Eisenhower with only importance set (e.g. imported from Outlook with no urgency)
if (task.importance === true) return importantStar();
return null; return null;
} }

View File

@ -218,7 +218,22 @@ export async function deleteCachedEvent(
externalId: string, externalId: string,
provider: string, provider: string,
): Promise<void> { ): Promise<void> {
// For Outlook recurring events, our composite ID is "seriesMasterId::instanceId".
// When the user deletes the whole series, every cached occurrence of that series
// must be cleared too — otherwise the surviving rows reappear after the next read.
const seriesMasterId = externalId.includes('::') ? externalId.split('::')[0] : externalId;
await prisma.cachedCalendarEvent.deleteMany({ await prisma.cachedCalendarEvent.deleteMany({
where: { userId, externalId, provider }, where: {
userId,
provider,
OR: [
{ externalId },
{ externalId: seriesMasterId },
{ recurringEventId: seriesMasterId },
// The composite IDs of all instances start with "<seriesMasterId>::"
{ externalId: { startsWith: `${seriesMasterId}::` } },
],
},
}); });
} }