fix(objects): preserve category filter per tab
This commit is contained in:
11 files changed
+47
-32
No files matched your search
@@ -2504,12 +2504,14 @@ defineExpose({
|
||||
:initial-event-open-request-id="activeTab.objectBrowser?.eventOpenRequestId"
|
||||
:initial-event-create-request-id="activeTab.objectBrowser?.eventCreateRequestId"
|
||||
:initial-object-filter="activeTab.objectBrowser?.initialObjectFilter"
|
||||
:selected-object-filter="activeTab.objectBrowser?.filter"
|
||||
:initial-search-query="activeTab.objectBrowser?.searchQuery"
|
||||
:viewport="activeTab.objectBrowser?.viewport"
|
||||
@open-table="emit('openObjectTable', activeTab.id, $event)"
|
||||
@schema-change="emit('objectSchemaChange', activeTab.id, $event)"
|
||||
@viewport-change="emit('objectBrowserViewportChange', activeTab.id, $event)"
|
||||
@search-change="emit('objectBrowserSearchChange', activeTab.id, $event)"
|
||||
@filter-change="emit('objectBrowserFilterChange', activeTab.id, $event)"
|
||||
@add-to-ai="emit('addObjectTableToAi', activeTab.id, $event)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ConnectionConfig, ObjectBrowserViewport, QueryTab } from "@/types/database";
|
||||
import type { ConnectionConfig, ObjectBrowserFilter, ObjectBrowserViewport, QueryTab } from "@/types/database";
|
||||
import type { DataGridReloadIntent } from "@/lib/dataGrid/dataGridToolbar";
|
||||
import type { DataGridSortMode } from "@/lib/dataGrid/dataGridSort";
|
||||
import type { SqlObjectNavigationTarget } from "@/lib/sql/sqlNavigation";
|
||||
@@ -90,6 +90,7 @@ export interface ContentAreaSurfaceEmits {
|
||||
objectSchemaChange: [tabId: string, schema: string | undefined];
|
||||
objectBrowserViewportChange: [tabId: string, viewport: ObjectBrowserViewport];
|
||||
objectBrowserSearchChange: [tabId: string, query: string];
|
||||
objectBrowserFilterChange: [tabId: string, filter: ObjectBrowserFilter];
|
||||
addObjectTableToAi: [tabId: string, tables: Array<{ name: string; schema?: string }>];
|
||||
structureEditorSaved: [tabId: string, commentChanged: boolean];
|
||||
structureEditorClose: [tabId: string];
|
||||
|
||||
@@ -180,6 +180,7 @@ const props = defineProps<{
|
||||
/** 显式"新建事件"请求号:每次菜单点击递增,用于打开/重新进入 CREATE 编辑器 */
|
||||
initialEventCreateRequestId?: number;
|
||||
initialObjectFilter?: "tables" | "events";
|
||||
selectedObjectFilter?: ObjectFilter;
|
||||
initialSearchQuery?: string;
|
||||
viewport?: ObjectBrowserViewport;
|
||||
}>();
|
||||
@@ -189,6 +190,7 @@ const emit = defineEmits<{
|
||||
schemaChange: [schema: string | undefined];
|
||||
viewportChange: [viewport: ObjectBrowserViewport];
|
||||
searchChange: [query: string];
|
||||
filterChange: [filter: ObjectFilter];
|
||||
addToAi: [tables: Array<{ name: string; schema?: string }>];
|
||||
}>();
|
||||
|
||||
@@ -2805,7 +2807,7 @@ function openInitialEventIfNeeded() {
|
||||
|
||||
function finishObjectBrowserRowsLoad() {
|
||||
loadingObjects.value = false;
|
||||
const preferredFilter = props.initialObjectFilter ?? (props.initialEventName || props.initialEventCreateRequestId !== undefined ? "events" : "tables");
|
||||
const preferredFilter = props.initialEventName || props.initialEventCreateRequestId !== undefined ? "events" : (props.selectedObjectFilter ?? props.initialObjectFilter ?? "tables");
|
||||
if (!userHasSelectedFilter.value && objectCounts.value[preferredFilter] > 0) {
|
||||
// The default table filter is a presentation choice, not a user query
|
||||
// change, so preserve the tab's saved scroll offset across remounts.
|
||||
@@ -2817,7 +2819,10 @@ function finishObjectBrowserRowsLoad() {
|
||||
}
|
||||
|
||||
watch([() => props.initialEventName, () => props.initialEventOpenRequestId, () => props.initialEventCreateRequestId], ([name, requestId, createRequestId], [previousName, previousRequestId, previousCreateRequestId]) => {
|
||||
if (name !== previousName || requestId !== previousRequestId || createRequestId !== previousCreateRequestId) openedInitialEvent.value = "";
|
||||
if (name !== previousName || requestId !== previousRequestId || createRequestId !== previousCreateRequestId) {
|
||||
openedInitialEvent.value = "";
|
||||
if (name || createRequestId !== undefined) objectFilter.value = "events";
|
||||
}
|
||||
openInitialEventIfNeeded();
|
||||
});
|
||||
|
||||
@@ -3010,6 +3015,12 @@ function filterLabel(filter: ObjectFilter) {
|
||||
return `${t(key)} ${filterCount(filter)}`;
|
||||
}
|
||||
|
||||
function selectObjectFilter(filter: ObjectFilter) {
|
||||
userHasSelectedFilter.value = true;
|
||||
objectFilter.value = filter;
|
||||
emit("filterChange", filter);
|
||||
}
|
||||
|
||||
function getSearchInput(): HTMLInputElement | null {
|
||||
return rootRef.value?.querySelector<HTMLInputElement>("[data-object-search-input]") ?? null;
|
||||
}
|
||||
@@ -3323,17 +3334,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="showObjectFilter && showInlineObjectFilter" class="flex h-7 shrink-0 items-center rounded border bg-muted/20 p-0.5">
|
||||
<button
|
||||
v-for="filter in objectFilters"
|
||||
:key="filter"
|
||||
type="button"
|
||||
class="h-6 rounded-sm px-2 text-xs text-muted-foreground transition-colors hover:text-foreground"
|
||||
:class="{ 'bg-background text-foreground shadow-sm': objectFilter === filter }"
|
||||
@click="
|
||||
userHasSelectedFilter = true;
|
||||
objectFilter = filter;
|
||||
"
|
||||
>
|
||||
<button v-for="filter in objectFilters" :key="filter" type="button" class="h-6 rounded-sm px-2 text-xs text-muted-foreground transition-colors hover:text-foreground" :class="{ 'bg-background text-foreground shadow-sm': objectFilter === filter }" @click="selectObjectFilter(filter)">
|
||||
{{ filterLabel(filter) }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -3419,17 +3420,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
<DropdownMenuCheckboxItem :model-value="settingsStore.editorSettings.objectBrowserShowCheckbox" @select.prevent @update:model-value="toggleCheckboxColumn()">{{ t("objects.toggleCheckbox") }}</DropdownMenuCheckboxItem>
|
||||
<template v-if="showObjectFilter && toolbarTier >= 2">
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem
|
||||
v-for="filter in objectFilters"
|
||||
:key="filter"
|
||||
:model-value="objectFilter === filter"
|
||||
@select.prevent
|
||||
@update:model-value="
|
||||
userHasSelectedFilter = true;
|
||||
objectFilter = filter;
|
||||
"
|
||||
>{{ filterLabel(filter) }}</DropdownMenuCheckboxItem
|
||||
>
|
||||
<DropdownMenuCheckboxItem v-for="filter in objectFilters" :key="filter" :model-value="objectFilter === filter" @select.prevent @update:model-value="selectObjectFilter(filter)">{{ filterLabel(filter) }}</DropdownMenuCheckboxItem>
|
||||
</template>
|
||||
</ToolbarOverflowMenu>
|
||||
</div>
|
||||
|
||||
+2
-1
@@ -55,10 +55,11 @@ describe("ObjectBrowser MySQL Event CREATE navigation", () => {
|
||||
it("re-triggers a create request when the request id changes on a reused tab", () => {
|
||||
expect(objectBrowserSource).toContain("() => props.initialEventCreateRequestId");
|
||||
expect(objectBrowserSource).toMatch(/watch\(\[\(\) => props\.initialEventName, \(\) => props\.initialEventOpenRequestId, \(\) => props\.initialEventCreateRequestId\][\s\S]*?openedInitialEvent\.value = "";[\s\S]*?openInitialEventIfNeeded\(\);/);
|
||||
expect(objectBrowserSource).toContain('if (name || createRequestId !== undefined) objectFilter.value = "events";');
|
||||
});
|
||||
|
||||
it("lists the events filter as the preferred view for a create request", () => {
|
||||
expect(objectBrowserSource).toMatch(/const preferredFilter = props\.initialObjectFilter \?\? \(props\.initialEventName \|\| props\.initialEventCreateRequestId !== undefined \? "events" : "tables"\);/);
|
||||
expect(objectBrowserSource).toMatch(/const preferredFilter = props\.initialEventName \|\| props\.initialEventCreateRequestId !== undefined \? "events" : \(props\.selectedObjectFilter \?\? props\.initialObjectFilter \?\? "tables"\);/);
|
||||
});
|
||||
|
||||
it("ContentArea passes the create request id into ObjectBrowser", () => {
|
||||
|
||||
Reference in new issue
Block a user