diff --git a/backend/version.py b/backend/version.py
index b19994f..8bdb2a6 100644
--- a/backend/version.py
+++ b/backend/version.py
@@ -1,6 +1,6 @@
# Shinkan Jinkendo Version Information
-APP_VERSION = "0.8.75"
+APP_VERSION = "0.8.76"
BUILD_DATE = "2026-05-11"
DB_SCHEMA_VERSION = "20260511048"
@@ -31,6 +31,13 @@ MODULE_VERSIONS = {
}
CHANGELOG = [
+ {
+ "version": "0.8.76",
+ "date": "2026-05-11",
+ "changes": [
+ "Fix P-06: RightsDeclarationDialog in ExerciseInlineFileMediaModal (Upload-Tab) und ExerciseInlineEmbedModal integriert; vor jedem Exercise-Media-Upload oeffnet sich der vollstaendige Einwilligungsdialog statt eines nicht-benutzbaren alert()",
+ ],
+ },
{
"version": "0.8.75",
"date": "2026-05-11",
diff --git a/frontend/src/components/ExerciseInlineEmbedModal.jsx b/frontend/src/components/ExerciseInlineEmbedModal.jsx
index f54e912..6357bdb 100644
--- a/frontend/src/components/ExerciseInlineEmbedModal.jsx
+++ b/frontend/src/components/ExerciseInlineEmbedModal.jsx
@@ -9,6 +9,7 @@ import {
sanitizeInlineMediaSize,
} from '../constants/inlineExerciseMedia'
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
+import RightsDeclarationDialog from './RightsDeclarationDialog'
/**
* @param {{
@@ -30,6 +31,7 @@ export default function ExerciseInlineEmbedModal({
const [title, setTitle] = useState('')
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
const [busy, setBusy] = useState(false)
+ const [rightsDialogOpen, setRightsDialogOpen] = useState(false)
useEffect(() => {
if (!open) return
@@ -38,12 +40,18 @@ export default function ExerciseInlineEmbedModal({
setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
}, [open])
- const submit = async () => {
+ const submit = () => {
const u = url.trim()
if (!u) {
alert('Bitte eine Embed-URL eingeben (https://…).')
return
}
+ setRightsDialogOpen(true)
+ }
+
+ const doSubmitWithDecl = async (decl) => {
+ setRightsDialogOpen(false)
+ const u = url.trim()
const size = sanitizeInlineMediaSize(displaySize)
const fd = new FormData()
fd.append('embed_url', u)
@@ -52,6 +60,9 @@ export default function ExerciseInlineEmbedModal({
fd.append('description', '')
fd.append('context', 'ablauf')
fd.append('is_primary', 'false')
+ for (const [k, v] of Object.entries(decl)) {
+ fd.append(k, String(v))
+ }
setBusy(true)
try {
const row = await api.uploadExerciseMedia(exerciseId, fd)
@@ -75,7 +86,15 @@ export default function ExerciseInlineEmbedModal({
if (!open) return null
return (
-
e.target === e.currentTarget && !busy && onClose()}>
+ <>
+
setRightsDialogOpen(false)}
+ onConfirm={doSubmitWithDecl}
+ targetVisibility="private"
+ mode="upload"
+ />
+ e.target === e.currentTarget && !busy && !rightsDialogOpen && onClose()}>
+ >
)
}
diff --git a/frontend/src/components/ExerciseInlineFileMediaModal.jsx b/frontend/src/components/ExerciseInlineFileMediaModal.jsx
index 8569cd8..8c84633 100644
--- a/frontend/src/components/ExerciseInlineFileMediaModal.jsx
+++ b/frontend/src/components/ExerciseInlineFileMediaModal.jsx
@@ -10,6 +10,7 @@ import {
sanitizeInlineMediaSize,
} from '../constants/inlineExerciseMedia'
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'
+import RightsDeclarationDialog from './RightsDeclarationDialog'
function RtePickerAssetThumb({ asset }) {
const id = asset.id
@@ -89,6 +90,7 @@ export default function ExerciseInlineFileMediaModal({
const [uploadTitle, setUploadTitle] = useState('')
const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
const [uploadInputKey, setUploadInputKey] = useState(0)
+ const [rightsDialogOpen, setRightsDialogOpen] = useState(false)
const assetToExerciseMedia = useMemo(() => {
const m = new Map()
@@ -182,11 +184,16 @@ export default function ExerciseInlineFileMediaModal({
}
}
- const handleUploadAndInsert = async () => {
+ const handleUploadAndInsert = () => {
if (!uploadFile) {
alert('Bitte eine Datei wählen.')
return
}
+ setRightsDialogOpen(true)
+ }
+
+ const doUploadWithDecl = async (decl) => {
+ setRightsDialogOpen(false)
const size = sanitizeInlineMediaSize(displaySize)
const inferred = inferExerciseMediaType(uploadFile)
const fd = new FormData()
@@ -196,6 +203,9 @@ export default function ExerciseInlineFileMediaModal({
fd.append('description', '')
fd.append('context', 'ablauf')
fd.append('is_primary', 'false')
+ for (const [k, v] of Object.entries(decl)) {
+ fd.append(k, String(v))
+ }
setBusy(true)
setErr(null)
try {
@@ -232,7 +242,15 @@ export default function ExerciseInlineFileMediaModal({
if (!open) return null
return (
- e.target === e.currentTarget && !busy && onClose()}>
+ <>
+
setRightsDialogOpen(false)}
+ onConfirm={doUploadWithDecl}
+ targetVisibility="private"
+ mode="upload"
+ />
+ e.target === e.currentTarget && !busy && !rightsDialogOpen && onClose()}>
+ >
)
}
diff --git a/frontend/src/version.js b/frontend/src/version.js
index 47d4e30..9575302 100644
--- a/frontend/src/version.js
+++ b/frontend/src/version.js
@@ -1,6 +1,6 @@
// Shinkan Jinkendo Frontend Version
-export const APP_VERSION = "0.8.75"
+export const APP_VERSION = "0.8.76"
export const BUILD_DATE = "2026-05-11"
export const PAGE_VERSIONS = {
@@ -21,4 +21,6 @@ export const PAGE_VERSIONS = {
AdminCatalogsPage: "2.2.0",
TrainerContextsPage: "1.0.0",
MediaLibraryPage: "1.2.0", // P-06: RightsDeclarationDialog + Altbestand-Indikator
+ ExerciseInlineFileMediaModal: "1.1.0", // P-06: RightsDeclarationDialog vor Upload
+ ExerciseInlineEmbedModal: "1.1.0", // P-06: RightsDeclarationDialog vor Embed-Upload
}