diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 97bfa34c..607b6e0d 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -185,6 +185,14 @@ Multi-statement queries execute sequentially via `POST /api/db/multi-query`. - **React hooks** for UI state: tabs, active connection, execution status - **Custom hooks** extracted from Studio.tsx: `useAuth`, `useConnectionManager`, `useTabManager`, `useTransactionControl`, `useQueryExecution`, `useInlineEditing` +Double-clicking an Explorer table uses `useTabManager.handleTableClick`, the same action as +Select Top 50: it opens a new query tab and executes the provider's preview query. A session-only +`QueryTab.previewQuery` records that generated query. BottomPanel's **Refresh rows** reruns it +on the same tab through the standalone or embedded execution hook; it is hidden after query +edits and for stored agent results, and disabled during execution, pagination or pending cell +edits. **Refresh schema** separately invokes the current connection's schema fetch, including +from empty/error states, without executing a query or replacing editor tabs. + ### 4.6. Workspace Abstraction (npm package embedding) Studio ships both as a standalone app and as the `@libredb/studio` npm package consumed by libredb-platform (built with `tsup` via `build:lib`). diff --git a/src/components/Studio.tsx b/src/components/Studio.tsx index 30258b22..b2407f5d 100644 --- a/src/components/Studio.tsx +++ b/src/components/Studio.tsx @@ -397,6 +397,10 @@ export default function Studio() { tabMgr.handleTableClick(tableName, queryExec.executeQuery); }; + const onRefreshSchema = () => { + if (conn.activeConnection) conn.fetchSchema(conn.activeConnection); + }; + const requestDeleteConnection = (id: string) => { setPendingDeleteConnectionId(id); }; @@ -494,6 +498,7 @@ export default function Studio() { }} onAddConnection={() => setIsConnectionModalOpen(true)} onTableClick={onTableClick} + onRefreshSchema={onRefreshSchema} onGenerateSelect={tabMgr.handleGenerateSelect} onCreateTableClick={() => setIsCreateTableModalOpen(true)} onShowDiagram={() => setShowDiagram(true)} @@ -623,6 +628,7 @@ export default function Studio() { onTableClick(tableName); setActiveMobileTab("editor"); }} + onRefreshSchema={onRefreshSchema} onGenerateSelect={(tableName) => { tabMgr.handleGenerateSelect(tableName); setActiveMobileTab("editor"); @@ -687,6 +693,7 @@ export default function Studio() { void; + onRefreshSchema?: () => void; onGenerateSelect?: (tableName: string) => void; onCreateTableClick?: () => void; isAdmin?: boolean; @@ -35,6 +35,7 @@ export function SchemaExplorer({ isLoadingSchema, schemaError = null, onTableClick, + onRefreshSchema, onGenerateSelect, onCreateTableClick, isAdmin = false, @@ -48,6 +49,18 @@ export function SchemaExplorer({ const capabilities = metadata?.capabilities; const [searchQuery, setSearchQuery] = useState(""); const [expandedTables, setExpandedTables] = useState>(new Set()); + const refreshButton = onRefreshSchema && ( + + ); const toggleTable = useCallback((tableName: string) => { setExpandedTables((prev) => { @@ -80,6 +93,7 @@ export function SchemaExplorer({ Scanning Schema... + {refreshButton} ); } @@ -99,6 +113,7 @@ export function SchemaExplorer({

Schema could not be read

{schemaError}

+ {refreshButton} ); } @@ -113,6 +128,7 @@ export function SchemaExplorer({

We couldn't find any tables or views in this connection.

+ {refreshButton} {capabilities?.supportsCreateTable !== false && ( + )}