fix(objects): refresh object browser from shortcut

This commit is contained in:
t8y2 2026-07-17 22:54:33 +08:00
parent 57416bfcea
commit 1e0c25d754
3 changed files with 31 additions and 2 deletions

View File

@ -697,6 +697,8 @@ function refreshQueryEditorCompletionCache(): boolean {
}
function refreshData(): boolean {
// Reuse ObjectBrowser's reload path so schema reloads and stale object-response guards stay intact.
if (props.activeTab.mode === "objects") return objectBrowserRef.value?.refresh?.() ?? false;
if (props.activeTab.mode === "etcd") return etcdKeyBrowserRef.value?.refresh?.() ?? false;
if (props.activeTab.mode === "zookeeper") return zookeeperKeyBrowserRef.value?.refresh?.() ?? false;
// Restored data tabs intentionally omit row data, so refresh must work before DataGrid mounts.

View File

@ -79,6 +79,7 @@ import QueryEditor from "@/components/editor/QueryEditor.vue";
import { sqlFormatDialectForDbType, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { isCancelSearchShortcut } from "@/lib/editor/keyboardShortcuts";
import { executeWithProductionSqlGuard } from "@/lib/database/productionExecutionGuard";
import { formatShortcut } from "@/lib/editor/shortcutRegistry";
import { batchTableEmptyFeedback, buildBatchTableEmptyPlan, runBatchTableEmpty, type BatchTableEmptyPlanItem } from "@/lib/sidebar/batchTableEmpty";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import {
@ -122,6 +123,10 @@ const { highlight } = useSqlHighlighter();
const connectionStore = useConnectionStore();
const queryStore = useQueryStore();
const settingsStore = useSettingsStore();
const refreshTooltip = computed(() => {
const shortcut = formatShortcut(settingsStore.editorSettings.shortcuts.refreshData);
return shortcut ? `${t("grid.refresh")} (${shortcut})` : t("grid.refresh");
});
const schemas = ref<string[]>([]);
const selectedSchema = ref<string | undefined>(props.schema);
@ -2132,6 +2137,11 @@ async function reload() {
await loadObjects();
}
function refresh(): boolean {
void reload();
return true;
}
function onSchemaChange(value: any) {
selectedSchema.value = typeof value === "string" && value ? value : undefined;
emit("schemaChange", selectedSchema.value);
@ -2195,7 +2205,7 @@ function onSearchKeydown(event: KeyboardEvent) {
search.value = "";
}
defineExpose({ focusSearch });
defineExpose({ focusSearch, refresh });
onBeforeUnmount(() => {
stopColumnResize?.();
@ -2438,7 +2448,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
<CheckSquare v-if="settingsStore.editorSettings.objectBrowserShowCheckbox" class="h-3.5 w-3.5" />
<Square v-else class="h-3.5 w-3.5" />
</Button>
<Button variant="ghost" size="icon" class="h-7 w-7" :disabled="loadingObjects" @click="reload">
<Button variant="ghost" size="icon" class="h-7 w-7" :title="refreshTooltip" :disabled="loadingObjects" @click="reload">
<RefreshCw class="h-3.5 w-3.5" :class="{ 'animate-spin': loadingObjects }" />
</Button>
<Button v-if="canPasteTableClipboard()" variant="ghost" size="sm" class="h-7 px-2 text-xs" @click="openPasteTableDialog">

View File

@ -4,6 +4,7 @@ import { describe, expect, it } from "vitest";
const contentAreaSource = readFileSync(new URL("../../../components/layout/ContentArea.vue", import.meta.url), "utf8");
const connectionTreeSource = readFileSync(new URL("../../../components/sidebar/ConnectionTree.vue", import.meta.url), "utf8");
const ddlViewDialogSource = readFileSync(new URL("../../../components/objects/DdlViewDialog.vue", import.meta.url), "utf8");
const objectBrowserSource = readFileSync(new URL("../../../components/objects/ObjectBrowser.vue", import.meta.url), "utf8");
function openingTag(source: string, componentName: string): string {
return source.match(new RegExp(`<${componentName}\\b[\\s\\S]*?>`))?.[0] ?? "";
@ -26,3 +27,19 @@ describe("ContentArea external catalog wiring", () => {
expect(ddlViewDialogSource).toMatch(/api\.getTableDdl\([\s\S]*?props\.objectType, props\.catalog\)/);
});
});
describe("ContentArea object browser refresh wiring", () => {
it("routes content refresh through the ObjectBrowser handle", () => {
expect(contentAreaSource).toContain('if (props.activeTab.mode === "objects") return objectBrowserRef.value?.refresh?.() ?? false;');
});
it("exposes the existing ObjectBrowser reload path as refresh", () => {
expect(objectBrowserSource).toMatch(/function refresh\(\): boolean \{\s+void reload\(\);\s+return true;\s+\}/);
expect(objectBrowserSource).toContain("defineExpose({ focusSearch, refresh });");
});
it("shows the configured content refresh shortcut on the refresh button", () => {
expect(objectBrowserSource).toContain("formatShortcut(settingsStore.editorSettings.shortcuts.refreshData)");
expect(objectBrowserSource).toMatch(/<Button[^>]*:title="refreshTooltip"[^>]*@click="reload">/);
});
});