udpate
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { fetchGuides, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel } from './api.js'
|
||||
import { fetchGuides, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel, reworkGuide as apiRework } from './api.js'
|
||||
import TopicSidebar from './components/TopicSidebar.vue'
|
||||
import TopicDetail from './components/TopicDetail.vue'
|
||||
|
||||
@@ -73,9 +73,15 @@ function createTopic(topic) {
|
||||
previewGuide.value = null
|
||||
}
|
||||
|
||||
async function handleFormatClick(format) {
|
||||
async function handleFormatClick({ format, instructions }) {
|
||||
if (!selectedTopic.value) return
|
||||
await apiCreate(selectedTopic.value, format)
|
||||
await apiCreate(selectedTopic.value, format, instructions)
|
||||
await loadGuides()
|
||||
startPolling()
|
||||
}
|
||||
|
||||
async function handleRework({ guideId, instructions }) {
|
||||
await apiRework(guideId, instructions)
|
||||
await loadGuides()
|
||||
startPolling()
|
||||
}
|
||||
@@ -162,6 +168,7 @@ onUnmounted(() => {
|
||||
@cancelGuide="handleCancel"
|
||||
@deleteGuide="handleDeleteGuide"
|
||||
@preview="handlePreview"
|
||||
@rework="handleRework"
|
||||
/>
|
||||
<TopicDetail
|
||||
v-if="selectedTopic"
|
||||
|
||||
@@ -10,11 +10,20 @@ export async function fetchGuide(id) {
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function createGuide(topic, format) {
|
||||
export async function createGuide(topic, format, instructions = '') {
|
||||
const res = await fetch(`${BASE}/guides`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ topic, format }),
|
||||
body: JSON.stringify({ topic, format, instructions }),
|
||||
})
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function reworkGuide(id, instructions) {
|
||||
const res = await fetch(`${BASE}/guides/${id}/rework`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ instructions }),
|
||||
})
|
||||
return res.json()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ const props = defineProps({
|
||||
allGuides: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['select', 'create', 'formatClick', 'deleteTopic', 'cancelGuide', 'deleteGuide', 'preview'])
|
||||
const emit = defineEmits(['select', 'create', 'formatClick', 'deleteTopic', 'cancelGuide', 'deleteGuide', 'preview', 'rework'])
|
||||
|
||||
const formats = [
|
||||
{ key: 'OnePager', label: 'OnePager' },
|
||||
@@ -38,12 +38,33 @@ function handleFormatClick(format) {
|
||||
}
|
||||
}
|
||||
|
||||
function handlePlay(format) {
|
||||
const guide = props.guidesByFormat[format]
|
||||
if (guide?.status === 'done') {
|
||||
if (!confirm('Guide überschreiben?')) return
|
||||
const activeInput = ref(null)
|
||||
const inputText = ref('')
|
||||
|
||||
function toggleInput(format) {
|
||||
if (activeInput.value === format) {
|
||||
activeInput.value = null
|
||||
inputText.value = ''
|
||||
} else {
|
||||
activeInput.value = format
|
||||
inputText.value = ''
|
||||
}
|
||||
emit('formatClick', format)
|
||||
}
|
||||
|
||||
function handlePlay(format) {
|
||||
const text = activeInput.value === format ? inputText.value.trim() : ''
|
||||
emit('formatClick', { format, instructions: text })
|
||||
activeInput.value = null
|
||||
inputText.value = ''
|
||||
}
|
||||
|
||||
function handleRefresh(format) {
|
||||
const guide = props.guidesByFormat[format]
|
||||
if (!guide) return
|
||||
const text = activeInput.value === format ? inputText.value.trim() : ''
|
||||
emit('rework', { guideId: guide.id, instructions: text || 'Überarbeite das Layout' })
|
||||
activeInput.value = null
|
||||
inputText.value = ''
|
||||
}
|
||||
|
||||
function handleDelete(format) {
|
||||
@@ -94,31 +115,44 @@ function submit() {
|
||||
<div class="progress-info" v-if="activeGenerations.length">
|
||||
<div v-for="(line, i) in activeGenerations" :key="i">{{ line }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="f in formats"
|
||||
:key="f.key"
|
||||
:class="['format-row', 'fmt-' + guideStatus(f.key)]"
|
||||
>
|
||||
<button class="format-name" @click="handleFormatClick(f.key)">
|
||||
{{ f.label }}
|
||||
</button>
|
||||
<div class="format-actions">
|
||||
<button
|
||||
v-if="guideStatus(f.key) !== 'generating' && guideStatus(f.key) !== 'queued'"
|
||||
class="action-btn play"
|
||||
:title="guideStatus(f.key) === 'done' ? 'Neu generieren' : 'Generieren'"
|
||||
@click="handlePlay(f.key)"
|
||||
>
|
||||
{{ guideStatus(f.key) === 'done' ? '↻' : '▶' }}
|
||||
</button>
|
||||
<button
|
||||
v-if="guideStatus(f.key) !== 'none'"
|
||||
class="action-btn delete"
|
||||
:title="guideStatus(f.key) === 'generating' || guideStatus(f.key) === 'queued' ? 'Abbrechen' : 'Löschen'"
|
||||
@click="handleDelete(f.key)"
|
||||
>
|
||||
×
|
||||
<div v-for="f in formats" :key="f.key">
|
||||
<div :class="['format-row', 'fmt-' + guideStatus(f.key)]">
|
||||
<button class="format-name" @click="handleFormatClick(f.key)">
|
||||
<span class="format-label">{{ f.label }}</span>
|
||||
<span
|
||||
v-if="guideStatus(f.key) !== 'none'"
|
||||
class="format-x"
|
||||
@click.stop="handleDelete(f.key)"
|
||||
:title="guideStatus(f.key) === 'generating' || guideStatus(f.key) === 'queued' ? 'Abbrechen' : 'Löschen'"
|
||||
>×</span>
|
||||
</button>
|
||||
<div class="format-actions">
|
||||
<template v-if="guideStatus(f.key) === 'done'">
|
||||
<button class="action-btn refresh" title="Überarbeiten" @click="handleRefresh(f.key)">↻</button>
|
||||
<button
|
||||
class="action-btn pencil"
|
||||
:class="{ active: activeInput === f.key }"
|
||||
title="Anweisungen"
|
||||
@click="toggleInput(f.key)"
|
||||
>✎</button>
|
||||
</template>
|
||||
<template v-else-if="guideStatus(f.key) !== 'generating' && guideStatus(f.key) !== 'queued'">
|
||||
<button class="action-btn play" title="Generieren" @click="handlePlay(f.key)">▶</button>
|
||||
<button
|
||||
class="action-btn pencil"
|
||||
:class="{ active: activeInput === f.key }"
|
||||
title="Anweisungen"
|
||||
@click="toggleInput(f.key)"
|
||||
>✎</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="activeInput === f.key" class="format-input">
|
||||
<input
|
||||
v-model="inputText"
|
||||
:placeholder="guideStatus(f.key) === 'done' ? 'Was soll überarbeitet werden?' : 'Anweisungen (optional)…'"
|
||||
@keyup.enter="guideStatus(f.key) === 'done' ? handleRefresh(f.key) : handlePlay(f.key)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -252,6 +286,22 @@ function submit() {
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
color: #999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.format-x {
|
||||
display: none;
|
||||
color: #991b1b;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.format-name:hover .format-x {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.fmt-done .format-name {
|
||||
@@ -309,14 +359,40 @@ function submit() {
|
||||
border-color: #34d399;
|
||||
}
|
||||
|
||||
.action-btn.delete {
|
||||
color: #991b1b;
|
||||
font-size: 1.1rem;
|
||||
.action-btn.refresh {
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.action-btn.delete:hover {
|
||||
background: #fee2e2;
|
||||
border-color: #f87171;
|
||||
.action-btn.refresh:hover {
|
||||
background: #d1fae5;
|
||||
border-color: #34d399;
|
||||
}
|
||||
|
||||
.action-btn.pencil {
|
||||
color: #6366f1;
|
||||
}
|
||||
|
||||
.action-btn.pencil:hover,
|
||||
.action-btn.pencil.active {
|
||||
background: #ede9fe;
|
||||
border-color: #a5b4fc;
|
||||
}
|
||||
|
||||
.format-input {
|
||||
padding: 4px 0.75rem 8px;
|
||||
}
|
||||
|
||||
.format-input input {
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #d8dde3;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.format-input input:focus {
|
||||
border-color: #6366f1;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
Reference in New Issue
Block a user