feat(structure): persist local column order
This commit is contained in:
13 files changed
+278
-9
No files matched your search
@@ -28,7 +28,9 @@ import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStor
|
||||
import { type BuildTableStructureChangeSqlOptions, type EditableStructureColumn, type EditableStructureForeignKey, type EditableStructureIndex, type EditableStructureTrigger } from "@/lib/table/tableStructureEditorSql";
|
||||
import { PRESET_FIELDS_TEMPLATE_ID, createTableColumnTemplateDrafts } from "@/lib/table/tableColumnTemplates";
|
||||
import { getTableMetadataCapabilities, firstStructureMetadataTab, isStructureMetadataTabSupported } from "@/lib/table/tableMetadataCapabilities";
|
||||
import { canAddTableStructureColumn, getTableStructureCapabilities } from "@/lib/table/tableStructureCapabilities";
|
||||
import { canAddTableStructureColumn, getTableStructureCapabilities, hasLocalTableColumnOrderChange, isPhysicalTableColumnOrderChange, supportsLocalTableColumnReorder } from "@/lib/table/tableStructureCapabilities";
|
||||
import { orderedColumnIndexes, uniqueDataGridColumnOrderKeys } from "@/lib/dataGrid/dataGridColumnOrder";
|
||||
import { loadTableDataGridColumnOrder, notifyTableDataGridColumnOrderChanged, removeTableDataGridColumnOrder, saveTableDataGridColumnOrder, tableDataGridColumnOrderScopeKey } from "@/lib/dataGrid/dataGridColumnLayoutStorage";
|
||||
import { connectionObjectTreeQuerySchema, tableStructureDatabaseTypeForConnection } from "@/lib/database/jdbcDialect";
|
||||
import type { TableInfoTab, TableStructureEditorDraft, TableStructureEditorTarget, TableStructureEditorViewport } from "@/types/database";
|
||||
import {
|
||||
@@ -191,7 +193,7 @@ function columnChanged(column: EditableStructureColumn, index: number): boolean
|
||||
if (!column.original || column.markedForDrop) return true;
|
||||
const original = column.original;
|
||||
return (
|
||||
column.originalPosition !== index ||
|
||||
isPhysicalTableColumnOrderChange(databaseType.value, connection.value?.db_type, column.originalPosition, index) ||
|
||||
column.name !== original.name ||
|
||||
column.dataType !== original.data_type ||
|
||||
column.isNullable !== original.is_nullable ||
|
||||
@@ -1152,6 +1154,7 @@ function resetState() {
|
||||
highlightedIndexId.value = null;
|
||||
appliedInitialTargetSearchKey = "";
|
||||
appliedInitialTargetScrollKey = "";
|
||||
localColumnOrderNoticeShown.value = false;
|
||||
}
|
||||
|
||||
async function reloadStructureFromDatabase() {
|
||||
@@ -1216,7 +1219,7 @@ async function loadStructure(silent = false, scope: StructureRefreshScope = FULL
|
||||
// Load live charset/collation metadata from the MySQL server so the column
|
||||
// editor shows the correct options for the server version.
|
||||
void loadCharsetMetadata();
|
||||
columns.value = createColumnDrafts(nextColumns, databaseType.value);
|
||||
columns.value = applyStoredLocalColumnOrder(createColumnDrafts(nextColumns, databaseType.value));
|
||||
}
|
||||
|
||||
const nextTableComment = await tableCommentPromise;
|
||||
@@ -1325,6 +1328,7 @@ type ColumnDragState = {
|
||||
};
|
||||
|
||||
const columnDragState = ref<ColumnDragState | null>(null);
|
||||
const localColumnOrderNoticeShown = ref(false);
|
||||
let columnDragPreviousBodyUserSelect = "";
|
||||
let columnDragPreviousBodyCursor = "";
|
||||
let columnDragTracking = false;
|
||||
@@ -1350,7 +1354,53 @@ function canDropColumnAt(sourceIndex: number, insertionIndex: number): boolean {
|
||||
return crossedColumns.every((column) => !column.original);
|
||||
}
|
||||
|
||||
const canShowColumnDragControls = computed(() => isCreateMode.value || structureCapabilities.value.reorderColumn);
|
||||
const usesLocalTableColumnOrder = computed(() => !isCreateMode.value && supportsLocalTableColumnReorder(databaseType.value, connection.value?.db_type));
|
||||
const canShowColumnDragControls = computed(() => isCreateMode.value || structureCapabilities.value.reorderColumn || usesLocalTableColumnOrder.value);
|
||||
|
||||
function localTableColumnOrderScopeKey(): string {
|
||||
return tableDataGridColumnOrderScopeKey({
|
||||
connectionId: props.connectionId,
|
||||
database: props.database,
|
||||
schema: props.schema,
|
||||
tableName: props.tableName,
|
||||
});
|
||||
}
|
||||
|
||||
function localColumnOrderKeys(items: readonly EditableStructureColumn[]): string[] {
|
||||
return uniqueDataGridColumnOrderKeys(items.map((column) => column.name));
|
||||
}
|
||||
|
||||
const hasLocalColumnOrderChange = computed(() => {
|
||||
if (!usesLocalTableColumnOrder.value) return false;
|
||||
return hasLocalTableColumnOrderChange(columns.value);
|
||||
});
|
||||
|
||||
function applyStoredLocalColumnOrder(items: EditableStructureColumn[]): EditableStructureColumn[] {
|
||||
if (!usesLocalTableColumnOrder.value) return items;
|
||||
const orderedKeys = loadTableDataGridColumnOrder(localTableColumnOrderScopeKey());
|
||||
if (!orderedKeys.length) return items;
|
||||
const columnKeys = uniqueDataGridColumnOrderKeys(items.map((column) => column.name));
|
||||
const indexes = orderedColumnIndexes({
|
||||
availableIndexes: items.map((_, index) => index),
|
||||
columnKeys,
|
||||
orderedKeys,
|
||||
});
|
||||
return indexes.map((index) => items[index]).filter((column): column is EditableStructureColumn => !!column);
|
||||
}
|
||||
|
||||
function persistLocalColumnOrder(showNotice = true) {
|
||||
if (!usesLocalTableColumnOrder.value) return;
|
||||
const scopeKey = localTableColumnOrderScopeKey();
|
||||
if (hasLocalColumnOrderChange.value) {
|
||||
saveTableDataGridColumnOrder(scopeKey, localColumnOrderKeys(columns.value));
|
||||
} else {
|
||||
removeTableDataGridColumnOrder(scopeKey);
|
||||
}
|
||||
notifyTableDataGridColumnOrderChanged(scopeKey);
|
||||
if (!showNotice || localColumnOrderNoticeShown.value) return;
|
||||
localColumnOrderNoticeShown.value = true;
|
||||
toast(t("structureEditor.localColumnOrderNotice"), 4000);
|
||||
}
|
||||
|
||||
function isSqlServerIdentityChecked(column: EditableStructureColumn): boolean {
|
||||
return !!column.extra.autoIncrement || !!column.extra.identity;
|
||||
@@ -1510,6 +1560,7 @@ function moveColumnTo(index: number, insertionIndex: number) {
|
||||
const adjustedInsertionIndex = insertionIndex > index ? insertionIndex - 1 : insertionIndex;
|
||||
nextColumns.splice(adjustedInsertionIndex, 0, column);
|
||||
columns.value = nextColumns;
|
||||
persistLocalColumnOrder();
|
||||
}
|
||||
|
||||
function onColumnDragPointerDown(index: number, event: PointerEvent) {
|
||||
@@ -2097,6 +2148,8 @@ async function applyChanges() {
|
||||
emit("saved", tableComment.value !== originalTableComment.value);
|
||||
emit("close");
|
||||
} else {
|
||||
// Refresh persisted keys after successful renames/additions before metadata reloads.
|
||||
persistLocalColumnOrder(false);
|
||||
saving.value = false;
|
||||
postSaveRefreshing.value = true;
|
||||
skipNextRefreshVersion = true;
|
||||
@@ -2788,7 +2841,7 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
:class="[structureActionButtonClass, canDragColumn(index) ? 'cursor-grab active:cursor-grabbing' : 'cursor-not-allowed']"
|
||||
:class="[structureActionButtonClass, canDragColumn(index) ? 'cursor-grab active:cursor-grabbing' : 'cursor-not-allowed', hasLocalColumnOrderChange ? 'border-primary/30 bg-primary/10 text-primary hover:bg-primary/15 hover:text-primary' : '']"
|
||||
:disabled="!canDragColumn(index)"
|
||||
:title="t('structureEditor.dragColumn')"
|
||||
:aria-label="t('structureEditor.dragColumn')"
|
||||
|
||||
Reference in new issue
Block a user