update
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
import { fetchGuides, fetchTopics, createTopic as apiCreateTopic, deleteTopic as apiDeleteTopic, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel, fetchBausteineStatus, fetchActiveBausteine, createBausteine as apiCreateBausteine, cancelBausteine as apiCancelBausteine, deleteBausteine as apiDeleteBausteine, fetchProjects, deleteProject as apiDeleteProject, fetchProviders, fetchStats, fetchTopicFortschritt, fetchGuideLocks } from './api.js'
|
||||
import { fetchGuides, fetchTopics, createTopic as apiCreateTopic, deleteTopic as apiDeleteTopic, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel, fetchBausteineStatus, fetchActiveBausteine, createBausteine as apiCreateBausteine, cancelBausteine as apiCancelBausteine, deleteBausteine as apiDeleteBausteine, fetchProviders, fetchStats, fetchTopicFortschritt, fetchGuideLocks, fetchFolders, updateQuelle as apiUpdateQuelle } from './api.js'
|
||||
import { usePolling } from './composables/usePolling.js'
|
||||
import TopicSidebar from './components/TopicSidebar.vue'
|
||||
import TopicDetail from './components/TopicDetail.vue'
|
||||
import BausteineUebersicht from './components/BausteineUebersicht.vue'
|
||||
import ElementsSidebar from './components/elements/ElementsSidebar.vue'
|
||||
import ElementsOverview from './components/ElementsOverview.vue'
|
||||
|
||||
const guides = ref([])
|
||||
const projects = ref([])
|
||||
const backendTopics = ref([])
|
||||
const selectedTopic = ref(null)
|
||||
const previewGuide = ref(null)
|
||||
@@ -24,6 +24,8 @@ const bausteine = ref({ ...EMPTY_BAUSTEINE })
|
||||
const activeBausteine = ref([])
|
||||
const provider = ref(localStorage.getItem('provider') || 'claude')
|
||||
const providers = ref([])
|
||||
const folders = ref({ projekt: [], uni: [] }) // Ordner für die Quellen-Auswahl
|
||||
const bausteineView = ref(false) // Bausteine-Übersicht im Hauptbereich
|
||||
const stats = ref(null)
|
||||
const fortschritt = ref({})
|
||||
const locks = ref({}) // Sperr-Gründe pro Format (Backend = einzige Regel-Quelle)
|
||||
@@ -47,6 +49,15 @@ function setProvider(id) {
|
||||
localStorage.setItem('provider', id)
|
||||
}
|
||||
|
||||
async function loadFolders() {
|
||||
try {
|
||||
const [projekt, uni] = await Promise.all([fetchFolders('projekt'), fetchFolders('uni')])
|
||||
folders.value = { projekt, uni }
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Laden der Ordner:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function loadProviders() {
|
||||
try {
|
||||
providers.value = await fetchProviders()
|
||||
@@ -86,12 +97,7 @@ function onSidebarLeave() {
|
||||
if (!sidebarPinned.value) sidebarSticky.value = false
|
||||
}
|
||||
|
||||
const projectNames = computed(() => projects.value.map((p) => p.name))
|
||||
|
||||
const topics = computed(() => {
|
||||
const isProject = new Set(projectNames.value)
|
||||
return backendTopics.value.filter((t) => !isProject.has(t))
|
||||
})
|
||||
const topics = computed(() => backendTopics.value)
|
||||
|
||||
const doneByFormat = computed(() => {
|
||||
const map = {}
|
||||
@@ -174,15 +180,7 @@ async function loadBausteine() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadProjects() {
|
||||
try {
|
||||
projects.value = await fetchProjects()
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Laden der Projekte:', e)
|
||||
}
|
||||
}
|
||||
|
||||
const FORMAT_ORDER = ['OnePager', 'MiniGuide', 'Guide', 'FullGuide']
|
||||
const FORMAT_ORDER = ['OnePager', 'MiniGuide', 'Guide', 'ProGuide', 'FullGuide']
|
||||
|
||||
function autoPreview() {
|
||||
const map = doneByFormat.value
|
||||
@@ -201,6 +199,7 @@ function selectTopic(topic) {
|
||||
sidebarSticky.value = false
|
||||
elementsOpen.value = false
|
||||
elementsView.value = false
|
||||
bausteineView.value = false
|
||||
elementOpenId.value = null
|
||||
localStorage.setItem('lastTopic', topic)
|
||||
loadBausteine()
|
||||
@@ -258,6 +257,24 @@ async function handleCreateThema({ topic, instructions, sourceType, sourceOrt })
|
||||
startPolling()
|
||||
}
|
||||
|
||||
async function handleUpdateQuelle({ topic, type, ort, spec }) {
|
||||
uiError.value = null
|
||||
try {
|
||||
await apiUpdateQuelle(topic, { type, ort, spec })
|
||||
} catch (e) {
|
||||
uiError.value = e.message
|
||||
return
|
||||
}
|
||||
await loadBausteine() // Schritt-Anzeige folgt ggf. der neuen Quelle (z.B. Link → „Quelle laden")
|
||||
}
|
||||
|
||||
function handleOpenBausteineView() {
|
||||
if (!selectedTopic.value) return
|
||||
bausteineView.value = true
|
||||
elementsView.value = false
|
||||
previewGuide.value = null
|
||||
}
|
||||
|
||||
async function handleFormatClick({ format, instructions }) {
|
||||
if (!selectedTopic.value) return
|
||||
// Kein Duplikat-Start: läuft für Thema+Format schon eine Generierung, ignorieren
|
||||
@@ -277,23 +294,16 @@ async function handleFormatClick({ format, instructions }) {
|
||||
startPolling()
|
||||
}
|
||||
|
||||
async function handleDeleteProject(name) {
|
||||
await apiDeleteProject(name)
|
||||
if (selectedTopic.value === name) {
|
||||
selectedTopic.value = null
|
||||
previewGuide.value = null
|
||||
}
|
||||
await loadProjects()
|
||||
}
|
||||
|
||||
function handlePreview(guide) {
|
||||
previewGuide.value = guide
|
||||
elementsView.value = false
|
||||
bausteineView.value = false
|
||||
}
|
||||
|
||||
function handleOpenElements() {
|
||||
if (!selectedTopic.value) return
|
||||
elementsView.value = true
|
||||
bausteineView.value = false
|
||||
// Rechte Sidebar bleibt zu — sie öffnet erst beim Klick auf ein Element.
|
||||
}
|
||||
|
||||
@@ -338,10 +348,10 @@ async function handleDeleteTopic(topic) {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadGuides(), loadTopics(), loadProjects(), loadProviders()])
|
||||
await Promise.all([loadGuides(), loadTopics(), loadProviders(), loadFolders()])
|
||||
const savedTopic = localStorage.getItem('lastTopic')
|
||||
const savedFormat = localStorage.getItem('lastFormat')
|
||||
if (savedTopic && [...topics.value, ...projectNames.value].includes(savedTopic)) {
|
||||
if (savedTopic && topics.value.includes(savedTopic)) {
|
||||
selectTopic(savedTopic)
|
||||
await nextTick()
|
||||
const g = doneByFormat.value[savedFormat]
|
||||
@@ -358,7 +368,6 @@ onMounted(async () => {
|
||||
<div v-if="!sidebarPinned && sidebarSticky" class="sidebar-backdrop" @click="sidebarSticky = false"></div>
|
||||
<TopicSidebar
|
||||
:topics="topics"
|
||||
:projects="projectNames"
|
||||
:selectedTopic="selectedTopic"
|
||||
:stats="stats"
|
||||
:fortschritt="fortschritt"
|
||||
@@ -374,17 +383,19 @@ onMounted(async () => {
|
||||
:dark="darkMode"
|
||||
:provider="provider"
|
||||
:providers="providers"
|
||||
:folders="folders"
|
||||
@setProvider="setProvider"
|
||||
@toggleDark="toggleDark"
|
||||
@select="selectTopic"
|
||||
@create="createTopic"
|
||||
@createThema="handleCreateThema"
|
||||
@updateQuelle="handleUpdateQuelle"
|
||||
@openBausteineView="handleOpenBausteineView"
|
||||
@formatClick="handleFormatClick"
|
||||
@bausteineClick="handleBausteineClick"
|
||||
@cancelBausteine="handleCancelBausteine"
|
||||
@resetBausteine="handleResetBausteine"
|
||||
@deleteTopic="handleDeleteTopic"
|
||||
@deleteProject="handleDeleteProject"
|
||||
@cancelGuide="handleCancel"
|
||||
@deleteGuide="handleDeleteGuide"
|
||||
@dismissError="handleDismissError"
|
||||
@@ -394,8 +405,13 @@ onMounted(async () => {
|
||||
@togglePin="toggleSidebarPin"
|
||||
@sidebarLeave="onSidebarLeave"
|
||||
/>
|
||||
<BausteineUebersicht
|
||||
v-if="selectedTopic && bausteineView"
|
||||
:topic="selectedTopic"
|
||||
@close="bausteineView = false"
|
||||
/>
|
||||
<ElementsOverview
|
||||
v-if="selectedTopic && elementsView"
|
||||
v-else-if="selectedTopic && elementsView"
|
||||
:topic="selectedTopic"
|
||||
:version="elementsVersion"
|
||||
@open="handleOpenElementDetail"
|
||||
|
||||
Reference in New Issue
Block a user