feat(tasks): completed tasks are deleted after a delay (default 30 days), "Erledigte leeren"
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m34s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m34s
thoughts.completed_at is set by triggers on every way a task is completed (migration 14; tasks completed earlier count from the update). Users choose the delay (7/30/90/365 days or never, users.done_retention_days); for tasks in a list the owner's delay counts. An hourly job deletes expired completed tasks (not in the demo) and tells their viewers. POST /tasks/clear-done clears completed tasks the user may edit. The done tab shows the setting and the button. v0.35.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
66b28e1998
commit
f91926c208
16 files changed
+433
-6
No files matched your search
@@ -690,6 +690,31 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
onRefreshStats();
|
||||
};
|
||||
|
||||
// Completed tasks: cleared by hand or deleted after the owner's delay (done_cleanup.go)
|
||||
const [doneRetentionDays, setDoneRetentionDays] = useState<number>(currentUser?.doneRetentionDays ?? 30);
|
||||
useEffect(() => {
|
||||
if (currentUser?.doneRetentionDays !== undefined) setDoneRetentionDays(currentUser.doneRetentionDays);
|
||||
}, [currentUser?.doneRetentionDays]);
|
||||
|
||||
const handleChangeDoneRetention = async (days: number) => {
|
||||
const previous = doneRetentionDays;
|
||||
setDoneRetentionDays(days);
|
||||
try {
|
||||
await api.updateSettings({ doneRetentionDays: days });
|
||||
} catch {
|
||||
setDoneRetentionDays(previous);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClearDone = async () => {
|
||||
const scope = selectedListId === 'all' ? 'aller Listen, die du bearbeiten darfst,' : `aus „${currentSelectedList?.title || 'dieser Liste'}“`;
|
||||
if (!window.confirm(`Alle erledigten Aufgaben ${scope} endgültig löschen?`)) return;
|
||||
triggerHaptic(20);
|
||||
await api.clearDoneTasks(selectedListId === 'all' ? '' : selectedListId);
|
||||
await loadData();
|
||||
onRefreshStats();
|
||||
};
|
||||
|
||||
const handlePurgeAllDiscarded = async () => {
|
||||
if (!window.confirm('Alle verworfenen Gedanken endgültig löschen?')) return;
|
||||
triggerHaptic(20);
|
||||
@@ -2586,8 +2611,44 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
Papierkorb leeren
|
||||
</button>
|
||||
)}
|
||||
{filter === 'done' && doneTasks.length > 0 && !isSelectedListReadOnly && (
|
||||
<button onClick={handleClearDone} className="btn-action min-h-[38px] sm:min-h-0 ml-auto">
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
Erledigte leeren
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* What happens to completed tasks; the delay of the list owner counts */}
|
||||
{filter === 'done' && (
|
||||
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted px-1">
|
||||
{currentSelectedList && currentSelectedList.isOwner === false ? (
|
||||
<span>
|
||||
Erledigte Aufgaben dieser Liste räumt die Einstellung von {currentSelectedList.ownerName || 'der Eigentümerin bzw. dem Eigentümer'} auf.
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<span>Erledigte Aufgaben löschen</span>
|
||||
<select
|
||||
value={doneRetentionDays}
|
||||
onChange={(e) => handleChangeDoneRetention(Number(e.target.value))}
|
||||
className="h-9 sm:h-6 px-1.5 input-field text-xs bg-panel"
|
||||
aria-label="Erledigte Aufgaben löschen nach"
|
||||
>
|
||||
<option value={7}>nach 7 Tagen</option>
|
||||
<option value={30}>nach 30 Tagen</option>
|
||||
<option value={90}>nach 90 Tagen</option>
|
||||
<option value={365}>nach einem Jahr</option>
|
||||
<option value={0}>nie</option>
|
||||
</select>
|
||||
<span className="text-faint">
|
||||
{doneRetentionDays > 0 ? '(gezählt ab dem Abhaken; gilt für deine eigenen Listen)' : '(bleiben, bis du sie leerst)'}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<div className="p-6 text-center text-faint text-sm">Lade Aufgaben…</div>
|
||||
) : filter === 'discarded' ? (
|
||||
|
||||
Reference in new issue
Block a user