This commit is contained in:
Team3
2026-06-06 16:07:04 +02:00
parent 18bb18bf4a
commit 4aa3130807
19 changed files with 861 additions and 206 deletions

View File

@@ -16,7 +16,7 @@ const props = defineProps({
providers: { type: Array, default: () => [] },
})
const emit = defineEmits(['select', 'create', 'formatClick', 'bausteineClick', 'deleteTopic', 'deleteProject', 'cancelGuide', 'deleteGuide', 'preview', 'togglePin', 'sidebarLeave', 'toggleDark', 'setProvider'])
const emit = defineEmits(['select', 'create', 'formatClick', 'bausteineClick', 'cancelBausteine', 'resetBausteine', 'deleteTopic', 'deleteProject', 'cancelGuide', 'deleteGuide', 'preview', 'togglePin', 'sidebarLeave', 'toggleDark', 'setProvider'])
function providerAvailable(id) {
const p = props.providers.find((x) => x.id === id)
@@ -34,6 +34,10 @@ const formats = [
const BAUSTEINE_KEY = '__bausteine__'
const bausteineUnsortiert = computed(
() => props.bausteine.ready && props.bausteine.steps?.at(-1)?.state === 'pending',
)
const bausteineState = computed(() => {
if (props.bausteine.generating) return 'generating'
return props.bausteine.ready ? 'done' : 'none'
@@ -49,6 +53,16 @@ const activeGenerations = computed(() => {
return [...bausteinLines, ...guideLines]
})
function confirmCancelBausteine() {
if (!confirm('Aktuellen Schritt abbrechen? Bisheriger Fortschritt bleibt erhalten.')) return
emit('cancelBausteine')
}
function confirmResetBausteine() {
if (!confirm('Gespeicherten Bausteine-Fortschritt löschen?')) return
emit('resetBausteine')
}
function handleBausteinePlay() {
if (bausteineState.value === 'generating') return
const text = activeInput.value === BAUSTEINE_KEY ? inputText.value.trim() : ''
@@ -171,15 +185,36 @@ function confirmDeleteProject(name) {
<div class="progress-info" v-if="activeGenerations.length">
<div v-for="(line, i) in activeGenerations" :key="i">{{ line }}</div>
</div>
<div :class="['format-row', 'bausteine-row', 'fmt-' + bausteineState]">
<button class="format-name">
<div class="format-row bausteine-row">
<div class="format-name bausteine-name">
<span class="format-label">Bausteine</span>
</button>
<span class="step-dots">
<span
v-for="s in (bausteine.steps || [])"
:key="s.label"
class="step-dot"
:class="s.state"
:title="s.state === 'active' ? (bausteine.progress || s.label) : s.label"
></span>
</span>
<span
v-if="bausteineState === 'generating'"
class="format-x"
title="Aktuellen Schritt abbrechen (Fortschritt bleibt)"
@click.stop="confirmCancelBausteine"
>&times;</span>
<span
v-else-if="bausteine.partial"
class="format-x"
title="Fortschritt löschen"
@click.stop="confirmResetBausteine"
>&times;</span>
</div>
<div class="format-actions">
<template v-if="bausteineState !== 'generating'">
<button
class="action-btn play"
:title="bausteine.ready ? 'Bausteine neu erstellen' : 'Bausteine erstellen'"
:title="bausteine.partial ? 'Fortsetzen' : bausteineUnsortiert ? 'Sortierung nachholen' : bausteine.ready ? 'Bausteine neu erstellen' : 'Bausteine erstellen'"
@click="handleBausteinePlay"
></button>
<button
@@ -216,8 +251,8 @@ function confirmDeleteProject(name) {
<template v-if="guideStatus(f.key) !== 'generating' && guideStatus(f.key) !== 'queued'">
<button
class="action-btn play"
:title="bausteine.ready ? 'Generieren' : 'Erst Bausteine erstellen'"
:disabled="!bausteine.ready"
:title="f.key === 'OnePager' || bausteine.ready ? 'Generieren' : 'Erst Bausteine erstellen'"
:disabled="f.key !== 'OnePager' && !bausteine.ready"
@click="handlePlay(f.key)"
></button>
<button
@@ -452,6 +487,41 @@ function confirmDeleteProject(name) {
margin-bottom: 0.5rem;
}
.bausteine-name {
display: flex;
align-items: center;
gap: 8px;
cursor: default;
}
.step-dots {
display: inline-flex;
gap: 5px;
flex: 1;
}
.step-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--border-strong);
flex-shrink: 0;
}
.step-dot.done {
background: var(--success-border);
}
.step-dot.active {
background: var(--warning-border);
animation: dot-pulse 1.2s ease-in-out infinite;
}
@keyframes dot-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.35; }
}
.action-btn:disabled {
opacity: 0.35;
cursor: not-allowed;