diff --git a/src/components/structure/TableStructureEditorDialog.vue b/src/components/structure/TableStructureEditorDialog.vue index 7cb3e046f..ff1e5ff8f 100644 --- a/src/components/structure/TableStructureEditorDialog.vue +++ b/src/components/structure/TableStructureEditorDialog.vue @@ -11,12 +11,15 @@ import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@/components/ui/tabs"; import { - AlertTriangle, Check, Database, KeyRound, Loader2, Plus, RefreshCw, Save, TableProperties, Trash2, X, + AlertTriangle, Check, ChevronDown, Database, KeyRound, Loader2, Plus, RefreshCw, Save, TableProperties, Trash2, X, } from "lucide-vue-next"; +import { + DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; import { useConnectionStore } from "@/stores/connectionStore"; import { useToast } from "@/composables/useToast"; import { buildTableStructureChangeSql, type EditableStructureColumn, type EditableStructureIndex } from "@/lib/tableStructureEditorSql"; -import { createColumnDrafts, createIndexDrafts, splitIndexColumns, toColumnNames } from "@/lib/tableStructureEditorState"; +import { createColumnDrafts, createIndexDrafts, toColumnNames } from "@/lib/tableStructureEditorState"; import type { ForeignKeyInfo, TriggerInfo } from "@/types/database"; import * as api from "@/lib/tauri"; @@ -45,6 +48,26 @@ const indexes = ref([]); const foreignKeys = ref([]); const triggers = ref([]); +const indexColWidths = ref([160, 240, 80, 112, 160, 192, 160, 96]); +const resizing = ref<{ col: number; startX: number; startW: number } | null>(null); + +function onIndexColResize(e: MouseEvent, col: number) { + e.preventDefault(); + resizing.value = { col, startX: e.clientX, startW: indexColWidths.value[col] }; + const onMove = (ev: MouseEvent) => { + if (!resizing.value) return; + const delta = ev.clientX - resizing.value.startX; + indexColWidths.value[col] = Math.max(60, resizing.value.startW + delta); + }; + const onUp = () => { + resizing.value = null; + document.removeEventListener("mousemove", onMove); + document.removeEventListener("mouseup", onUp); + }; + document.addEventListener("mousemove", onMove); + document.addEventListener("mouseup", onUp); +} + const connection = computed(() => props.prefillConnectionId ? store.getConfig(props.prefillConnectionId) : undefined ); @@ -138,12 +161,35 @@ function addIndex() { columns: [], isUnique: false, isPrimary: false, + filter: "", + indexType: "", + includedColumns: [], + comment: "", markedForDrop: false, }); } -function updateIndexColumns(index: EditableStructureIndex, value: string) { - index.columns = splitIndexColumns(value); +const availableColumnNames = computed(() => + columns.value.filter((c) => !c.markedForDrop).map((c) => c.name).filter(Boolean) +); + +const colSearch = ref(""); +const filteredColumnNames = computed(() => { + const q = colSearch.value.toLowerCase().trim(); + if (!q) return availableColumnNames.value; + return availableColumnNames.value.filter((c) => c.toLowerCase().includes(q)); +}); + +function toggleIndexColumn(index: EditableStructureIndex, col: string) { + const i = index.columns.indexOf(col); + if (i >= 0) index.columns.splice(i, 1); + else index.columns.push(col); +} + +function toggleIncludedColumn(index: EditableStructureIndex, col: string) { + const i = index.includedColumns.indexOf(col); + if (i >= 0) index.includedColumns.splice(i, 1); + else index.includedColumns.push(col); } function removeNewIndex(index: EditableStructureIndex) { @@ -294,24 +340,61 @@ watch(open, (value) => { - - - - + - + + + +
{{ t('structureEditor.indexName') }}{{ t('structureEditor.indexColumns') }}{{ t('structureEditor.unique') }}{{ t('structureEditor.actions') }} + {{ label }} +
+
- + - + + + + + + +
+ +
+ + {{ col }} + +
+
+ {{ toColumnNames(index.columns) }}
+ {{ index.indexType || 'BTREE' }} + + + + + + + +
+ +
+ + {{ col }} + +
+
+ {{ index.includedColumns.join(', ') }} +
+ + + {{ index.comment }} + + {{ t('structureEditor.primary') }}