Three independent connection-list bugs:
1. Multi-select drag only moved one row. The drag system tracks a single
draggedId and ignored selectedTreeNodeIds. The drop callback now expands
to the full selection when the grabbed row is part of it, and the store
gains reorderSidebarEntries() to move them together.
2. Clicking the blank tree area didn't clear the selection (notably in
double-click activation mode). Row clicks now stopPropagation and the
tree containers clear the selection on click, so only blank clicks reset.
3. Creating a group then submitting an empty name dissolved ALL groups.
Enter (@keydown.enter) and the following @blur both fired finishRenameGroup;
the first call rebuilt the tree and recycled props.node onto another group,
so the second deleted the wrong one, cascading. Guard against double
invocation and treat an empty name as a cancel (never delete here — deleting
a group stays in the context menu).
Verified end-to-end on the web build: multi-select drag nests both
connections under the group; blank-click clears selection; empty-name Enter
keeps all groups intact. pnpm check is green.
Co-authored-by: vrustx <vrustx@vrustxdeMac-mini.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After an app update (typically >15min since last use), the on-disk schema
tree cache is past its TTL and counts as stale. When "locate in sidebar"
loads the connection's databases, the stale cache is served synchronously
and an async `refreshStaleTreeNode` fires in the background; that refresh
replaces the database node with a fresh one whose tables haven't loaded
yet, evicting the node that locate just populated. By the time
`findNodePathForActiveTab` runs, the target table isn't in the tree, so
locate only reaches the database. After a restart the cache is fresh, no
refresh races, and locate works — matching the report.
Make `ensureTreeLoadedForTab` accept `{ force }` (loads everything via
awaited calls, bypassing the stale-cache fire-and-forget path) and, in
`locateActiveTabInSidebar`, retry once with force when the first
`findNodePath` misses. Fresh-cache locates still succeed on the first
pass and never force (no regression); `refreshStaleTreeNode` is untouched.
Co-authored-by: vrustx <vrustx@vrustxdeMac-mini.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sidebar already supports multi-select, so deletion now resolves the context-clicked selected connection set before confirming. Connection removal gained a batched path to persist once while pruning sidebar layout, pins, active state, connection errors, and stale selection for every removed connection.
Constraint: No new dependencies and existing single-connection delete behavior must remain available.\nRejected: Delete every selected tree item regardless of type | mixed tree selections could unexpectedly remove connections while table/object deletion has separate SQL confirmation behavior.\nConfidence: high\nScope-risk: narrow\nTested: pnpm fmt; pnpm test; pnpm typecheck; pnpm lint; pnpm build\nNot-tested: Manual desktop UI interaction against a running Tauri window
Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
Database connection context menus now show a copy action when the connection has enabled transport layers. The action starts or reuses the ordered transport chain, copies the final local forwarding port, and keeps runtime config cached so later disconnect cleanup can stop the created tunnel.
Constraint: Local testing sometimes needs external tools to connect through DBX's generated proxy/tunnel endpoint
Rejected: Copy full host:port endpoint | user specifically asked for the port and existing tunnel host is always localhost
Rejected: Require an active pool before copying | local test workflows may need the tunnel before opening the DBX connection
Confidence: high
Scope-risk: moderate
Tested: pnpm test -- packages/app-tests/connectionTransport.test.ts (ran full app-tests: 862 passed)
Tested: pnpm typecheck
Tested: pnpm exec oxlint --vue-plugin apps/desktop/src/components/sidebar/TreeItem.vue apps/desktop/src/lib/connectionTransport.ts apps/desktop/src/lib/api.ts apps/desktop/src/lib/tauri.ts apps/desktop/src/lib/http.ts
Tested: cargo check -p dbx-core -p dbx-web
Tested: cargo check -p dbx
Tested: cargo fmt --check --all
Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
Add a configurable option in Settings > Navigation to reuse an existing data
tab instead of creating a new one each time a table is clicked in the sidebar.
* docs(getting-started): set brew upgrade to use official homebrew cask
* fix(mysql): make admin show handling dialect aware
* fix(data-compare): create missing target tables during sync
* feat(sql): suggest join conditions from foreign keys
* fix(sidebar): use filtered order for range selection
* fix(tabs): close connection tabs on disconnect
* fix(sqlserver): execute cte queries without wrapping
* fix(opengauss): open table structure editor
* perf(export): 优化导出ui体验和性能
* perf(export): 优化导出ui体验和性能
* fix(export): normalize status casing and fix web route issues
- Add missing table export web routes (POST /export/table, SSE progress, cancel)
- Fix tauri table export Promise to wait for terminal events
- Change cancel to return Ok(()) so it doesn't get overwritten as Error
- Unify ExportStatus to PascalCase across all frontend components
- Fix http.ts table export POST body wrapping
- Fix duplicate pub mod in dbx-web routes
* fix(export): return export file for browser download in web mode
Write table export output to temp dir, register a download endpoint,
and trigger browser download from the frontend when export completes.
* fix(export): avoid table export progress races
---------
Co-authored-by: Francesco Lucarelli <francesco06lucarelli@gmail.com>
Co-authored-by: t8y2 <1156263951@qq.com>
Co-authored-by: dqn <someonegdeng@qq.com>
Add a crosshair button next to the "New Group" button that scrolls the
sidebar tree to the table/database/collection corresponding to the
currently active tab. Auto-expands collapsed ancestors, reconnects
disconnected connections, and highlights the target node with an amber
flash that fades after 1.8s.