Skip to content

fix: treeview loading flicker, pagination overflow, refresh animation, saved queries layout, materialized views#115

Merged
Blankll merged 15 commits into
masterfrom
feat/sidebar-redesign-materialized-views
Jun 24, 2026
Merged

fix: treeview loading flicker, pagination overflow, refresh animation, saved queries layout, materialized views#115
Blankll merged 15 commits into
masterfrom
feat/sidebar-redesign-materialized-views

Conversation

@Blankll

@Blankll Blankll commented Jun 23, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the monolithic 981-line DatabaseBrowser.vue with 11 focused, composable sidebar components. Adds PostgreSQL materialized view support. Fixes critical UI flicker (treeview loading overlay, refresh icon animation), pagination overflow, database switching for all adapters, and saved queries layout.

Changes

Frontend — 11 new sidebar components

Component Purpose
ConnectionSelector Connection picker with status indicator
DatabaseSelectorRow Database picker + refresh with smooth spin animation + action menu
SchemaTree Schema-aware database tree (lazy-load, click/dblclick semantics, unified selection)
SavedQueriesPanel Bottom-pinned saved queries with metadata sync
SavedQueryItem Compact two-row layout with icon dates, double-click to open
SidebarSplitView Resizable top/bottom split layout
TreeGroup Collapsible tree section (TABLES/VIEWS/PROCEDURES/FUNCTIONS) with category-specific icons
dbCapabilities.ts Provider-agnostic DB feature detection
DeleteQueryDialog Confirm delete dialog
RenameQueryDialog Inline rename dialog
ChangeConnectionDialog Target connection selector for saved queries

Treeview UX Fixes

  • Loading flash eliminated: overlay is absolutely positioned, only during initial fetch — no tree unmount during expand
  • Scrollbar stability: overflow-y-scroll prevents layout shift when scrollbar appears
  • Click semantics: single-click selects, double-click opens for all item types
  • Unified selection: selectedTreeItem ref with bg-primary/15 highlight
  • Lucide icons: replaced Carbon in treeview; each group has its own distinct icon

Pagination & Data Display

  • Pagination overflow: fixed with min-h-0 on table container, shrink-0 on fixed sections
  • Global thin scrollbars: 5px with transparent track
  • Saved query item: compact two-row layout with icon dates, connection on same row

Backend (Rust)

  • Database switching: with_db_switch! macro for get_table_data/get_table_count across MySQL, ClickHouse, JDBC bridge, Rqlite, Turso
  • Materialized views: list_views UNIONs with pg_matviews, split for PG-compat DBs
  • Atomic metadata: save_query_metadata command for saved query metadata
  • DDL display: handleOpenDdlTab fetches procedure/function DDL via getObjectDdl

Bug Fixes

  • ListingTab.vue: fixed 4 occurrences of props.type instead of obj.object_type
  • DatabaseSelectorRow: refresh icon has minimum 0.5s spin duration — no flicker
  • handleSelectTable: MySQL database names escaped in USE statement
  • dbCapabilities.ts: MySQL/ClickHouse newSchema:false, Oracle matViews:true, Hive newDatabase/dropDatabase:true
  • SavedQueriesPanel: connection change updates modifiedAt

i18n

  • Complete sidebar namespace in enUS.ts and zhCN.ts

Verification

  • vue-tsc --noEmit: 0 errors
  • npm run lint:check: 0 errors, 0 warnings
  • npm test: 416 passed, 0 failed
  • cargo build: Success
  • cargo test --lib: 272 passed, 0 failed

Blankll added 15 commits June 23, 2026 21:52
… view support

- Replace 981-line DatabaseBrowser.vue with 11 focused sidebar components
- Add SchemaTree (schema-database browser with lazy-load + context menus)
- Add SavedQueriesPanel (bottom-pinned with metadata sync, rename/delete/change-connection dialogs)
- Add ConnectionSelector (connection picker + status indicator)
- Add DatabaseSelectorRow (database picker + refresh + action menu stub)
- Add SidebarSplitView (resizable top/bottom layout for tree + saved queries)
- Add Rust backend: read/write saved query metadata JSON, serde camelCase
- Add PostgreSQL materialized view support (list_views UNION pg_matviews + DDL/DROP/RENAME arms)
- Fix ListingTab.vue: use obj.object_type instead of props.type for DDL/drop/rename/copy
- Add i18n keys (enUS + zhCN) for all sidebar strings
- Keep DataTableView.vue and its 5 panel tabs unchanged
- Keep all table context menu actions preserved (selectTopN, viewStructure, etc.)
…ueries height

