DGSVO Compliance update 1 #30
|
|
@ -9,7 +9,40 @@ import {
|
||||||
sanitizeInlineMediaSize,
|
sanitizeInlineMediaSize,
|
||||||
} from '../constants/inlineExerciseMedia'
|
} from '../constants/inlineExerciseMedia'
|
||||||
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
|
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
|
||||||
import RightsDeclarationDialog from './RightsDeclarationDialog'
|
|
||||||
|
const DECL_INIT = {
|
||||||
|
rights_holder_confirmed: false,
|
||||||
|
contains_identifiable_persons: null,
|
||||||
|
person_consent_confirmed: false,
|
||||||
|
contains_minors: null,
|
||||||
|
parental_consent_confirmed: false,
|
||||||
|
contains_music: null,
|
||||||
|
music_rights_confirmed: false,
|
||||||
|
contains_third_party_content: null,
|
||||||
|
third_party_rights_confirmed: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateDecl(decl) {
|
||||||
|
if (!decl.rights_holder_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass du die erforderlichen Rechte an diesem Medium besitzt.'
|
||||||
|
if (decl.contains_identifiable_persons === null)
|
||||||
|
return 'Bitte angeben, ob erkennbare Personen abgebildet sind.'
|
||||||
|
if (decl.contains_identifiable_persons && !decl.person_consent_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Einwilligungen aller erkennbaren Personen vorliegen.'
|
||||||
|
if (decl.contains_minors === null)
|
||||||
|
return 'Bitte angeben, ob Minderjährige abgebildet sind.'
|
||||||
|
if (decl.contains_minors && !decl.parental_consent_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Einwilligungen der Sorgeberechtigten vorliegen.'
|
||||||
|
if (decl.contains_music === null)
|
||||||
|
return 'Bitte angeben, ob das Medium Musik enthält.'
|
||||||
|
if (decl.contains_music && !decl.music_rights_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die erforderlichen Musikrechte vorliegen.'
|
||||||
|
if (decl.contains_third_party_content === null)
|
||||||
|
return 'Bitte angeben, ob fremde geschützte Inhalte enthalten sind.'
|
||||||
|
if (decl.contains_third_party_content && !decl.third_party_rights_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Rechte an allen enthaltenen Fremdmaterialien vorliegen.'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {{
|
* @param {{
|
||||||
|
|
@ -31,27 +64,32 @@ export default function ExerciseInlineEmbedModal({
|
||||||
const [title, setTitle] = useState('')
|
const [title, setTitle] = useState('')
|
||||||
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
|
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
|
||||||
const [busy, setBusy] = useState(false)
|
const [busy, setBusy] = useState(false)
|
||||||
const [rightsDialogOpen, setRightsDialogOpen] = useState(false)
|
const [decl, setDecl] = useState({ ...DECL_INIT })
|
||||||
|
const [declErr, setDeclErr] = useState('')
|
||||||
|
|
||||||
|
const setDeclField = (key, val) => setDecl((d) => ({ ...d, [key]: val }))
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return
|
if (!open) return
|
||||||
setUrl('')
|
setUrl('')
|
||||||
setTitle('')
|
setTitle('')
|
||||||
setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
|
setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
|
||||||
|
setDecl({ ...DECL_INIT })
|
||||||
|
setDeclErr('')
|
||||||
}, [open])
|
}, [open])
|
||||||
|
|
||||||
const submit = () => {
|
const submit = async () => {
|
||||||
const u = url.trim()
|
const u = url.trim()
|
||||||
if (!u) {
|
if (!u) {
|
||||||
alert('Bitte eine Embed-URL eingeben (https://…).')
|
alert('Bitte eine Embed-URL eingeben (https://…).')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setRightsDialogOpen(true)
|
const validErr = validateDecl(decl)
|
||||||
|
if (validErr) {
|
||||||
|
setDeclErr(validErr)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
setDeclErr('')
|
||||||
const doSubmitWithDecl = async (decl) => {
|
|
||||||
setRightsDialogOpen(false)
|
|
||||||
const u = url.trim()
|
|
||||||
const size = sanitizeInlineMediaSize(displaySize)
|
const size = sanitizeInlineMediaSize(displaySize)
|
||||||
const fd = new FormData()
|
const fd = new FormData()
|
||||||
fd.append('embed_url', u)
|
fd.append('embed_url', u)
|
||||||
|
|
@ -86,21 +124,13 @@ export default function ExerciseInlineEmbedModal({
|
||||||
if (!open) return null
|
if (!open) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && !busy && onClose()}>
|
||||||
<RightsDeclarationDialog
|
|
||||||
open={rightsDialogOpen}
|
|
||||||
onCancel={() => setRightsDialogOpen(false)}
|
|
||||||
onConfirm={doSubmitWithDecl}
|
|
||||||
targetVisibility="private"
|
|
||||||
mode="upload"
|
|
||||||
/>
|
|
||||||
<div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && !busy && !rightsDialogOpen && onClose()}>
|
|
||||||
<div
|
<div
|
||||||
className="admin-modal-sheet"
|
className="admin-modal-sheet"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="rte-inline-embed-title"
|
aria-labelledby="rte-inline-embed-title"
|
||||||
style={{ maxWidth: '480px', width: '100%' }}
|
style={{ maxWidth: '480px', width: '100%', maxHeight: '90vh', display: 'flex', flexDirection: 'column' }}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div className="admin-modal-sheet__header">
|
<div className="admin-modal-sheet__header">
|
||||||
|
|
@ -111,7 +141,7 @@ export default function ExerciseInlineEmbedModal({
|
||||||
Schließen
|
Schließen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: '14px 16px' }}>
|
<div style={{ overflowY: 'auto', flex: 1, padding: '14px 16px' }}>
|
||||||
<label className="form-label">Embed-URL</label>
|
<label className="form-label">Embed-URL</label>
|
||||||
<input
|
<input
|
||||||
type="url"
|
type="url"
|
||||||
|
|
@ -141,12 +171,135 @@ export default function ExerciseInlineEmbedModal({
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<button type="button" className="btn btn-primary btn-full" style={{ marginTop: '16px' }} disabled={busy} onClick={submit}>
|
|
||||||
|
{/* P-06 Rechte-Erklärung */}
|
||||||
|
<div style={{ marginTop: '18px', paddingTop: '14px', borderTop: '1px solid var(--border)' }}>
|
||||||
|
<p style={{ fontSize: '0.82rem', fontWeight: 600, marginBottom: '10px', color: 'var(--text2)' }}>
|
||||||
|
Rechte-Erklärung <span style={{ fontWeight: 400, color: 'var(--text3)' }}>(VORLÄUFIG – p06-v1-conservative)</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginBottom: '10px' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="emb-rhc"
|
||||||
|
checked={decl.rights_holder_confirmed}
|
||||||
|
onChange={(e) => setDeclField('rights_holder_confirmed', e.target.checked)}
|
||||||
|
disabled={busy}
|
||||||
|
style={{ marginTop: '3px', flexShrink: 0 }}
|
||||||
|
/>
|
||||||
|
<label htmlFor="emb-rhc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Ich bestätige, dass ich die erforderlichen Rechte an diesem Medium besitze oder zur Veröffentlichung berechtigt bin. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Erkennbare Personen abgebildet? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cip" checked={decl.contains_identifiable_persons === true}
|
||||||
|
onChange={() => setDeclField('contains_identifiable_persons', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cip" checked={decl.contains_identifiable_persons === false}
|
||||||
|
onChange={() => setDeclField('contains_identifiable_persons', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_identifiable_persons === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="emb-pcc" checked={decl.person_consent_confirmed}
|
||||||
|
onChange={(e) => setDeclField('person_consent_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="emb-pcc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Einwilligungen aller erkennbaren Personen liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Minderjährige abgebildet? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cm" checked={decl.contains_minors === true}
|
||||||
|
onChange={() => setDeclField('contains_minors', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cm" checked={decl.contains_minors === false}
|
||||||
|
onChange={() => setDeclField('contains_minors', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_minors === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="emb-pcc2" checked={decl.parental_consent_confirmed}
|
||||||
|
onChange={(e) => setDeclField('parental_consent_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="emb-pcc2" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Einwilligungen der Sorgeberechtigten liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Musik enthalten? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cmu" checked={decl.contains_music === true}
|
||||||
|
onChange={() => setDeclField('contains_music', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-cmu" checked={decl.contains_music === false}
|
||||||
|
onChange={() => setDeclField('contains_music', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_music === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="emb-mrc" checked={decl.music_rights_confirmed}
|
||||||
|
onChange={(e) => setDeclField('music_rights_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="emb-mrc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Musikrechte (GEMA / Lizenz) liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '4px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Fremde geschützte Inhalte (Logos, Grafiken, Fotos Dritter)? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-ctpc" checked={decl.contains_third_party_content === true}
|
||||||
|
onChange={() => setDeclField('contains_third_party_content', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="emb-ctpc" checked={decl.contains_third_party_content === false}
|
||||||
|
onChange={() => setDeclField('contains_third_party_content', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_third_party_content === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="emb-tprc" checked={decl.third_party_rights_confirmed}
|
||||||
|
onChange={(e) => setDeclField('third_party_rights_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="emb-tprc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Rechte an allen enthaltenen Fremdmaterialien liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{declErr && (
|
||||||
|
<p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginTop: '8px' }}>{declErr}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ padding: '12px 16px', borderTop: '1px solid var(--border)', flexShrink: 0 }}>
|
||||||
|
<button type="button" className="btn btn-primary btn-full" disabled={busy} onClick={submit}>
|
||||||
{busy ? 'Speichern…' : 'Hinzufügen & in Text einfügen'}
|
{busy ? 'Speichern…' : 'Hinzufügen & in Text einfügen'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
sanitizeInlineMediaSize,
|
sanitizeInlineMediaSize,
|
||||||
} from '../constants/inlineExerciseMedia'
|
} from '../constants/inlineExerciseMedia'
|
||||||
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
|
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
|
||||||
import RightsDeclarationDialog from './RightsDeclarationDialog'
|
|
||||||
|
|
||||||
function RtePickerAssetThumb({ asset }) {
|
function RtePickerAssetThumb({ asset }) {
|
||||||
const id = asset.id
|
const id = asset.id
|
||||||
|
|
@ -61,6 +60,40 @@ function inferExerciseMediaType(file) {
|
||||||
return 'image'
|
return 'image'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DECL_INIT = {
|
||||||
|
rights_holder_confirmed: false,
|
||||||
|
contains_identifiable_persons: null,
|
||||||
|
person_consent_confirmed: false,
|
||||||
|
contains_minors: null,
|
||||||
|
parental_consent_confirmed: false,
|
||||||
|
contains_music: null,
|
||||||
|
music_rights_confirmed: false,
|
||||||
|
contains_third_party_content: null,
|
||||||
|
third_party_rights_confirmed: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateDecl(decl) {
|
||||||
|
if (!decl.rights_holder_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass du die erforderlichen Rechte an diesem Medium besitzt.'
|
||||||
|
if (decl.contains_identifiable_persons === null)
|
||||||
|
return 'Bitte angeben, ob erkennbare Personen abgebildet sind.'
|
||||||
|
if (decl.contains_identifiable_persons && !decl.person_consent_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Einwilligungen aller erkennbaren Personen vorliegen.'
|
||||||
|
if (decl.contains_minors === null)
|
||||||
|
return 'Bitte angeben, ob Minderjährige abgebildet sind.'
|
||||||
|
if (decl.contains_minors && !decl.parental_consent_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Einwilligungen der Sorgeberechtigten vorliegen.'
|
||||||
|
if (decl.contains_music === null)
|
||||||
|
return 'Bitte angeben, ob das Medium Musik enthält.'
|
||||||
|
if (decl.contains_music && !decl.music_rights_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die erforderlichen Musikrechte vorliegen.'
|
||||||
|
if (decl.contains_third_party_content === null)
|
||||||
|
return 'Bitte angeben, ob fremde geschützte Inhalte enthalten sind.'
|
||||||
|
if (decl.contains_third_party_content && !decl.third_party_rights_confirmed)
|
||||||
|
return 'Bitte bestätigen, dass die Rechte an allen enthaltenen Fremdmaterialien vorliegen.'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {{
|
* @param {{
|
||||||
* open: boolean,
|
* open: boolean,
|
||||||
|
|
@ -90,7 +123,10 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
const [uploadTitle, setUploadTitle] = useState('')
|
const [uploadTitle, setUploadTitle] = useState('')
|
||||||
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
|
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
|
||||||
const [uploadInputKey, setUploadInputKey] = useState(0)
|
const [uploadInputKey, setUploadInputKey] = useState(0)
|
||||||
const [rightsDialogOpen, setRightsDialogOpen] = useState(false)
|
const [decl, setDecl] = useState({ ...DECL_INIT })
|
||||||
|
const [declErr, setDeclErr] = useState('')
|
||||||
|
|
||||||
|
const setDeclField = (key, val) => setDecl((d) => ({ ...d, [key]: val }))
|
||||||
|
|
||||||
const assetToExerciseMedia = useMemo(() => {
|
const assetToExerciseMedia = useMemo(() => {
|
||||||
const m = new Map()
|
const m = new Map()
|
||||||
|
|
@ -128,6 +164,8 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
setUploadInputKey((k) => k + 1)
|
setUploadInputKey((k) => k + 1)
|
||||||
setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
|
setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
|
||||||
setErr(null)
|
setErr(null)
|
||||||
|
setDecl({ ...DECL_INIT })
|
||||||
|
setDeclErr('')
|
||||||
const t = setTimeout(loadAssets, 280)
|
const t = setTimeout(loadAssets, 280)
|
||||||
return () => clearTimeout(t)
|
return () => clearTimeout(t)
|
||||||
}, [open])
|
}, [open])
|
||||||
|
|
@ -184,16 +222,17 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUploadAndInsert = () => {
|
const handleUploadAndInsert = async () => {
|
||||||
if (!uploadFile) {
|
if (!uploadFile) {
|
||||||
alert('Bitte eine Datei wählen.')
|
alert('Bitte eine Datei wählen.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setRightsDialogOpen(true)
|
const validErr = validateDecl(decl)
|
||||||
|
if (validErr) {
|
||||||
|
setDeclErr(validErr)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
setDeclErr('')
|
||||||
const doUploadWithDecl = async (decl) => {
|
|
||||||
setRightsDialogOpen(false)
|
|
||||||
const size = sanitizeInlineMediaSize(displaySize)
|
const size = sanitizeInlineMediaSize(displaySize)
|
||||||
const inferred = inferExerciseMediaType(uploadFile)
|
const inferred = inferExerciseMediaType(uploadFile)
|
||||||
const fd = new FormData()
|
const fd = new FormData()
|
||||||
|
|
@ -242,15 +281,7 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
if (!open) return null
|
if (!open) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && !busy && onClose()}>
|
||||||
<RightsDeclarationDialog
|
|
||||||
open={rightsDialogOpen}
|
|
||||||
onCancel={() => setRightsDialogOpen(false)}
|
|
||||||
onConfirm={doUploadWithDecl}
|
|
||||||
targetVisibility="private"
|
|
||||||
mode="upload"
|
|
||||||
/>
|
|
||||||
<div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && !busy && !rightsDialogOpen && onClose()}>
|
|
||||||
<div
|
<div
|
||||||
className="admin-modal-sheet rte-inline-media-modal"
|
className="admin-modal-sheet rte-inline-media-modal"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
|
|
@ -339,7 +370,7 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{!loading && items.length === 0 ? (
|
{!loading && items.length === 0 ? (
|
||||||
<p style={{ color: 'var(--text3)', marginTop: '12px' }}>Keine Treffer — Suche anpassen oder „Neu hochladen“.</p>
|
<p style={{ color: 'var(--text3)', marginTop: '12px' }}>Keine Treffer — Suche anpassen oder „Neu hochladen".</p>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
@ -376,6 +407,127 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
onChange={(e) => setUploadTitle(e.target.value)}
|
onChange={(e) => setUploadTitle(e.target.value)}
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* P-06 Rechte-Erklärung */}
|
||||||
|
<div style={{ marginTop: '18px', paddingTop: '14px', borderTop: '1px solid var(--border)' }}>
|
||||||
|
<p style={{ fontSize: '0.82rem', fontWeight: 600, marginBottom: '10px', color: 'var(--text2)' }}>
|
||||||
|
Rechte-Erklärung <span style={{ fontWeight: 400, color: 'var(--text3)' }}>(VORLÄUFIG – p06-v1-conservative)</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginBottom: '10px' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="up-rhc"
|
||||||
|
checked={decl.rights_holder_confirmed}
|
||||||
|
onChange={(e) => setDeclField('rights_holder_confirmed', e.target.checked)}
|
||||||
|
disabled={busy}
|
||||||
|
style={{ marginTop: '3px', flexShrink: 0 }}
|
||||||
|
/>
|
||||||
|
<label htmlFor="up-rhc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Ich bestätige, dass ich die erforderlichen Rechte an diesem Medium besitze oder zur Veröffentlichung berechtigt bin. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Erkennbare Personen abgebildet? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cip" checked={decl.contains_identifiable_persons === true}
|
||||||
|
onChange={() => setDeclField('contains_identifiable_persons', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cip" checked={decl.contains_identifiable_persons === false}
|
||||||
|
onChange={() => setDeclField('contains_identifiable_persons', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_identifiable_persons === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="up-pcc" checked={decl.person_consent_confirmed}
|
||||||
|
onChange={(e) => setDeclField('person_consent_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="up-pcc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Einwilligungen aller erkennbaren Personen liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Minderjährige abgebildet? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cm" checked={decl.contains_minors === true}
|
||||||
|
onChange={() => setDeclField('contains_minors', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cm" checked={decl.contains_minors === false}
|
||||||
|
onChange={() => setDeclField('contains_minors', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_minors === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="up-pcc2" checked={decl.parental_consent_confirmed}
|
||||||
|
onChange={(e) => setDeclField('parental_consent_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="up-pcc2" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Einwilligungen der Sorgeberechtigten liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Musik enthalten? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cmu" checked={decl.contains_music === true}
|
||||||
|
onChange={() => setDeclField('contains_music', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-cmu" checked={decl.contains_music === false}
|
||||||
|
onChange={() => setDeclField('contains_music', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_music === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="up-mrc" checked={decl.music_rights_confirmed}
|
||||||
|
onChange={(e) => setDeclField('music_rights_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="up-mrc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Musikrechte (GEMA / Lizenz) liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style={{ border: 'none', padding: 0, marginBottom: '4px' }}>
|
||||||
|
<legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Fremde geschützte Inhalte (Logos, Grafiken, Fotos Dritter)? *</legend>
|
||||||
|
<div style={{ display: 'flex', gap: '14px' }}>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-ctpc" checked={decl.contains_third_party_content === true}
|
||||||
|
onChange={() => setDeclField('contains_third_party_content', true)} disabled={busy} /> Ja
|
||||||
|
</label>
|
||||||
|
<label style={{ fontSize: '0.85rem' }}>
|
||||||
|
<input type="radio" name="up-ctpc" checked={decl.contains_third_party_content === false}
|
||||||
|
onChange={() => setDeclField('contains_third_party_content', false)} disabled={busy} /> Nein
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{decl.contains_third_party_content === true && (
|
||||||
|
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
|
||||||
|
<input type="checkbox" id="up-tprc" checked={decl.third_party_rights_confirmed}
|
||||||
|
onChange={(e) => setDeclField('third_party_rights_confirmed', e.target.checked)}
|
||||||
|
disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
|
||||||
|
<label htmlFor="up-tprc" style={{ fontSize: '0.85rem' }}>
|
||||||
|
Rechte an allen enthaltenen Fremdmaterialien liegen vor. *
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{declErr && (
|
||||||
|
<p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginTop: '8px' }}>{declErr}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -410,6 +562,5 @@ export default function ExerciseInlineFileMediaModal({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user