feat: fix signature editor init and expand README
Build and Push Multi-Platform Images / build-and-push (push) Successful in 18s

- Pass initialContent prop to WysiwygEditor instead of imperative setContent
  to ensure mail signature loads correctly on mount
- Rewrite README to reflect full project scope (scanner inbox, email import,
  postprocessing rules, label printing, OIDC auth)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 15:48:23 +02:00
parent 2df3af719b
commit f482304061
3 changed files with 82 additions and 11 deletions
+76 -5
View File
@@ -1,9 +1,80 @@
# Paperless Manager # Paperless Manager
Ein Erweiterungstool für Paperless-ngx zur automatisierten Verarbeitung von E-Mails und Dokumenten. Eine Erweiterungsplattform für [Paperless-NGX](https://github.com/paperless-ngx/paperless-ngx) zur automatisierten Dokumentenverarbeitung von der Scanner-Eingangsbox bis zur regelbasierten Ablage.
## Was ist Paperless Manager?
Paperless-NGX ist ein leistungsstarkes DMS, bietet aber wenig Automatisierung beim Erfassen und Verarbeiten eingehender Dokumente. Paperless Manager schließt diese Lücke:
- Dokumente kommen per Scanner, E-Mail oder Dateiablage herein
- Sie werden aufbereitet, gesplittet, per OCR erkannt und klassifiziert
- Regelwerke entscheiden automatisch über Tags, Export und Weiterleitung
- Etiketten werden direkt aus dem System heraus gedruckt
Der Paperless Manager läuft als eigenständige Anwendung neben Paperless-NGX und kommuniziert über dessen REST API.
## Features ## Features
- Automatischer E-Mail Import mit Barcode-Erkennung
- PDF Splitting und Metadaten-Anreicherung ### Scanner-Eingangsbox
- Multi-Plattform Docker-Unterstützung (AMD64 & ARM64) - Überwachung eines Scan-Verzeichnisses per Filesystem-Watcher
- Gitea Actions CI/CD Integration - PDF-Vorschau, Seitenrotation und Splitting direkt im Browser
- Barcode- und QR-Code-Erkennung zur automatischen Dokumententrennung
- OCR über Ollama (llava Vision-Modell) für handschriftliche und gescannte Seiten
- GoBD-konformes Archivieren der Originaldokumente
### E-Mail-Import
- IMAP-Anbindung zum automatischen Abruf von Postfächern
- Extraktion von E-Mail-Anhängen (PDF, ZUGFeRD-Rechnungen)
- Zuordnung von Absendern zu Paperless-Korrespondenten
### Regelbasierte Nachbearbeitung
- Konfigurierbare Filterregeln (Feld-Operatoren: eq, contains, in, …)
- Aktionen: Tags setzen, Felder aktualisieren, E-Mail senden, WebDAV-Export
- Priorisierbare Regelketten mit Stop-Bedingung
### Etikettendruck-Agent
- SVG-Vorlagen → PNG-Rendering via `@resvg/resvg-js`
- SSE-basierte Job-Queue für angebundene Druckagenten
- Automatische Job-Sperrung zur Vermeidung von Race Conditions
### Authentifizierung & Berechtigungen
- OIDC-Integration (z. B. Authentik) mit JWT-Validierung
- API-Key-Unterstützung für maschinellen Zugriff
- Granulares Berechtigungssystem auf Basis von OIDC-Gruppen
## Technologie
| Schicht | Stack |
|---------|-------|
| Backend | NestJS (TypeScript), TypeORM, MySQL 8 |
| Frontend | React 19, Ant Design, Vite |
| OCR | Ollama (llava) |
| Deployment | Docker Compose, Gitea Actions CI/CD |
| Auth | OIDC (Authentik), JWT, API Keys |
## Deployment
```bash
cp .env.example .env
# .env anpassen (DB, Paperless-URL, OIDC, Ollama, …)
docker compose up -d
```
Backend läuft auf Port `3100`, Frontend wird über nginx ausgeliefert.
Eine vollständige Beschreibung aller Umgebungsvariablen findet sich in `.env.example`.
## Entwicklung
```bash
# Backend
cd paperless-backend
npm install
npm run start:dev
# Frontend
cd paperless-frontend
npm install
npm run dev # Proxy auf localhost:3100
```
@@ -26,6 +26,7 @@ export interface WysiwygEditorHandle {
interface WysiwygEditorProps { interface WysiwygEditorProps {
minHeight?: number; minHeight?: number;
initialContent?: string;
} }
function ToolBtn({ function ToolBtn({
@@ -69,14 +70,14 @@ const HEADING_OPTIONS = [
]; ];
export const WysiwygEditor = forwardRef<WysiwygEditorHandle, WysiwygEditorProps>( export const WysiwygEditor = forwardRef<WysiwygEditorHandle, WysiwygEditorProps>(
({ minHeight = 200 }, ref) => { ({ minHeight = 200, initialContent }, ref) => {
const editor = useEditor({ const editor = useEditor({
extensions: [ extensions: [
StarterKit, StarterKit,
Underline, Underline,
TextAlign.configure({ types: ['heading', 'paragraph'] }), TextAlign.configure({ types: ['heading', 'paragraph'] }),
], ],
content: '', content: initialContent ?? '',
}); });
useImperativeHandle( useImperativeHandle(
@@ -68,6 +68,7 @@ function MailSettingsTab() {
const [testing, setTesting] = useState(false); const [testing, setTesting] = useState(false);
const [testResult, setTestResult] = useState<{ ok: boolean; error?: string } | null>(null); const [testResult, setTestResult] = useState<{ ok: boolean; error?: string } | null>(null);
const [passSet, setPassSet] = useState(false); const [passSet, setPassSet] = useState(false);
const [signatureHtml, setSignatureHtml] = useState<string | null>(null);
const editorRef = useRef<WysiwygEditorHandle>(null); const editorRef = useRef<WysiwygEditorHandle>(null);
useEffect(() => { useEffect(() => {
@@ -81,9 +82,7 @@ function MailSettingsTab() {
smtpFromName: data.smtpFromName ?? '', smtpFromName: data.smtpFromName ?? '',
}); });
setPassSet(data.smtpPassSet); setPassSet(data.smtpPassSet);
if (data.mailSignatureHtml) { setSignatureHtml(data.mailSignatureHtml ?? null);
editorRef.current?.setContent(data.mailSignatureHtml);
}
}).catch(() => { }).catch(() => {
message.error('Einstellungen konnten nicht geladen werden'); message.error('Einstellungen konnten nicht geladen werden');
}).finally(() => setLoading(false)); }).finally(() => setLoading(false));
@@ -167,7 +166,7 @@ function MailSettingsTab() {
</Form.Item> </Form.Item>
<Form.Item label="Signatur"> <Form.Item label="Signatur">
<WysiwygEditor ref={editorRef} minHeight={180} /> <WysiwygEditor ref={editorRef} initialContent={signatureHtml ?? ''} minHeight={180} />
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>