- DatabaseSelectorRow: remove <SelectItem value=""> that crashed radix-vue
  (empty string is reserved for clearing selection)
- ConnectionSelector: remove host:port display, add search filter input
  inside dropdown for filtering connections by name
- SchemaTree: remove v-if from Views/Procedures/Functions groups so they
  always show even when empty; dedup database names in Mode B tree
- SavedQueriesPanel: restore h-full on outer div so body gets proper
  height when panel is expanded (flex-1 needs parent height)
- Remove unused capabilities computed + imports from SchemaTree
Connections with different IDs but the same name were showing as
duplicates. Dedup by name so only unique connection names appear.
Both ConnectionSelector and DatabaseSelectorRow now use the existing
SearchableSelect component (Popover + inline search pattern) instead of
custom Select + separate Input. This gives them the same search UX as
the database selector in the connection modal — inline search that
replaces the label when the dropdown opens, no separate input box.

- ConnectionSelector: dedup by name, icon via #selected-prepend slot,
  connected badge in #option slot, search always visible (threshold=1)
- DatabaseSelectorRow: dedup database names, database icon in slots,
  left-aligned text, refresh + action menu preserved alongside
- Removed unused Select/SelectContent/SelectItem imports from both
SearchableSelect:
- Add w-full min-w-0 overflow-hidden to trigger button to prevent
  width expansion when search input appears (overlap with siblings)
- Add min-w-0 to search input
- Remove p-1 right padding from listbox so scrollbar sits flush against
  right border
- Add group header support: ComboboxOption.group field renders a
  category label when the group changes

ConnectionSelector:
- Replace CONNECTED text badge with green dot indicator

DatabaseSelectorRow:
- Add 'All Databases' option at top (value='' clears selection)
- System databases grouped at end with 'System Databases' label

SchemaTree:
- Remove auto-selection of database from connection watchers — database
  is ONLY set when user picks from the selector
- Add hasRealSchemas() helper: for MySQL where schema=db name, skip
  the schema node layer and show groups directly under database
- Add Views/Procedures/Functions TreeGroups in Mode B (were missing)
- Add getObjectsForDbSchema() and handleGroupToggleForDb() helpers

QueriesPage:
- Remove auto-selection of database in onMounted
- Remove auto-selection in watch(selectedConnectionId)
- Remove auto-sync from watch(activeTab) to selectedDatabase
SavedQueryItem:
- Intl.RelativeTimeFormat crashed with RangeError: invalid language tag
  enUS — BCP 47 expects en-US (hyphen). Add locale sanitization regex
  that converts enUS→en-US, zhCN→zh-CN before passing to Intl API.
- This was the ROOT CAUSE cascade: SavedQueryItem crash → Vue render
  errors → component tree collapse → 'cannot destructure type from
  null' → all selectors unresponsive, no tree items shown

SearchableSelect:
- Reduce option item padding from px-2 py-1.5 to px-1.5 py-1
- Remove rounded-sm from items so content sits closer to borders
- Apply same padding reduction to create-new option
- Add guard in relativeTime(): return empty string for missing/invalid
  timestamps (undefined, NaN, Infinity) — Intl.RelativeTimeFormat.format
  throws RangeError on NaN even with correct locale
- Change SavedQueryItem hover from bg-accent to bg-accent/30 to reduce
  'shading' effect when hovering/clicking items
- Remove 'rounded-sm' from SearchableSelect option items
- Reduce option item padding from px-1.5 py-1 to px-1 py-0.5 for
  tighter content-to-scrollbar spacing
- Reduce SavedQueryItem padding from py-1.5 to py-1
…items)

ROOT CAUSE: toggleDatabaseNode (SchemaTree.vue:245-251) called
fetchTables WITH schema for ALL databases where schemas.length > 0,
including MySQL where schema name == database name. This stored tables
at key 'blank.blank' (via ). But the template
uses hasRealSchemas() which returns false for MySQL (schema == db name),
so the v-else template reads from key 'blank' (via getTablesForDbSchema
without schema). KEY MISMATCH → tables show as 0.

