From a9c1e5fd20fbdb0391dc0c20a27e0ca8a83ee22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20P=C3=B6ttker?= Date: Mon, 4 May 2026 10:17:17 +0200 Subject: [PATCH] feat: add functionality to toggle inbox document source between personal and public scopes --- .../src/inbox/inbox.controller.ts | 11 +++++++ paperless-backend/src/inbox/inbox.service.ts | 22 ++++++++++++++ paperless-frontend/src/api/inbox.ts | 4 +++ paperless-frontend/src/pages/InboxPage.tsx | 29 +++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/paperless-backend/src/inbox/inbox.controller.ts b/paperless-backend/src/inbox/inbox.controller.ts index de0a24f..5a762bc 100644 --- a/paperless-backend/src/inbox/inbox.controller.ts +++ b/paperless-backend/src/inbox/inbox.controller.ts @@ -142,4 +142,15 @@ export class InboxController { res.setHeader('Cache-Control', 'private, max-age=3600'); return new StreamableFile(createReadStream(filePath)); } + + @Post(':id/source') + @HttpCode(204) + async updateSource( + @Param('id') id: string, + @Body() body: { source: any }, + @Request() req: any, + ): Promise { + const preferredUsername: string | null = req.user?.preferredUsername ?? null; + await this.inboxService.updateSource(id, body.source, preferredUsername); + } } diff --git a/paperless-backend/src/inbox/inbox.service.ts b/paperless-backend/src/inbox/inbox.service.ts index f257b34..946e1e5 100644 --- a/paperless-backend/src/inbox/inbox.service.ts +++ b/paperless-backend/src/inbox/inbox.service.ts @@ -1,4 +1,5 @@ import { + BadRequestException, ConflictException, Injectable, Logger, @@ -190,4 +191,25 @@ export class InboxService { } return filePath; } + + async updateSource( + id: string, + source: InboxSource, + preferredUsername: string | null, + ): Promise { + const { doc } = await this.resolveDocument(id, preferredUsername); + + if (source === 'all') { + doc.Source = 'all'; + doc.OwnerUsername = null; + } else { + if (!preferredUsername) { + throw new BadRequestException('Benutzername erforderlich für persönlichen Scan'); + } + doc.Source = 'user'; + doc.OwnerUsername = preferredUsername; + } + + await this.documentRepo.save(doc); + } } diff --git a/paperless-frontend/src/api/inbox.ts b/paperless-frontend/src/api/inbox.ts index 04049cc..21abf92 100644 --- a/paperless-frontend/src/api/inbox.ts +++ b/paperless-frontend/src/api/inbox.ts @@ -89,6 +89,10 @@ export const inboxApi = { opts ?? {}, ) .then((r) => r.data), + updateSource: (id: string, source: InboxSource) => + api + .post(`/api/inbox/${encodeURIComponent(id)}/source`, { source }) + .then((r) => r.data), }; export interface PostprocessActionResult { diff --git a/paperless-frontend/src/pages/InboxPage.tsx b/paperless-frontend/src/pages/InboxPage.tsx index d01595d..46a3b94 100644 --- a/paperless-frontend/src/pages/InboxPage.tsx +++ b/paperless-frontend/src/pages/InboxPage.tsx @@ -22,6 +22,7 @@ import { ReloadOutlined, ScanOutlined, SearchOutlined, + TeamOutlined, UserOutlined, } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; @@ -168,6 +169,19 @@ export default function InboxPage() { } }; + const handleUpdateSource = async (id: string, current: InboxFile['source']) => { + const next = current === 'all' ? 'user' : 'all'; + try { + await inboxApi.updateSource(id, next); + message.success( + next === 'all' ? 'Zu Öffentlich verschoben' : 'Zu Persönlich verschoben', + ); + await load(); + } catch { + message.error('Verschieben fehlgeschlagen'); + } + }; + const filtered = files.filter((f) => search ? f.name.toLowerCase().includes(search.toLowerCase()) : true, ); @@ -255,6 +269,21 @@ export default function InboxPage() { Löschen + + + ), },