All checks were successful
Deploy Development / deploy (push) Successful in 40s
Test Suite / pytest-backend (push) Successful in 35s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 10s
Test Suite / playwright-tests (push) Successful in 1m1s
141 lines
5.0 KiB
JavaScript
141 lines
5.0 KiB
JavaScript
/**
|
||
* Gemeinsamer Medienvorschau-Dialog.
|
||
*
|
||
* Props:
|
||
* title – Anzeigename des Mediums (Dateiname o.ä.)
|
||
* media – Medienobjekt (mime_type, embed_url, asset_legal_hold_active, media_type)
|
||
* fileUrl – Bereits aufgelöste Datei-URL (null für Embed-only-Medien)
|
||
* onClose – Pflicht
|
||
* onReport – optional; wenn gesetzt, erscheint "Melden"-Button
|
||
* onEdit – optional; wenn gesetzt, erscheint "Bearbeiten"-Button
|
||
*/
|
||
import React from 'react'
|
||
|
||
export default function MediaPreviewModal({ title, media, fileUrl, onClose, onReport, onEdit }) {
|
||
const mlow = (media?.mime_type || '').toLowerCase()
|
||
const isHeic = mlow.includes('heic') || mlow.includes('heif')
|
||
const isImage = !isHeic && (media?.mime_type?.startsWith('image/') || media?.media_type === 'image')
|
||
const isVideo = media?.mime_type?.startsWith('video/') || media?.media_type === 'video'
|
||
const isPdf = mlow.includes('pdf')
|
||
const isLegalHold = !!media?.asset_legal_hold_active
|
||
const canReport = onReport && !isLegalHold
|
||
|
||
function handleBackdrop(e) {
|
||
if (e.target === e.currentTarget) onClose()
|
||
}
|
||
|
||
function handleKeyDown(e) {
|
||
if (e.key === 'Escape') onClose()
|
||
}
|
||
|
||
return (
|
||
<div
|
||
role="dialog"
|
||
aria-modal="true"
|
||
aria-label="Medienvorschau"
|
||
style={{
|
||
position: 'fixed',
|
||
inset: 0,
|
||
background: 'rgba(0,0,0,0.55)',
|
||
zIndex: 1100,
|
||
overflow: 'auto',
|
||
padding: '16px',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
onClick={handleBackdrop}
|
||
onKeyDown={handleKeyDown}
|
||
>
|
||
<div
|
||
className="card"
|
||
style={{ maxWidth: 720, width: '100%', maxHeight: '90vh', overflow: 'auto', padding: '1.25rem' }}
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
{/* Header */}
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem', gap: '0.5rem' }}>
|
||
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||
{title || 'Vorschau'}
|
||
</h3>
|
||
<div style={{ display: 'flex', gap: '0.4rem', flexShrink: 0 }}>
|
||
{canReport && (
|
||
<button type="button" className="btn btn-secondary" style={{ fontSize: '0.85rem', padding: '5px 10px' }} onClick={onReport}>
|
||
Melden
|
||
</button>
|
||
)}
|
||
{onEdit && (
|
||
<button type="button" className="btn btn-secondary" style={{ fontSize: '0.85rem', padding: '5px 10px' }} onClick={onEdit}>
|
||
Bearbeiten
|
||
</button>
|
||
)}
|
||
<button
|
||
type="button"
|
||
className="btn btn-secondary"
|
||
style={{ fontSize: '0.85rem', padding: '5px 10px' }}
|
||
onClick={onClose}
|
||
aria-label="Schließen"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Body */}
|
||
{isLegalHold ? (
|
||
<p style={{ color: 'var(--danger)', fontSize: '0.9rem' }}>
|
||
Dieses Medium ist gesperrt und steht nicht zur Verfügung.
|
||
</p>
|
||
) : media?.embed_url ? (
|
||
<p style={{ fontSize: '14px', wordBreak: 'break-all' }}>
|
||
<a href={media.embed_url} target="_blank" rel="noreferrer">{media.embed_url}</a>
|
||
</p>
|
||
) : isHeic ? (
|
||
<div>
|
||
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>
|
||
HEIC/HEIF — in diesem Browser oft keine eingebettete Vorschau. Zum Ansehen herunterladen oder im neuen Tab öffnen.
|
||
</p>
|
||
{fileUrl && (
|
||
<a className="btn btn-secondary" href={fileUrl} target="_blank" rel="noopener noreferrer">
|
||
Datei öffnen
|
||
</a>
|
||
)}
|
||
</div>
|
||
) : isImage ? (
|
||
<img
|
||
key={media?.id}
|
||
alt=""
|
||
src={fileUrl}
|
||
style={{ maxWidth: '100%', borderRadius: '8px', maxHeight: '70vh', objectFit: 'contain', display: 'block' }}
|
||
/>
|
||
) : isVideo ? (
|
||
<video
|
||
key={media?.id}
|
||
src={fileUrl}
|
||
controls
|
||
playsInline
|
||
preload="metadata"
|
||
style={{ width: '100%', borderRadius: '8px', maxHeight: '70vh' }}
|
||
>
|
||
Wiedergabe nicht unterstützt.
|
||
</video>
|
||
) : isPdf ? (
|
||
<div>
|
||
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>PDF — zur Ansicht im neuen Tab öffnen.</p>
|
||
{fileUrl && (
|
||
<a className="btn btn-secondary" href={fileUrl} target="_blank" rel="noopener noreferrer">
|
||
PDF öffnen
|
||
</a>
|
||
)}
|
||
</div>
|
||
) : fileUrl ? (
|
||
<p style={{ fontSize: '14px' }}>
|
||
<a href={fileUrl} target="_blank" rel="noreferrer">Datei öffnen</a>
|
||
</p>
|
||
) : (
|
||
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>Keine Vorschau verfügbar.</p>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|