update
This commit is contained in:
@@ -89,3 +89,46 @@
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
/* Stufen-Segmente (Vollansicht): dezenter Rand + A/F/E-Badge. Global, weil TopicDetail
|
||||
das Markup per v-html injiziert (scoped-Styles greifen dort nicht). */
|
||||
.sub-stufe {
|
||||
position: relative;
|
||||
border-left: 3px solid color-mix(in srgb, var(--stufe-farbe) 55%, transparent);
|
||||
padding-left: 0.75rem;
|
||||
margin: 0.5rem 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.sub-stufe-badge {
|
||||
position: absolute;
|
||||
top: 0.1rem;
|
||||
right: 0;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 700;
|
||||
color: var(--stufe-farbe);
|
||||
border: 1px solid color-mix(in srgb, var(--stufe-farbe) 60%, transparent);
|
||||
border-radius: 4px;
|
||||
padding: 0 4px;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
/* Neu freigeschaltete Subbausteine (Auto-Stufe): kräftigerer Rand + Stufen-Badge */
|
||||
.sub-neu {
|
||||
position: relative;
|
||||
border-left: 3px solid var(--neu-farbe);
|
||||
padding-left: 0.75rem;
|
||||
margin: 0.5rem 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.sub-neu-badge {
|
||||
position: absolute;
|
||||
top: 0.1rem;
|
||||
right: 0;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 700;
|
||||
color: var(--neu-farbe);
|
||||
border: 1px solid var(--neu-farbe);
|
||||
border-radius: 4px;
|
||||
padding: 0 4px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import BlockPanel from './BlockPanel.vue'
|
||||
import { renderMarkdown, renderBlocks } from '../markdown.js'
|
||||
import { stufeFuer } from '../levels.js'
|
||||
import { stufeFuer, SUB_RANK, VIEW_KURZ, VIEW_FARBE } from '../levels.js'
|
||||
import { pruefeBlock, uebernehmeBlock, resetBlockProgress } from '../api.js'
|
||||
import { clearPruef } from '../pruefungCache.js'
|
||||
import { useConfirm } from '../composables/useConfirm.js'
|
||||
@@ -98,7 +98,25 @@ const level = computed(() => {
|
||||
const displayedText = computed(() =>
|
||||
props.ansicht === 'compact' ? (props.block.compact || props.block.md) : props.block.md,
|
||||
)
|
||||
const blocks = computed(() => renderBlocks(displayedText.value))
|
||||
// Stufen-Segmente: mit subs wird je Sub separat gerendert (Rand+Badge in Stufen-Farbe),
|
||||
// ohne subs (Legacy) bleibt der flache Pfad. Globaler Block-Index läuft über alle
|
||||
// Segmente durch — Check/Vorschläge arbeiten unverändert über Index + raw.
|
||||
const segments = computed(() => {
|
||||
const compact = props.ansicht === 'compact'
|
||||
const subs = props.block.subs
|
||||
let i = 0
|
||||
const seg = (level, text) => ({ level, blocks: renderBlocks(text).map((b) => ({ ...b, i: i++ })) })
|
||||
if (!subs || !subs.length) return [seg('', displayedText.value)]
|
||||
const out = []
|
||||
const anchor = compact ? (props.block.anker_compact || '') : (props.block.anchor || '')
|
||||
if (anchor.trim()) out.push(seg('', anchor))
|
||||
for (const sub of subs) {
|
||||
const body = compact ? (sub.compact || sub.md) : (sub.md || sub.compact)
|
||||
if (body && body.trim()) out.push(seg(sub.level, body))
|
||||
}
|
||||
return out
|
||||
})
|
||||
const blocks = computed(() => segments.value.flatMap((s) => s.blocks))
|
||||
// Field that edits are applied to (must match the displayed text).
|
||||
const spot = computed(() => (props.ansicht === 'compact' && props.block.compact) ? 'compact' : 'ausführlich')
|
||||
|
||||
@@ -176,21 +194,28 @@ watch(() => `${props.block.title}|${props.block.md}|${props.block.compact || ''}
|
||||
<div class="fokus-body">
|
||||
<div ref="guideEl" class="fokus-col left">
|
||||
<div class="markdown">
|
||||
<template v-for="(b, i) in blocks" :key="i">
|
||||
<div class="md-block" v-html="b.html" @contextmenu.prevent="blockMenu(i, $event)"></div>
|
||||
<div v-if="suggestions[i]" class="block-vorschlag">
|
||||
<div v-if="suggestions[i].running" class="bv-status">Check Section…</div>
|
||||
<template v-else>
|
||||
<p v-if="suggestions[i].error" class="bv-fehler">{{ suggestions[i].error }}</p>
|
||||
<div class="markdown bv-new" v-html="renderMarkdown(suggestions[i].revised)"></div>
|
||||
<div class="bv-aktionen">
|
||||
<button class="bv-btn ja" title="Apply" @click="applyBlock(i)">✓</button>
|
||||
<button class="bv-btn" title="Discard" @click="discardBlock(i)">✗</button>
|
||||
<button class="bv-btn" :class="{ aktiv: suggestions[i].editOpen }" title="Add hint" @click="editBlock(i)">✏️</button>
|
||||
</div>
|
||||
<div v-if="suggestions[i].editOpen" class="bv-edit">
|
||||
<input v-model="suggestions[i].hint" class="bv-input" placeholder="Extra info → check again" @keyup.enter="sendBlockEdit(i)" />
|
||||
<button class="bv-btn ja" title="Check again" @click="sendBlockEdit(i)">↻</button>
|
||||
<template v-for="(seg, si) in segments" :key="si">
|
||||
<div :class="{ 'sub-stufe': !!seg.level }"
|
||||
:style="seg.level ? { '--stufe-farbe': VIEW_FARBE[SUB_RANK[seg.level] || 1] } : null">
|
||||
<span v-if="seg.level" class="sub-stufe-badge"
|
||||
:title="`Stufe ${VIEW_KURZ[SUB_RANK[seg.level] || 1]}`">{{ VIEW_KURZ[SUB_RANK[seg.level] || 1] }}</span>
|
||||
<template v-for="b in seg.blocks" :key="b.i">
|
||||
<div class="md-block" v-html="b.html" @contextmenu.prevent="blockMenu(b.i, $event)"></div>
|
||||
<div v-if="suggestions[b.i]" class="block-vorschlag">
|
||||
<div v-if="suggestions[b.i].running" class="bv-status">Check Section…</div>
|
||||
<template v-else>
|
||||
<p v-if="suggestions[b.i].error" class="bv-fehler">{{ suggestions[b.i].error }}</p>
|
||||
<div class="markdown bv-new" v-html="renderMarkdown(suggestions[b.i].revised)"></div>
|
||||
<div class="bv-aktionen">
|
||||
<button class="bv-btn ja" title="Apply" @click="applyBlock(b.i)">✓</button>
|
||||
<button class="bv-btn" title="Discard" @click="discardBlock(b.i)">✗</button>
|
||||
<button class="bv-btn" :class="{ aktiv: suggestions[b.i].editOpen }" title="Add hint" @click="editBlock(b.i)">✏️</button>
|
||||
</div>
|
||||
<div v-if="suggestions[b.i].editOpen" class="bv-edit">
|
||||
<input v-model="suggestions[b.i].hint" class="bv-input" placeholder="Extra info → check again" @keyup.enter="sendBlockEdit(b.i)" />
|
||||
<button class="bv-btn ja" title="Check again" @click="sendBlockEdit(b.i)">↻</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -56,6 +56,9 @@ function htmlFor(s) {
|
||||
const body = renderMarkdown(compact ? (sub.compact || sub.md) : (sub.md || sub.compact))
|
||||
if (props.stufeAnsicht === 'auto' && lvl > 1 && rank === lvl) {
|
||||
parts.push(`<div class="sub-neu" style="--neu-farbe:${VIEW_FARBE[rank]}"><span class="sub-neu-badge" title="Neu ab Stufe ${VIEW_KURZ[rank]}">${VIEW_KURZ[rank]}</span>${body}</div>`)
|
||||
} else if (Number(props.stufeAnsicht) === 4) {
|
||||
// Vollansicht: jede Stufe dezent kennzeichnen (Rand + Badge in Stufen-Farbe)
|
||||
parts.push(`<div class="sub-stufe" style="--stufe-farbe:${VIEW_FARBE[rank]}"><span class="sub-stufe-badge" title="Stufe ${VIEW_KURZ[rank]}">${VIEW_KURZ[rank]}</span>${body}</div>`)
|
||||
} else {
|
||||
parts.push(body)
|
||||
}
|
||||
@@ -765,24 +768,5 @@ function extractContext() {
|
||||
background: var(--danger);
|
||||
}
|
||||
|
||||
/* Neu freigeschaltete Subbausteine (Auto-Stufe): dezenter Rand + Stufen-Badge */
|
||||
.sub-neu {
|
||||
position: relative;
|
||||
border-left: 3px solid var(--neu-farbe);
|
||||
padding-left: 0.75rem;
|
||||
margin: 0.5rem 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.sub-neu-badge {
|
||||
position: absolute;
|
||||
top: 0.1rem;
|
||||
right: 0;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 700;
|
||||
color: var(--neu-farbe);
|
||||
border: 1px solid var(--neu-farbe);
|
||||
border-radius: 4px;
|
||||
padding: 0 4px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
/* .sub-neu/.sub-stufe: global in assets/markdown.css — scoped greift nicht auf v-html-Inhalt. */
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user