Also fix relativeTime guard (!timestamp catches 0, use == null instead)
and popover padding (p-0 class may not override p-4 in UnoCSS, use
inline style instead)
ROOT CAUSE OF ONGOING CRASH: regex /([a-z]+)([A-Z][a-z]+)/ requires
uppercase part to END with a lowercase letter. Locale 'enUS' has two
consecutive uppercase letters (U,S), so [a-z]+ doesn't match 'S'.
Regex FAILED silently → returned 'enUS' unchanged → Intl threw
RangeError. Changed to /([a-z]+)([A-Z]+)/ to match any number of
consecutive uppercase letters.

Also fix treeview inheritance: add ml-2 indent to Mode A non-schema
items that were flush with the group header
No regex needed. The locale is always xxYY format (enUS, zhCN).
Simple slice at position 2 and insert hyphen is exact and fragile-free.
Complete rethink per user's direction:

1. SavedQueryItem: replace Intl.RelativeTimeFormat with toLocaleDateString
   — no locale conversion needed, no RangeError possible
   — only show timestamps FROM metadata (not from file system fallback)
   — no locale import, no locale regex

2. SavedQueriesPanel: filter sortedFiles to only include files that HAVE
   metadata entries. Old .sql files without metadata are invisible.

3. QueriesPage: saveMetadataEntry() called after every saveQueryFile/
   saveQueryFileAs. Creates metadata with connection info + timestamps
   so every saved file has a proper metadata record.

This eliminates the root cause chain completely:
   no Intl.RelativeTimeFormat → no locale crash → no cascade failure
   metadata always exists → timestamps always show → items always render
…ctor

handleSelectTable now calls connectionStore.setCurrentDatabase() to give
the backend database context for queries, but does NOT set
selectedDatabase ref — the database selector stays on its current
selection.

Also increased treeview indentation: schema content ml-4 (was ml-3),
items ml-4 (was ml-2) for clearer visual hierarchy matching dbx.
Tree indent: wrap Mode B non-schema TreeGroups in ml-4 div so groups
are indented from the database node. Items inside have ml-4 from the
group. Hierarchy: db 8px → group 24px → item 40px (matching dbx).

Table data loading: Rust get_table_data MySQL branch ignores query.database
(bug in browse.rs _ => branch). Workaround: execute USE `database`
before opening table view tab to set the backend connection context.
DataTableView was using getConnectionId() for its connection-id prop
and key, which depends on the sidebar's selected connection. When the
sidebar selection changes (e.g. user selects 'All Databases'), the
DataTableView loses its connection context.

Now uses activeTab.connectionId (the tab's own stored connection ID)
so table data always loads regardless of sidebar selection. Also
updates isTableViewConnectionValid to check the tab's connectionId.
…, saved queries layout

- SchemaTree: loading overlay absolutely positioned, only during initial fetch (not expand)
- SchemaTree: overflow-y-scroll prevents scrollbar layout shift
- DatabaseSelectorRow: refresh icon has 0.5s minimum spin duration
- DataTableView: min-h-0 + shrink-0 fixes pagination overflow
- SavedQueryItem: compact two-row layout with icon dates
- treeview: Lucide icons, category-specific group icons
- treeview: single-click selects, double-click opens
- treeview: unified selectedTreeItem with bg-primary/15 highlight
- save_query_metadata Rust command for atomic metadata upsert
- postgres list_views: split pg_matviews for PG-compat DBs
- with_db_switch! macro for all adapter database switching
- handleOpenDdlTab async fetch for procedure/function DDL
- MySQL database name escaping
- capabilities: fix MySQL/ClickHouse/Oracle/Hive flags
- global thin scrollbar styles
@Blankll Blankll changed the title feat: redesign queries sidebar with modular components + materialized view support fix: treeview loading flicker, pagination overflow, refresh animation, saved queries layout, materialized views Jun 24, 2026
@Blankll Blankll merged commit 498bcaf into master Jun 24, 2026
3 checks passed
@Blankll Blankll deleted the feat/sidebar-redesign-materialized-views branch June 24, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant