@@ -642,14 +778,32 @@ const nodeFilter = reactive({
autopOnly: false,
})
+const filtersMenuOpen = ref(false)
+
+const activeFilterCount = computed(() => {
+ let count = 0
+ if (nodeFilter.role !== 'all') count += 1
+ if (nodeFilter.phase !== 'all') count += 1
+ if (nodeFilter.autopOnly) count += 1
+ return count
+})
+
+const activeFilterBadges = computed(() => {
+ const badges: { label: string; color: string }[] = []
+ if (nodeFilter.role !== 'all') {
+ badges.push({ label: `Rolle: ${nodeFilter.role}`, color: 'cyan' })
+ }
+ if (nodeFilter.phase !== 'all') {
+ badges.push({ label: `Phase: ${nodeFilter.phase}`, color: 'purple' })
+ }
+ if (nodeFilter.autopOnly) {
+ badges.push({ label: 'Auto-Trigger', color: 'amber' })
+ }
+ return badges
+})
+
const selectedNodeId = ref(null)
const inspectorTab = ref<'general' | 'transitions' | 'llm' | 'metadata'>('general')
-const inspectorSections = [
- { value: 'general', label: 'Allgemein', icon: 'mdi-tune-variant' },
- { value: 'transitions', label: 'Transitions', icon: 'mdi-source-branch' },
- { value: 'llm', label: 'LLM Template', icon: 'mdi-robot-outline' },
- { value: 'metadata', label: 'Metadata', icon: 'mdi-text-box-search-outline' },
-] as const
const nodeForm = ref(null)
const nodeSnapshot = ref(null)
const nodeSaving = ref(false)
@@ -683,6 +837,39 @@ const phaseFilterOptions = computed(() => {
return Array.from(phases)
})
+const nodeSelectorItems = computed(() => {
+ if (!flowDetail.value) return []
+ const query = nodeFilter.search.trim().toLowerCase()
+ const role = nodeFilter.role
+ const phase = nodeFilter.phase
+ const autopOnly = nodeFilter.autopOnly
+ return flowDetail.value.nodes
+ .slice()
+ .sort((a, b) => a.stateId.localeCompare(b.stateId))
+ .map((node) => {
+ const autopCount = (node.transitions || []).filter((t) => t.autoTrigger).length
+ return {
+ id: node.stateId,
+ title: node.title,
+ summary: node.summary,
+ phase: node.phase,
+ role: node.role,
+ icon: node.layout?.icon,
+ autopCount,
+ matchesSearch:
+ !query ||
+ [node.stateId, node.title, node.summary]
+ .filter(Boolean)
+ .some((entry) => entry!.toLowerCase().includes(query)),
+ matchesRole: role === 'all' || node.role === role,
+ matchesPhase: phase === 'all' || node.phase === phase,
+ matchesAuto: !autopOnly || autopCount > 0,
+ }
+ })
+ .filter((node) => node.matchesSearch && node.matchesRole && node.matchesPhase && node.matchesAuto)
+ .map(({ matchesSearch, matchesRole, matchesPhase, matchesAuto, ...rest }) => rest)
+})
+
const canvasNodes = computed(() => {
if (!flowDetail.value) return []
const flow = flowDetail.value.flow
@@ -951,8 +1138,10 @@ async function runImport() {
}
}
-function toggleAutopOnly() {
- nodeFilter.autopOnly = !nodeFilter.autopOnly
+function resetNodeFilters() {
+ nodeFilter.role = 'all'
+ nodeFilter.phase = 'all'
+ nodeFilter.autopOnly = false
}
function selectNode(stateId: string) {