mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
fix(objects): render MySQL event create editor with fresh state
This commit is contained in:
@@ -155,7 +155,7 @@ import { loadObjectMetadataFacet } from "@/lib/metadata/objectMetadataCache";
|
||||
import { invalidateObjectMetadataCache } from "@/lib/metadata/objectMetadataCache";
|
||||
import { invalidateObjectDdl } from "@/lib/metadata/objectDdlCache";
|
||||
import { invalidateObjectBrowserRowsCache } from "@/lib/table/objectBrowserRowsCache";
|
||||
import { resolveInitialEventEditorRequest } from "@/lib/table/eventEditorRequest";
|
||||
import { eventEditorInstanceKey, resolveInitialEventEditorRequest } from "@/lib/table/eventEditorRequest";
|
||||
|
||||
type ObjectFilter = ObjectBrowserFilter;
|
||||
type ObjectBrowserColumnKey = "select" | "name" | "type" | "estimatedRows" | "totalBytes" | "created_at" | "updated_at" | "comment";
|
||||
@@ -214,6 +214,13 @@ const sidePanelRow = ref<ObjectBrowserRow | null>(null);
|
||||
const openedInitialEvent = ref("");
|
||||
const isEventEditor = computed(() => sidePanelMode.value === "event-editor");
|
||||
const sidePanelMode = ref<"table-info" | "source" | "type-info" | "event-editor">("source");
|
||||
const eventEditorKey = computed(() =>
|
||||
eventEditorInstanceKey({
|
||||
createRequestId: props.initialEventCreateRequestId,
|
||||
openRequestId: props.initialEventOpenRequestId,
|
||||
rowId: sidePanelRow.value?.id,
|
||||
}),
|
||||
);
|
||||
// Table info panel state
|
||||
const tableInfoTab = ref<TableInfoTab>("ddl");
|
||||
const tableColumns = ref<ColumnInfo[]>([]);
|
||||
@@ -3492,7 +3499,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
</div>
|
||||
</div>
|
||||
<!-- Right-side panel: table info or source -->
|
||||
<div v-if="sidePanelRow" class="object-browser-side-panel relative flex min-h-0 shrink-0 flex-col border-l bg-background" :class="{ 'side-panel-resizing': isResizingSidePanel }" :style="{ width: `${sidePanelWidth}px` }">
|
||||
<div v-if="sidePanelRow || isEventEditor" class="object-browser-side-panel relative flex min-h-0 shrink-0 flex-col border-l bg-background" :class="{ 'side-panel-resizing': isResizingSidePanel }" :style="{ width: `${sidePanelWidth}px` }">
|
||||
<div class="absolute left-0 top-0 bottom-0 z-20 w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-primary/30" @mousedown.prevent="onSidePanelResizeStart" />
|
||||
<!-- Table info mode -->
|
||||
<template v-if="sidePanelMode === 'table-info'">
|
||||
@@ -3681,7 +3688,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
<CustomTypeInfoPanel ref="sidePanelRef" :connection="props.connection" :database="props.database" :schema="sidePanelRow?.schema || selectedSchema || props.database" :name="sidePanelRow?.name || ''" :catalog="props.catalog" @close="closeSidePanel" />
|
||||
</template>
|
||||
<template v-else-if="sidePanelMode === 'event-editor'">
|
||||
<MySqlEventEditor :connection="props.connection" :database="props.database" :schema="sidePanelRow?.schema || selectedSchema || props.database" :name="sidePanelRow?.name" :read-only="props.initialEventReadOnly" @saved="onEventSaved" @close="closeSidePanel" />
|
||||
<MySqlEventEditor :key="eventEditorKey" :connection="props.connection" :database="props.database" :schema="sidePanelRow?.schema || selectedSchema || props.database" :name="sidePanelRow?.name" :read-only="props.initialEventReadOnly" @saved="onEventSaved" @close="closeSidePanel" />
|
||||
</template>
|
||||
<!-- Source mode (views, procedures, functions, sequences) -->
|
||||
<template v-else>
|
||||
|
||||
+8
-2
@@ -42,8 +42,14 @@ describe("ObjectBrowser MySQL Event CREATE navigation", () => {
|
||||
expect(openInitialEventIfNeeded).not.toContain("sidePanelRow.value = row;");
|
||||
});
|
||||
|
||||
it("renders the editor with sidePanelRow name (empty in create mode -> CREATE SQL)", () => {
|
||||
expect(objectBrowserSource).toContain('<MySqlEventEditor :connection="props.connection" :database="props.database" :schema="sidePanelRow?.schema || selectedSchema || props.database" :name="sidePanelRow?.name"');
|
||||
it("keeps the CREATE editor mounted when there is no EVENT row", () => {
|
||||
expect(objectBrowserSource).toContain('v-if="sidePanelRow || isEventEditor"');
|
||||
expect(objectBrowserSource).toContain('<MySqlEventEditor :key="eventEditorKey"');
|
||||
});
|
||||
|
||||
it("renders the editor with an empty CREATE name and request-scoped instance", () => {
|
||||
expect(objectBrowserSource).toContain('<MySqlEventEditor :key="eventEditorKey" :connection="props.connection" :database="props.database" :schema="sidePanelRow?.schema || selectedSchema || props.database" :name="sidePanelRow?.name"');
|
||||
expect(objectBrowserSource).toMatch(/const eventEditorKey = computed\(\(\) =>[\s\S]*?createRequestId: props\.initialEventCreateRequestId[\s\S]*?openRequestId: props\.initialEventOpenRequestId[\s\S]*?rowId: sidePanelRow\.value\?\.id/);
|
||||
});
|
||||
|
||||
it("re-triggers a create request when the request id changes on a reused tab", () => {
|
||||
|
||||
+12
-1
@@ -1,8 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveInitialEventEditorRequest } from "./eventEditorRequest";
|
||||
import { eventEditorInstanceKey, resolveInitialEventEditorRequest } from "./eventEditorRequest";
|
||||
|
||||
const base = { openedRequestKey: "" };
|
||||
|
||||
describe("eventEditorInstanceKey", () => {
|
||||
it("separates repeated CREATE requests", () => {
|
||||
expect(eventEditorInstanceKey({ createRequestId: 1 })).not.toBe(eventEditorInstanceKey({ createRequestId: 2 }));
|
||||
});
|
||||
|
||||
it("separates ALTER rows from CREATE mode", () => {
|
||||
expect(eventEditorInstanceKey({ openRequestId: 1, rowId: "event:old_event" })).not.toBe(eventEditorInstanceKey({ createRequestId: 3 }));
|
||||
expect(eventEditorInstanceKey({ openRequestId: 1, rowId: "event:old_event" })).not.toBe(eventEditorInstanceKey({ openRequestId: 1, rowId: "event:other_event" }));
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveInitialEventEditorRequest", () => {
|
||||
describe("create request (New Event)", () => {
|
||||
it("opens CREATE mode without requiring an existing EVENT row", () => {
|
||||
|
||||
@@ -30,6 +30,17 @@ export interface InitialEventEditorRequestInput {
|
||||
loadingObjects?: boolean;
|
||||
}
|
||||
|
||||
export interface EventEditorInstanceKeyInput {
|
||||
createRequestId?: number;
|
||||
openRequestId?: number;
|
||||
rowId?: string;
|
||||
}
|
||||
|
||||
export function eventEditorInstanceKey({ createRequestId, openRequestId, rowId }: EventEditorInstanceKeyInput): string {
|
||||
const requestKey = createRequestId !== undefined ? `create:${createRequestId}` : `open:${openRequestId ?? 0}`;
|
||||
return `${requestKey}:${rowId ?? "new"}`;
|
||||
}
|
||||
|
||||
export function resolveInitialEventEditorRequest(input: InitialEventEditorRequestInput): InitialEventEditorDecision {
|
||||
const { eventCreateRequestId, eventName, eventOpenRequestId, openedRequestKey, hasEventRow = false, loadingObjects = false } = input;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user