refactor: replace direct Paperless upload with client-side document download functionality
Build and Push Multi-Platform Images / build-and-push (push) Successful in 36s

This commit is contained in:
2026-05-06 09:30:53 +02:00
parent 4f1f030423
commit e08a5697f0
5 changed files with 34 additions and 137 deletions
+2 -11
View File
@@ -107,17 +107,8 @@ export const inboxApi = {
)
.then((r) => r.data),
saveToPaperless: (
id: string,
body: {
title: string;
date?: string;
documentTypeId?: number;
correspondentId?: number;
tagIds?: number[];
},
) =>
api.post(`/api/inbox/${encodeURIComponent(id)}/save-to-paperless`, body).then(() => {}),
downloadBlob: (id: string) =>
api.get<Blob>(`/api/inbox/${encodeURIComponent(id)}/download`, { responseType: 'blob' }).then((r) => r.data),
sendEmail: (
id: string,
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { Button, DatePicker, Dropdown, Empty, Form, Input, Modal, Popconfirm, Select, Space, Spin, Steps, Tag, Tooltip, Typography, message } from 'antd';
import { Button, Dropdown, Empty, Form, Input, Modal, Popconfirm, Space, Spin, Steps, Tag, Tooltip, Typography, message } from 'antd';
import type { MenuProps } from 'antd';
import {
ArrowLeftOutlined,
@@ -25,7 +25,7 @@ import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import { inboxApi, type InboxBarcode, type InboxFile, type PostprocessActionResult } from '../api/inbox';
import { paperlessApi, type PaperlessDocType, type PaperlessCorrespondent, type PaperlessTag } from '../api/paperless';
import { paperlessApi } from '../api/paperless';
const ZOOM_MIN = 0.5;
const ZOOM_MAX = 3;
@@ -528,88 +528,6 @@ function PostprocessWizardModal({
);
}
interface SaveToPaperlessDialogProps {
open: boolean;
fileId: string;
defaultTitle: string;
onClose: () => void;
}
function SaveToPaperlessDialog({ open, fileId, defaultTitle, onClose }: SaveToPaperlessDialogProps) {
const [form] = Form.useForm();
const [submitting, setSubmitting] = useState(false);
const [docTypes, setDocTypes] = useState<PaperlessDocType[]>([]);
const [correspondents, setCorrespondents] = useState<PaperlessCorrespondent[]>([]);
const [tags, setTags] = useState<PaperlessTag[]>([]);
useEffect(() => {
if (!open) return;
form.resetFields();
form.setFieldsValue({ title: defaultTitle });
Promise.all([
paperlessApi.getDocumentTypes(),
paperlessApi.getCorrespondents(),
paperlessApi.getTags(),
]).then(([dt, co, tg]) => {
setDocTypes(dt);
setCorrespondents(co);
setTags(tg);
}).catch(() => {});
}, [open, defaultTitle, form]);
const handleOk = async () => {
try {
const values = await form.validateFields();
setSubmitting(true);
await inboxApi.saveToPaperless(fileId, {
title: values.title,
date: values.date ? values.date.format('YYYY-MM-DD') : undefined,
documentTypeId: values.documentTypeId,
correspondentId: values.correspondentId,
tagIds: values.tagIds,
});
message.success('Dokument wurde an Paperless übertragen');
onClose();
} catch (err: any) {
if (err?.errorFields) return;
message.error('Übertragung fehlgeschlagen');
} finally {
setSubmitting(false);
}
};
return (
<Modal
open={open}
title="Dokument in Paperless speichern"
onCancel={onClose}
onOk={handleOk}
okText="Speichern"
cancelText="Abbrechen"
confirmLoading={submitting}
destroyOnClose
width={520}
>
<Form form={form} layout="vertical" style={{ marginTop: 16 }}>
<Form.Item name="title" label="Titel" rules={[{ required: true, message: 'Bitte Titel angeben' }]}>
<Input />
</Form.Item>
<Form.Item name="date" label="Datum">
<DatePicker style={{ width: '100%' }} format="DD.MM.YYYY" />
</Form.Item>
<Form.Item name="documentTypeId" label="Dokumenttyp">
<Select allowClear placeholder="Kein Typ" options={docTypes.map((d) => ({ value: d.id, label: d.name }))} />
</Form.Item>
<Form.Item name="correspondentId" label="Korrespondent">
<Select allowClear placeholder="Kein Korrespondent" options={correspondents.map((c) => ({ value: c.id, label: c.name }))} />
</Form.Item>
<Form.Item name="tagIds" label="Tags">
<Select mode="multiple" allowClear placeholder="Keine Tags" options={tags.map((t) => ({ value: t.id, label: t.name }))} />
</Form.Item>
</Form>
</Modal>
);
}
function TiptapToolbar({ editor }: { editor: ReturnType<typeof useEditor> }) {
if (!editor) return null;
@@ -720,7 +638,7 @@ export default function InboxDetailPage() {
const [selectedPage, setSelectedPage] = useState(1);
const [zoom, setZoom] = useState(1);
const [wizardOpen, setWizardOpen] = useState(false);
const [saveDialogOpen, setSaveDialogOpen] = useState(false);
const [downloading, setDownloading] = useState(false);
const [emailDialogOpen, setEmailDialogOpen] = useState(false);
const [scanMode, setScanMode] = useState(false);
const [scanning, setScanning] = useState(false);
@@ -1087,7 +1005,8 @@ export default function InboxDetailPage() {
<Dropdown.Button
type="primary"
icon={<DownOutlined />}
disabled={documents.length === 0}
disabled={documents.length === 0 || downloading}
loading={downloading}
onClick={() => setWizardOpen(true)}
menu={{
items: [
@@ -1095,7 +1014,19 @@ export default function InboxDetailPage() {
{ key: 'email', label: 'Als E-Mail-Anhang versenden', icon: <MailOutlined /> },
] as MenuProps['items'],
onClick: ({ key }) => {
if (key === 'save') setSaveDialogOpen(true);
if (key === 'save') {
setDownloading(true);
inboxApi.downloadBlob(file.id).then((blob) => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.name;
a.click();
URL.revokeObjectURL(url);
}).catch(() => {
message.error('Download fehlgeschlagen');
}).finally(() => setDownloading(false));
}
if (key === 'email') setEmailDialogOpen(true);
},
}}
@@ -1523,12 +1454,6 @@ export default function InboxDetailPage() {
onClose={() => setWizardOpen(false)}
onDeleted={() => navigate('/inbox')}
/>
<SaveToPaperlessDialog
open={saveDialogOpen}
fileId={file.id}
defaultTitle={file.name}
onClose={() => setSaveDialogOpen(false)}
/>
<SendEmailDialog
open={emailDialogOpen}
fileId={file.id}