fix(p06): RightsDeclarationDialog als echtes Modal (admin-modal-backdrop)
Some checks failed
Deploy Development / deploy (push) Successful in 38s
Test Suite / pytest-backend (push) Successful in 47s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 10s
Test Suite / playwright-tests (push) Failing after 1m1s

modal-overlay/modal-content existierten nicht im CSS und hatten kein
Styling -- daher kein Backdrop, keine Zentrierung. Umgestellt auf
admin-modal-backdrop + admin-modal-sheet wie alle anderen Modals in der App.

version: 0.8.76

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lars 2026-05-11 08:51:56 +02:00
parent 9ac8200b41
commit 42aec79ad1

View File

@ -89,149 +89,153 @@ export default function RightsDeclarationDialog({
} }
return ( return (
<div className="modal-overlay" role="dialog" aria-modal="true" aria-label="Rechte-Erklärung"> <div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && handleCancel()}>
<div className="modal-content" style={{ maxWidth: 560 }}> <div
<h2 style={{ marginBottom: 4 }}>{titleMap[mode] || titleMap.upload}</h2> className="admin-modal-sheet"
<p style={{ fontSize: '0.85rem', color: 'var(--text2)', marginBottom: 16 }}> role="dialog"
VORLÄUFIG Texte noch nicht juristisch geprüft (p06-v1-conservative). aria-modal="true"
{isPromotion && ( aria-labelledby="rights-decl-title"
<> Die bestehende Erklärung gilt nicht für die Sichtbarkeit {visLabel}". Bitte erneut bestätigen.</> style={{ maxWidth: '520px', width: '100%', maxHeight: '90vh', display: 'flex', flexDirection: 'column' }}
)} onClick={(e) => e.stopPropagation()}
</p> >
<div className="admin-modal-sheet__header">
{/* T1 */} <h3 id="rights-decl-title" className="admin-modal-sheet__title">
<div className="form-row" style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}> {titleMap[mode] || titleMap.upload}
<input </h3>
type="checkbox" <button type="button" className="btn btn-secondary admin-modal-sheet__close" onClick={handleCancel}>
id="rhc" Abbrechen
checked={decl.rights_holder_confirmed} </button>
onChange={(e) => setField('rights_holder_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }}
/>
<label htmlFor="rhc" style={{ fontSize: '0.9rem' }}>
Ich bestätige, dass ich die erforderlichen Urheber- und Nutzungsrechte an diesem Medium besitze
oder rechtmäßig zur Veröffentlichung berechtigt bin. *
</label>
</div> </div>
{/* T2 / T3 */} <div style={{ overflowY: 'auto', flex: 1, padding: '14px 16px' }}>
<fieldset style={{ border: 'none', padding: 0, marginTop: 14 }}> <p style={{ fontSize: '0.82rem', color: 'var(--text3)', marginBottom: 16 }}>
<legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}> VORLÄUFIG Texte noch nicht juristisch geprüft (p06-v1-conservative).
Sind erkennbare Personen abgebildet? * {isPromotion && (
</legend> <> Die bestehende Erklärung gilt nicht für die Sichtbarkeit {visLabel}". Bitte erneut bestätigen.</>
<div style={{ display: 'flex', gap: 16 }}> )}
<label style={{ fontSize: '0.9rem' }}> </p>
<input type="radio" name="cip" checked={decl.contains_identifiable_persons === true}
onChange={() => setField('contains_identifiable_persons', true)} /> Ja <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 14 }}>
</label> <input
<label style={{ fontSize: '0.9rem' }}> type="checkbox"
<input type="radio" name="cip" checked={decl.contains_identifiable_persons === false} id="rdlg-rhc"
onChange={() => setField('contains_identifiable_persons', false)} /> Nein checked={decl.rights_holder_confirmed}
onChange={(e) => setField('rights_holder_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }}
/>
<label htmlFor="rdlg-rhc" style={{ fontSize: '0.9rem' }}>
Ich bestätige, dass ich die erforderlichen Urheber- und Nutzungsrechte an diesem Medium besitze
oder rechtmäßig zur Veröffentlichung berechtigt bin. *
</label> </label>
</div> </div>
{decl.contains_identifiable_persons === true && (
<div className="form-row" style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}> <fieldset style={{ border: 'none', padding: 0, marginBottom: 14 }}>
<input type="checkbox" id="pcc" checked={decl.person_consent_confirmed} <legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}>Erkennbare Personen abgebildet? *</legend>
onChange={(e) => setField('person_consent_confirmed', e.target.checked)} <div style={{ display: 'flex', gap: 16 }}>
style={{ marginTop: 3, flexShrink: 0 }} /> <label style={{ fontSize: '0.9rem' }}>
<label htmlFor="pcc" style={{ fontSize: '0.9rem' }}> <input type="radio" name="rdlg-cip" checked={decl.contains_identifiable_persons === true}
Ich bestätige, dass die Einwilligungen aller erkennbaren Personen zur Abbildung vorliegen. * onChange={() => setField('contains_identifiable_persons', true)} /> Ja
</label>
<label style={{ fontSize: '0.9rem' }}>
<input type="radio" name="rdlg-cip" checked={decl.contains_identifiable_persons === false}
onChange={() => setField('contains_identifiable_persons', false)} /> Nein
</label> </label>
</div> </div>
)} {decl.contains_identifiable_persons === true && (
</fieldset> <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="rdlg-pcc" checked={decl.person_consent_confirmed}
onChange={(e) => setField('person_consent_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="rdlg-pcc" style={{ fontSize: '0.9rem' }}>
Einwilligungen aller erkennbaren Personen liegen vor. *
</label>
</div>
)}
</fieldset>
{/* T4 / T5 */} <fieldset style={{ border: 'none', padding: 0, marginBottom: 14 }}>
<fieldset style={{ border: 'none', padding: 0, marginTop: 14 }}> <legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}>Minderjährige abgebildet? *</legend>
<legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}> <div style={{ display: 'flex', gap: 16 }}>
Sind Minderjährige abgebildet? * <label style={{ fontSize: '0.9rem' }}>
</legend> <input type="radio" name="rdlg-cm" checked={decl.contains_minors === true}
<div style={{ display: 'flex', gap: 16 }}> onChange={() => setField('contains_minors', true)} /> Ja
<label style={{ fontSize: '0.9rem' }}> </label>
<input type="radio" name="cm" checked={decl.contains_minors === true} <label style={{ fontSize: '0.9rem' }}>
onChange={() => setField('contains_minors', true)} /> Ja <input type="radio" name="rdlg-cm" checked={decl.contains_minors === false}
</label> onChange={() => setField('contains_minors', false)} /> Nein
<label style={{ fontSize: '0.9rem' }}>
<input type="radio" name="cm" checked={decl.contains_minors === false}
onChange={() => setField('contains_minors', false)} /> Nein
</label>
</div>
{decl.contains_minors === true && (
<div className="form-row" style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="pcc2" checked={decl.parental_consent_confirmed}
onChange={(e) => setField('parental_consent_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="pcc2" style={{ fontSize: '0.9rem' }}>
Ich bestätige, dass die Einwilligungen der Sorgeberechtigten vorliegen. *
</label> </label>
</div> </div>
)} {decl.contains_minors === true && (
</fieldset> <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="rdlg-pcc2" checked={decl.parental_consent_confirmed}
onChange={(e) => setField('parental_consent_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="rdlg-pcc2" style={{ fontSize: '0.9rem' }}>
Einwilligungen der Sorgeberechtigten liegen vor. *
</label>
</div>
)}
</fieldset>
{/* T6 / T7 */} <fieldset style={{ border: 'none', padding: 0, marginBottom: 14 }}>
<fieldset style={{ border: 'none', padding: 0, marginTop: 14 }}> <legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}>Musik enthalten? *</legend>
<legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}> <div style={{ display: 'flex', gap: 16 }}>
Enthält das Medium Musik? * <label style={{ fontSize: '0.9rem' }}>
</legend> <input type="radio" name="rdlg-cmu" checked={decl.contains_music === true}
<div style={{ display: 'flex', gap: 16 }}> onChange={() => setField('contains_music', true)} /> Ja
<label style={{ fontSize: '0.9rem' }}> </label>
<input type="radio" name="cmu" checked={decl.contains_music === true} <label style={{ fontSize: '0.9rem' }}>
onChange={() => setField('contains_music', true)} /> Ja <input type="radio" name="rdlg-cmu" checked={decl.contains_music === false}
</label> onChange={() => setField('contains_music', false)} /> Nein
<label style={{ fontSize: '0.9rem' }}>
<input type="radio" name="cmu" checked={decl.contains_music === false}
onChange={() => setField('contains_music', false)} /> Nein
</label>
</div>
{decl.contains_music === true && (
<div className="form-row" style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="mrc" checked={decl.music_rights_confirmed}
onChange={(e) => setField('music_rights_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="mrc" style={{ fontSize: '0.9rem' }}>
Ich bestätige, dass die erforderlichen Musikrechte (GEMA / Lizenz) vorliegen. *
</label> </label>
</div> </div>
)} {decl.contains_music === true && (
</fieldset> <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="rdlg-mrc" checked={decl.music_rights_confirmed}
onChange={(e) => setField('music_rights_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="rdlg-mrc" style={{ fontSize: '0.9rem' }}>
Musikrechte (GEMA / Lizenz) liegen vor. *
</label>
</div>
)}
</fieldset>
{/* T8 / T9 */} <fieldset style={{ border: 'none', padding: 0, marginBottom: 4 }}>
<fieldset style={{ border: 'none', padding: 0, marginTop: 14 }}> <legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}>Fremde geschützte Inhalte (Logos, Grafiken, Fotos Dritter)? *</legend>
<legend style={{ fontSize: '0.9rem', fontWeight: 600, marginBottom: 6 }}> <div style={{ display: 'flex', gap: 16 }}>
Enthält das Medium fremde geschützte Inhalte (Logos, Grafiken, Fotos Dritter)? * <label style={{ fontSize: '0.9rem' }}>
</legend> <input type="radio" name="rdlg-ctpc" checked={decl.contains_third_party_content === true}
<div style={{ display: 'flex', gap: 16 }}> onChange={() => setField('contains_third_party_content', true)} /> Ja
<label style={{ fontSize: '0.9rem' }}> </label>
<input type="radio" name="ctpc" checked={decl.contains_third_party_content === true} <label style={{ fontSize: '0.9rem' }}>
onChange={() => setField('contains_third_party_content', true)} /> Ja <input type="radio" name="rdlg-ctpc" checked={decl.contains_third_party_content === false}
</label> onChange={() => setField('contains_third_party_content', false)} /> Nein
<label style={{ fontSize: '0.9rem' }}>
<input type="radio" name="ctpc" checked={decl.contains_third_party_content === false}
onChange={() => setField('contains_third_party_content', false)} /> Nein
</label>
</div>
{decl.contains_third_party_content === true && (
<div className="form-row" style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="tprc" checked={decl.third_party_rights_confirmed}
onChange={(e) => setField('third_party_rights_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="tprc" style={{ fontSize: '0.9rem' }}>
Ich bestätige, dass die Rechte an allen enthaltenen Fremdmaterialien vorliegen. *
</label> </label>
</div> </div>
{decl.contains_third_party_content === true && (
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginTop: 8 }}>
<input type="checkbox" id="rdlg-tprc" checked={decl.third_party_rights_confirmed}
onChange={(e) => setField('third_party_rights_confirmed', e.target.checked)}
style={{ marginTop: 3, flexShrink: 0 }} />
<label htmlFor="rdlg-tprc" style={{ fontSize: '0.9rem' }}>
Rechte an allen enthaltenen Fremdmaterialien liegen vor. *
</label>
</div>
)}
</fieldset>
{error && (
<p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginTop: 12 }}>{error}</p>
)} )}
</fieldset> </div>
{error && ( <div style={{ padding: '12px 16px', borderTop: '1px solid var(--border)', flexShrink: 0, display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
<p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginTop: 12 }}>{error}</p>
)}
<div style={{ display: 'flex', gap: 10, marginTop: 20, justifyContent: 'flex-end' }}>
<button className="btn btn-secondary" type="button" onClick={handleCancel}> <button className="btn btn-secondary" type="button" onClick={handleCancel}>
Abbrechen Abbrechen
</button> </button>
<button className="btn btn-primary" type="button" onClick={handleConfirm}> <button className="btn btn-primary" type="button" onClick={handleConfirm}>
Bestätigen &amp; fortfahren Bestätigen &amp; hochladen
</button> </button>
</div> </div>
</div> </div>