feat: task trash, triage trash and retention settings for every area; admin can forbid keeping things for good
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m39s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m39s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a927a94a95
commit
5a9c5bac37
36 files changed
+1356
-175
No files matched your search
@@ -4,6 +4,8 @@ import {
|
||||
DashboardStats,
|
||||
Document,
|
||||
TrashedDocument,
|
||||
TrashedTask,
|
||||
Retention,
|
||||
JournalDay,
|
||||
PushDevice,
|
||||
BackupFile,
|
||||
@@ -302,6 +304,7 @@ export const api = {
|
||||
notificationSettings?: NotificationSettings;
|
||||
doneRetentionDays?: number;
|
||||
voiceInput?: '' | 'browser';
|
||||
retention?: Retention;
|
||||
}): Promise<User> {
|
||||
return request<User>('/api/v1/auth/settings', {
|
||||
method: 'PATCH',
|
||||
@@ -479,6 +482,24 @@ export const api = {
|
||||
return request<{ deleted: number }>('/api/v1/tasks/clear-done', { method: 'POST', body: JSON.stringify({ taskListId }) });
|
||||
},
|
||||
|
||||
// Task trash: deleted tasks, cleared and automatically cleaned-up completed ones
|
||||
async getTaskTrash(taskListId = ''): Promise<TrashedTask[]> {
|
||||
const q = taskListId ? `?taskListId=${encodeURIComponent(taskListId)}` : '';
|
||||
return request<TrashedTask[]>(`/api/v1/tasks/trash${q}`);
|
||||
},
|
||||
|
||||
async restoreTrashedTask(id: string): Promise<Thought> {
|
||||
return request<Thought>(`/api/v1/tasks/trash/${id}/restore`, { method: 'POST' });
|
||||
},
|
||||
|
||||
async purgeTrashedTask(id: string): Promise<{ deleted: boolean }> {
|
||||
return request<{ deleted: boolean }>(`/api/v1/tasks/trash/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
|
||||
async emptyTaskTrash(taskListId: string): Promise<{ deleted: number }> {
|
||||
return request<{ deleted: number }>('/api/v1/tasks/trash/empty', { method: 'POST', body: JSON.stringify({ taskListId }) });
|
||||
},
|
||||
|
||||
async purgeDiscarded(): Promise<{ purged: number }> {
|
||||
return request<{ purged: number }>('/api/v1/thoughts/discarded/purge', { method: 'DELETE' });
|
||||
},
|
||||
|
||||
@@ -48,3 +48,10 @@ export const formatDue = (due: string | undefined, now: Date = new Date()): stri
|
||||
else label = `${pad(d)}.${pad(m)}.${y}`;
|
||||
return time ? `${label}, ${time}` : label;
|
||||
};
|
||||
|
||||
/** When something went to a trash, e.g. "01.11.2026, 14:05". */
|
||||
export const formatDeletedAt = (iso: string) => {
|
||||
const d = new Date(iso);
|
||||
if (Number.isNaN(d.getTime())) return '';
|
||||
return d.toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' });
|
||||
};
|
||||
@@ -115,6 +115,9 @@ export interface User {
|
||||
doneRetentionDays?: number;
|
||||
// Voice input: '' = the server's Whisper (default), 'browser' = the browser's recognition
|
||||
voiceInput?: '' | 'browser';
|
||||
// How long finished and deleted things are kept, in days (0 = for good; only when allowed)
|
||||
retention?: Retention;
|
||||
retentionNeverAllowed?: boolean;
|
||||
organizationId?: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -293,6 +296,9 @@ export interface SystemSettings {
|
||||
backupEnabled?: boolean;
|
||||
backupTime?: string;
|
||||
backupRetentionDays?: number;
|
||||
// People may keep finished and deleted things for good ("nie"); fixed when set via RETENTION_ALLOW_NEVER
|
||||
retentionAllowNever?: boolean;
|
||||
retentionNeverViaEnv?: boolean;
|
||||
}
|
||||
|
||||
/** One file of a server backup listing. */
|
||||
@@ -382,6 +388,26 @@ export interface JournalDay {
|
||||
empty: boolean;
|
||||
}
|
||||
|
||||
/** Delays in days per area (Kontoeinstellungen → Aufbewahrung); 0 = keep for good. */
|
||||
export interface Retention {
|
||||
doneTasks: number;
|
||||
taskTrash: number;
|
||||
triageTrash: number;
|
||||
noteTrash: number;
|
||||
listDone: number;
|
||||
}
|
||||
|
||||
/** A deleted task waiting in the task trash. */
|
||||
export interface TrashedTask {
|
||||
id: string;
|
||||
content: string;
|
||||
taskListId: string;
|
||||
isCompleted: boolean;
|
||||
trashedAt: string;
|
||||
trashedBy: string;
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
export interface TrashedDocument {
|
||||
id: string;
|
||||
title: string;
|
||||
|
||||
Reference in new issue
Block a user