From 4dd88cb5d49919f81d37492c2e3053db74de5cd6 Mon Sep 17 00:00:00 2001
From: Michael Chihlas
Date: Fri, 20 Feb 2026 21:24:47 -0500
Subject: [PATCH] =?UTF-8?q?feat:=20Phase=203=20=E2=80=94=20Library=20page?=
=?UTF-8?q?=20create=20dropdown=20+=20AI=20Builder=20+=20pin=20wiring?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Replace single Create link with dropdown menu (3 flow types + AI Builder)
- Wire pinnedFlowsStore to all view components
- AI Builder modal integration via useCachedQuota hook
Co-Authored-By: Claude Opus 4.6
---
frontend/src/pages/TreeLibraryPage.tsx | 116 ++++++++++++++++++++++---
1 file changed, 106 insertions(+), 10 deletions(-)
diff --git a/frontend/src/pages/TreeLibraryPage.tsx b/frontend/src/pages/TreeLibraryPage.tsx
index 63d8e7d3..603ca4b5 100644
--- a/frontend/src/pages/TreeLibraryPage.tsx
+++ b/frontend/src/pages/TreeLibraryPage.tsx
@@ -1,6 +1,6 @@
import { useEffect, useState, useCallback } from 'react'
import { useNavigate, Link, useSearchParams } from 'react-router-dom'
-import { Plus, X, RotateCcw, Play } from 'lucide-react'
+import { Plus, X, RotateCcw, Play, ChevronDown, Sparkles, FolderTree, ListOrdered, Wrench } from 'lucide-react'
import { treesApi } from '@/api/trees'
import { categoriesApi } from '@/api/categories'
import { foldersApi } from '@/api/folders'
@@ -17,6 +17,9 @@ import { cn, safeGetItem } from '@/lib/utils'
import { getSessionResumePath } from '@/lib/routing'
import { usePermissions } from '@/hooks/usePermissions'
import { useUserPreferencesStore } from '@/store/userPreferencesStore'
+import { usePinnedFlowsStore, selectPinnedTreeIds, selectPinLoadingTreeIds } from '@/store/pinnedFlowsStore'
+import { useCachedQuota } from '@/hooks/useCachedQuota'
+import { AIFlowBuilderModal } from '@/components/ai-builder/AIFlowBuilderModal'
import { toast } from '@/lib/toast'
export function TreeLibraryPage() {
@@ -69,6 +72,17 @@ export function TreeLibraryPage() {
// Fork state
const [isForkingTree, setIsForkingTree] = useState(false)
+ // Create menu & AI builder state
+ const [showCreateMenu, setShowCreateMenu] = useState(false)
+ const [showAIBuilder, setShowAIBuilder] = useState(false)
+ const { aiEnabled } = useCachedQuota()
+
+ // Pin store
+ const pinnedTreeIds = usePinnedFlowsStore(selectPinnedTreeIds)
+ const pinLoadingTreeIds = usePinnedFlowsStore(selectPinLoadingTreeIds)
+ const togglePin = usePinnedFlowsStore((s) => s.toggle)
+ const loadPinned = usePinnedFlowsStore((s) => s.load)
+
// Repeat Last Session
const lastSessionData = (() => {
const raw = safeGetItem('last-session')
@@ -102,6 +116,9 @@ export function TreeLibraryPage() {
.catch((err) => console.error('Failed to load incomplete sessions:', err))
}, [])
+ // Load pinned flows
+ useEffect(() => { loadPinned() }, [loadPinned])
+
const dismissSession = (sessionId: string) => {
const next = new Set(dismissedSessionIds)
next.add(sessionId)
@@ -263,16 +280,78 @@ export function TreeLibraryPage() {
{canCreateTrees && (
-
+
+ {showCreateMenu && (
+ <>
+ setShowCreateMenu(false)} />
+
+
setShowCreateMenu(false)}
+ className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
+ >
+
+
+
Troubleshooting Tree
+
Branching decision flow
+
+
+
setShowCreateMenu(false)}
+ className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
+ >
+
+
+
Procedural Flow
+
Step-by-step procedure
+
+
+
setShowCreateMenu(false)}
+ className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
+ >
+
+
+
Maintenance Flow
+
Scheduled multi-target tasks
+
+
+ {aiEnabled && (
+ <>
+
+
+ >
+ )}
+
+ >
)}
- >
-
- {typeFilter === 'procedural' ? 'New Project' : typeFilter === 'maintenance' ? 'New Maintenance Flow' : 'Create Flow'}
-
+
)}
@@ -474,6 +553,9 @@ export function TreeLibraryPage() {
setShowDeleteConfirm(true)
}}
onForkTree={handleForkTree}
+ pinnedTreeIds={pinnedTreeIds}
+ onTogglePin={togglePin}
+ pinLoadingTreeIds={pinLoadingTreeIds}
/>
)}
{treeLibraryView === 'list' && (
@@ -487,6 +569,9 @@ export function TreeLibraryPage() {
setShowDeleteConfirm(true)
}}
onForkTree={handleForkTree}
+ pinnedTreeIds={pinnedTreeIds}
+ onTogglePin={togglePin}
+ pinLoadingTreeIds={pinLoadingTreeIds}
/>
)}
{treeLibraryView === 'table' && (
@@ -505,6 +590,9 @@ export function TreeLibraryPage() {
)
}}
onForkTree={handleForkTree}
+ pinnedTreeIds={pinnedTreeIds}
+ onTogglePin={togglePin}
+ pinLoadingTreeIds={pinLoadingTreeIds}
/>
)}
>
@@ -538,6 +626,14 @@ export function TreeLibraryPage() {
confirmVariant="destructive"
isLoading={isDeleting}
/>
+
+ {/* AI Builder Modal */}
+ {showAIBuilder && (
+ setShowAIBuilder(false)}
+ />
+ )}
)
}