feat(admin/exports): inline preview modal with copy-to-clipboard (#631)

Follow-up to #623. The Lightroom TXT export now shows the filename list
in a modal with a "Copy to clipboard" button instead of triggering a
.txt file download — saves the "open file → select all → copy" dance
admins were doing anyway. CSV export takes the same path (paste straight
into Sheets / Excel).

The modal keeps a "Download as file" button so admins who want the file
(sharing with colleagues, archiving, post-processing tooling) aren't
worse off than before — fully additive.

XMP (ZIP archive) and JSON exports keep their direct download path. A
textarea preview is the wrong UI for a binary archive, and JSON is
structured tool input where the file form is the natural mode.

Implementation:

- ExportPreviewModal — readonly textarea, copy + download buttons,
  monospace font for filename lists, click-to-select-all on the textarea
  for browsers that block clipboard writes (older Safari, hardened
  sandboxes — the catch falls through to a "select and copy manually"
  toast instead of silent failure).
- photosService.exportPhotosAsText — same backend endpoint as
  exportPhotos but resolves the blob.text() and returns
  { content, filename } instead of triggering a download. Preserves
  the existing exportPhotos for the XMP / JSON paths.
- PhotoExportMenu — PREVIEW_FORMATS = ['txt', 'csv']; non-preview
  formats keep the direct-download flow unchanged.
- EN + DE i18n entries.

No backend changes. No new endpoints. No breaking changes for callers
of photosService.exportPhotos.
This commit is contained in:
Paul Nothaft
2026-06-17 23:35:19 +02:00
parent 9d3daa1f93
commit 27b5f7e4b6
6 changed files with 228 additions and 6 deletions
+12 -1
View File
@@ -2920,7 +2920,18 @@
"exportFiltered": "Gefilterte Fotos exportieren",
"hint": "Fotos auswählen oder Filter anwenden zum Exportieren",
"exportSelected_one": "{{count}} ausgewähltes exportieren",
"exportSelected_other": "{{count}} ausgewählte exportieren"
"exportSelected_other": "{{count}} ausgewählte exportieren",
"preview": {
"titleTxt": "Dateinamen-Liste für Lightroom",
"titleCsv": "CSV-Export",
"helpTxt": "In das Lightroom-Dateinamensuchfeld einfügen. Die Liste ist kommagetrennt und ohne Dateiendung, damit sie auch zu einem Katalog mit RAW-Dateien passt.",
"helpCsv": "In eine Tabellenkalkulation einfügen (Google Sheets, Excel, Numbers) die erste Zeile ist die Spaltenüberschrift.",
"copyButton": "In die Zwischenablage kopieren",
"copiedShort": "Kopiert",
"copied": "In die Zwischenablage kopiert.",
"copyFailed": "Zugriff auf die Zwischenablage blockiert. Bitte den Text markieren und manuell kopieren.",
"download": "Als Datei herunterladen"
}
},
"clientAccess": {
"title": "Kundenzugang",
+12 -1
View File
@@ -2989,7 +2989,18 @@
"exportFiltered": "Export filtered photos",
"hint": "Select photos or apply filters to export",
"exportSelected_one": "Export {{count}} selected",
"exportSelected_other": "Export {{count}} selected"
"exportSelected_other": "Export {{count}} selected",
"preview": {
"titleTxt": "Lightroom filename list",
"titleCsv": "CSV export",
"helpTxt": "Paste into Lightroom's filename search. The list is comma-separated with no extension so it matches a catalog that holds RAW files.",
"helpCsv": "Paste into a spreadsheet (Google Sheets, Excel, Numbers) — the first row is the column header.",
"copyButton": "Copy to clipboard",
"copiedShort": "Copied",
"copied": "Copied to clipboard.",
"copyFailed": "Clipboard write blocked. Select the text and copy manually.",
"download": "Download as file"
}
},
"photoSort": {
"defaultSort": "Default Photo Sort",