feat(grid): persist column layouts and improve drag-to-reorder
This commit is contained in:
1 parent
f5c29f08f1
commit
44f748d3a1
24 files changed
+1532
-276
No files matched your search
@@ -1,11 +1,21 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { effectScope, nextTick, ref } from "vue";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { dataGridColumnOffsets, dataGridHorizontalColumnWindow, useDataGridColumnLayout, useDataGridColumnLayoutState } from "@/composables/useDataGridColumnLayout";
|
||||
import { loadDataGridColumnLayout, saveDataGridColumnLayout } from "@/lib/dataGrid/dataGridColumnLayoutStorage";
|
||||
|
||||
describe("useDataGridColumnLayout", () => {
|
||||
beforeEach(() => localStorage.clear());
|
||||
beforeEach(() => {
|
||||
const values = new Map<string, string>();
|
||||
vi.stubGlobal("localStorage", {
|
||||
clear: () => values.clear(),
|
||||
getItem: (key: string) => values.get(key) ?? null,
|
||||
setItem: (key: string, value: string) => values.set(key, value),
|
||||
removeItem: (key: string) => values.delete(key),
|
||||
});
|
||||
});
|
||||
afterEach(() => vi.unstubAllGlobals());
|
||||
it("builds cumulative offsets", () => {
|
||||
expect(dataGridColumnOffsets([80, 120, 60])).toEqual([0, 80, 200, 260]);
|
||||
});
|
||||
@@ -91,7 +101,7 @@ describe("useDataGridColumnLayout", () => {
|
||||
|
||||
allNullColumnIndexes.value = [2];
|
||||
await nextTick();
|
||||
state.resetColumnVisibility();
|
||||
state.resetColumnVisibility([]);
|
||||
expect(state.visibleColumnIndexes.value).toEqual([0, 1]);
|
||||
|
||||
state.toggleAllNullColumns();
|
||||
@@ -101,7 +111,6 @@ describe("useDataGridColumnLayout", () => {
|
||||
});
|
||||
|
||||
it("restores manually hidden columns after the grid scope is recreated", () => {
|
||||
const hiddenColumnKeys = ref<string[]>([]);
|
||||
const options = {
|
||||
columns: ref(["id", "name", "email"]),
|
||||
sourceColumns: ref(undefined),
|
||||
@@ -111,28 +120,49 @@ describe("useDataGridColumnLayout", () => {
|
||||
columnOrderKeys: ref(["id\0\0", "name\0\0", "email\0\0"]),
|
||||
layoutScopeKey: ref("visibility-recreated-layout"),
|
||||
tableScopeKey: ref(""),
|
||||
initialHiddenColumnKeys: hiddenColumnKeys,
|
||||
onHiddenColumnKeysChange: (keys: string[]) => {
|
||||
hiddenColumnKeys.value = keys;
|
||||
},
|
||||
};
|
||||
const firstScope = effectScope();
|
||||
const firstState = firstScope.run(() => useDataGridColumnLayoutState(options))!;
|
||||
|
||||
firstState.toggleColumnVisibility(1);
|
||||
expect(hiddenColumnKeys.value).toEqual(["name\0\0"]);
|
||||
firstScope.stop();
|
||||
|
||||
const recreatedScope = effectScope();
|
||||
const recreatedState = recreatedScope.run(() => useDataGridColumnLayoutState(options))!;
|
||||
expect(recreatedState.visibleColumnIndexes.value).toEqual([0, 2]);
|
||||
recreatedState.showAllColumns();
|
||||
expect(hiddenColumnKeys.value).toEqual([]);
|
||||
recreatedScope.stop();
|
||||
|
||||
expect(JSON.parse(localStorage.getItem("dbx-data-grid-column-layout:visibility-recreated-layout")!)).toMatchObject({ hiddenKeys: [] });
|
||||
});
|
||||
|
||||
it("show all clears hidden keys for fields missing from the current page", () => {
|
||||
const layoutScopeKey = "visibility-missing-field-layout";
|
||||
saveDataGridColumnLayout(layoutScopeKey, {
|
||||
orderKeys: [],
|
||||
hiddenKeys: ["goodsList\0\0"],
|
||||
});
|
||||
const scope = effectScope();
|
||||
const state = scope.run(() =>
|
||||
useDataGridColumnLayoutState({
|
||||
columns: ref(["id", "status"]),
|
||||
sourceColumns: ref(undefined),
|
||||
commentByColumn: ref(new Map()),
|
||||
displayableColumnIndexes: ref([0, 1]),
|
||||
allNullColumnIndexes: ref([]),
|
||||
columnOrderKeys: ref(["id\0\0", "status\0\0"]),
|
||||
layoutScopeKey: ref(layoutScopeKey),
|
||||
tableScopeKey: ref(""),
|
||||
}),
|
||||
)!;
|
||||
|
||||
state.showAllColumns();
|
||||
scope.stop();
|
||||
|
||||
expect(loadDataGridColumnLayout(layoutScopeKey)?.hiddenKeys).toEqual([]);
|
||||
});
|
||||
|
||||
it("persists a null column when it is manually hidden after showing all columns", () => {
|
||||
const onHiddenColumnKeysChange = vi.fn();
|
||||
const scope = effectScope();
|
||||
const state = scope.run(() =>
|
||||
useDataGridColumnLayoutState({
|
||||
@@ -145,7 +175,6 @@ describe("useDataGridColumnLayout", () => {
|
||||
layoutScopeKey: ref("visibility-null-column-layout"),
|
||||
tableScopeKey: ref(""),
|
||||
hideNullColumns: ref(true),
|
||||
onHiddenColumnKeysChange,
|
||||
}),
|
||||
)!;
|
||||
|
||||
@@ -153,7 +182,30 @@ describe("useDataGridColumnLayout", () => {
|
||||
state.showAllColumns();
|
||||
state.toggleColumnVisibility(1);
|
||||
|
||||
expect(onHiddenColumnKeysChange).toHaveBeenLastCalledWith(["empty\0\0"]);
|
||||
scope.stop();
|
||||
expect(JSON.parse(localStorage.getItem("dbx-data-grid-column-layout:visibility-null-column-layout")!)).toMatchObject({ hiddenKeys: ["empty\0\0"] });
|
||||
});
|
||||
|
||||
it("returns ordered layout options with visibility state and reorders hidden fields", () => {
|
||||
const scope = effectScope();
|
||||
const state = scope.run(() =>
|
||||
useDataGridColumnLayoutState({
|
||||
columns: ref(["id", "status", "goodsList"]),
|
||||
sourceColumns: ref(undefined),
|
||||
commentByColumn: ref(new Map([["goodsList", "Line items"]])),
|
||||
displayableColumnIndexes: ref([0, 1, 2]),
|
||||
allNullColumnIndexes: ref([]),
|
||||
columnOrderKeys: ref(["id\0\0", "status\0\0", "goodsList\0\0"]),
|
||||
layoutScopeKey: ref("layout-options"),
|
||||
tableScopeKey: ref(""),
|
||||
}),
|
||||
)!;
|
||||
|
||||
state.toggleColumnVisibility(2);
|
||||
state.moveDisplayableColumn(2, 1);
|
||||
|
||||
expect(state.filteredColumnLayoutOptions("line")).toMatchObject([{ column: "goodsList", visible: false, displayPosition: 1 }]);
|
||||
expect(state.orderedDisplayableColumnIndexes.value).toEqual([0, 2, 1]);
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { computed, nextTick, onScopeDispose, ref, toValue, watch, type MaybeRefOrGetter } from "vue";
|
||||
import { columnOrderKeysForIndexes, isDefaultColumnOrder, moveVisibleColumnIndex, orderedColumnIndexes } from "@/lib/dataGrid/dataGridColumnOrder";
|
||||
import { columnOrderKeysForIndexes, isDefaultColumnOrder, mergeUnavailableColumnOrderKeys, moveDisplayableColumnIndex, moveVisibleColumnIndex, orderedColumnIndexes } from "@/lib/dataGrid/dataGridColumnOrder";
|
||||
import { columnHeaderCanvasPointerDisabled, columnHeaderClickShouldBeSuppressed, columnHeaderPreviewOffsetForColumn, columnHeaderTooltipDisabled } from "@/lib/dataGrid/dataGridColumnHeaderInteraction";
|
||||
import {
|
||||
loadDataGridColumnOrder,
|
||||
loadDataGridColumnLayout,
|
||||
loadDataGridColumnFrozenState,
|
||||
loadTableDataGridColumnOrder,
|
||||
notifyTableDataGridColumnOrderChanged,
|
||||
removeDataGridColumnOrder,
|
||||
removeDataGridColumnFrozenCount,
|
||||
removeTableDataGridColumnOrder,
|
||||
saveDataGridColumnOrder,
|
||||
saveDataGridColumnLayout,
|
||||
saveDataGridColumnFrozenCount,
|
||||
saveTableDataGridColumnOrder,
|
||||
type TableDataGridColumnOrderChangedDetail,
|
||||
} from "@/lib/dataGrid/dataGridColumnLayoutStorage";
|
||||
import { filterColumnVisibilityOptions, hiddenColumnIndexesForKeys, hiddenColumnIndexesWithAllNullColumns, hiddenColumnKeysForIndexes, invertedHiddenColumnIndexes, nextHiddenColumnIndexes, removeAutoHiddenColumnIndexes, visibleColumnIndexesForFilter } from "@/lib/dataGrid/dataGridColumnVisibility";
|
||||
import { buildDataGridColumnLookupItems, filterDataGridColumnLookupItems, type DataGridColumnLookupItem } from "@/lib/dataGrid/dataGridColumnLookup";
|
||||
import { hiddenColumnIndexesForKeys, hiddenColumnIndexesWithAllNullColumns, hiddenColumnKeysForIndexes, invertedHiddenColumnIndexes, nextHiddenColumnIndexes, removeAutoHiddenColumnIndexes, visibleColumnIndexesForFilter } from "@/lib/dataGrid/dataGridColumnVisibility";
|
||||
|
||||
export type RenderedDataGridColumn = {
|
||||
visibleColIdx: number;
|
||||
@@ -29,6 +29,13 @@ export type DataGridHorizontalColumnWindow = {
|
||||
afterWidth: number;
|
||||
};
|
||||
|
||||
export interface DataGridColumnLayoutOption extends DataGridColumnLookupItem {
|
||||
key: string;
|
||||
column: string;
|
||||
visible: boolean;
|
||||
displayPosition: number;
|
||||
}
|
||||
|
||||
type ColumnHeaderDragState = {
|
||||
sourceVisibleIndex: number;
|
||||
targetVisibleIndex: number;
|
||||
@@ -78,7 +85,6 @@ export function useDataGridColumnLayoutState(options: {
|
||||
tableScopeKey: MaybeRefOrGetter<string>;
|
||||
initialHiddenColumnKeys?: MaybeRefOrGetter<readonly string[] | undefined>;
|
||||
hideNullColumns?: MaybeRefOrGetter<boolean>;
|
||||
onHiddenColumnKeysChange?: (keys: string[]) => void;
|
||||
onHideNullColumnsChange?: (value: boolean) => void;
|
||||
onRefreshMetrics?: () => void;
|
||||
}) {
|
||||
@@ -87,9 +93,12 @@ export function useDataGridColumnLayoutState(options: {
|
||||
const nullColumnsHidden = computed(() => (options.hideNullColumns === undefined ? localNullColumnsHidden.value : toValue(options.hideNullColumns)));
|
||||
const autoHiddenNullColumnIndexes = ref<Set<number>>(new Set());
|
||||
const persistedColumnOrderKeys = ref<string[]>([]);
|
||||
const persistedHiddenColumnKeys = ref<string[]>([...(toValue(options.initialHiddenColumnKeys) ?? [])]);
|
||||
const frozenColumnCount = ref(0);
|
||||
// 冻结选中列前的列序快照,取消冻结时还原
|
||||
const columnOrderSnapshotBeforeFreeze = ref<string[] | null>(null);
|
||||
let columnLayoutPersistTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
let columnLayoutPersistPending = false;
|
||||
let pendingColumnLayoutScopeKey = "";
|
||||
const orderedDisplayableColumnIndexes = computed(() => orderedColumnIndexes({ availableIndexes: toValue(options.displayableColumnIndexes), columnKeys: toValue(options.columnOrderKeys), orderedKeys: persistedColumnOrderKeys.value }));
|
||||
const visibleColumnIndexes = computed(() => visibleColumnIndexesForFilter(orderedDisplayableColumnIndexes.value, hiddenColumnIndexes.value));
|
||||
const displayableColumnCount = computed(() => toValue(options.displayableColumnIndexes).length);
|
||||
@@ -97,17 +106,77 @@ export function useDataGridColumnLayoutState(options: {
|
||||
const allNullColumnCount = computed(() => toValue(options.allNullColumnIndexes).length);
|
||||
const hasCustomColumnOrder = computed(() => !isDefaultColumnOrder(toValue(options.displayableColumnIndexes), orderedDisplayableColumnIndexes.value));
|
||||
const canToggleAllNullColumns = computed(() => nullColumnsHidden.value || (toValue(options.allNullColumnIndexes).length > 0 && displayableColumnCount.value > 1));
|
||||
const columnLookupItems = computed(() =>
|
||||
buildDataGridColumnLookupItems({
|
||||
columns: toValue(options.columns),
|
||||
sourceColumns: toValue(options.sourceColumns),
|
||||
displayableIndexes: toValue(options.displayableColumnIndexes),
|
||||
commentByColumn: toValue(options.commentByColumn),
|
||||
}),
|
||||
);
|
||||
const columnLookupItemByIndex = computed(() => new Map(columnLookupItems.value.map((item) => [item.index, item])));
|
||||
const orderedColumnLayoutOptions = computed<DataGridColumnLayoutOption[]>(() =>
|
||||
orderedDisplayableColumnIndexes.value.flatMap((columnIndex, displayPosition) => {
|
||||
const item = columnLookupItemByIndex.value.get(columnIndex);
|
||||
const key = toValue(options.columnOrderKeys)[columnIndex];
|
||||
if (!item || !key) return [];
|
||||
return [
|
||||
{
|
||||
...item,
|
||||
key,
|
||||
column: item.name,
|
||||
visible: !hiddenColumnIndexes.value.has(columnIndex),
|
||||
displayPosition,
|
||||
},
|
||||
];
|
||||
}),
|
||||
);
|
||||
|
||||
function filteredColumnVisibilityOptions(query: string) {
|
||||
const displayable = new Set(toValue(options.displayableColumnIndexes));
|
||||
return filterColumnVisibilityOptions(toValue(options.columns), query, { sourceColumns: toValue(options.sourceColumns), commentByColumn: toValue(options.commentByColumn) }).filter((option) => displayable.has(option.index));
|
||||
function filteredColumnLayoutOptions(query: string): DataGridColumnLayoutOption[] {
|
||||
return filterDataGridColumnLookupItems(orderedColumnLayoutOptions.value, query);
|
||||
}
|
||||
function isColumnVisible(columnIndex: number) {
|
||||
return !hiddenColumnIndexes.value.has(columnIndex);
|
||||
}
|
||||
function persistHiddenColumnKeys() {
|
||||
options.onHiddenColumnKeysChange?.(hiddenColumnKeysForIndexes(hiddenColumnIndexes.value, autoHiddenNullColumnIndexes.value, toValue(options.columnOrderKeys), toValue(options.displayableColumnIndexes)));
|
||||
|
||||
function flushPersistColumnLayout() {
|
||||
if (!columnLayoutPersistPending) return;
|
||||
if (columnLayoutPersistTimer !== undefined) clearTimeout(columnLayoutPersistTimer);
|
||||
columnLayoutPersistTimer = undefined;
|
||||
columnLayoutPersistPending = false;
|
||||
saveDataGridColumnLayout(pendingColumnLayoutScopeKey || toValue(options.layoutScopeKey), {
|
||||
orderKeys: persistedColumnOrderKeys.value,
|
||||
hiddenKeys: persistedHiddenColumnKeys.value,
|
||||
});
|
||||
}
|
||||
|
||||
function markColumnLayoutForPersistence() {
|
||||
columnLayoutPersistPending = true;
|
||||
pendingColumnLayoutScopeKey = toValue(options.layoutScopeKey);
|
||||
}
|
||||
|
||||
function schedulePersistColumnLayout() {
|
||||
markColumnLayoutForPersistence();
|
||||
if (columnLayoutPersistTimer !== undefined) clearTimeout(columnLayoutPersistTimer);
|
||||
columnLayoutPersistTimer = setTimeout(flushPersistColumnLayout, 100);
|
||||
}
|
||||
|
||||
function persistColumnLayoutImmediately() {
|
||||
markColumnLayoutForPersistence();
|
||||
flushPersistColumnLayout();
|
||||
}
|
||||
|
||||
function currentManualHiddenColumnKeys() {
|
||||
return hiddenColumnKeysForIndexes(hiddenColumnIndexes.value, autoHiddenNullColumnIndexes.value, toValue(options.columnOrderKeys), toValue(options.displayableColumnIndexes));
|
||||
}
|
||||
|
||||
function persistHiddenColumnKeys() {
|
||||
const currentKeys = new Set(toValue(options.displayableColumnIndexes).flatMap((index) => toValue(options.columnOrderKeys)[index] ?? []));
|
||||
const unavailableHiddenKeys = persistedHiddenColumnKeys.value.filter((key) => !currentKeys.has(key));
|
||||
persistedHiddenColumnKeys.value = [...new Set([...unavailableHiddenKeys, ...currentManualHiddenColumnKeys()])];
|
||||
schedulePersistColumnLayout();
|
||||
}
|
||||
|
||||
function toggleColumnVisibility(columnIndex: number) {
|
||||
hiddenColumnIndexes.value = nextHiddenColumnIndexes({ columnIndex, hiddenIndexes: hiddenColumnIndexes.value, totalColumns: displayableColumnCount.value });
|
||||
if (!hiddenColumnIndexes.value.has(columnIndex) && autoHiddenNullColumnIndexes.value.delete(columnIndex)) {
|
||||
@@ -115,16 +184,20 @@ export function useDataGridColumnLayoutState(options: {
|
||||
}
|
||||
persistHiddenColumnKeys();
|
||||
}
|
||||
|
||||
function showAllColumns() {
|
||||
hiddenColumnIndexes.value = new Set();
|
||||
autoHiddenNullColumnIndexes.value = new Set();
|
||||
persistHiddenColumnKeys();
|
||||
persistedHiddenColumnKeys.value = [];
|
||||
schedulePersistColumnLayout();
|
||||
}
|
||||
|
||||
function invertColumnVisibility() {
|
||||
hiddenColumnIndexes.value = invertedHiddenColumnIndexes([...toValue(options.displayableColumnIndexes)], hiddenColumnIndexes.value);
|
||||
autoHiddenNullColumnIndexes.value = new Set();
|
||||
persistHiddenColumnKeys();
|
||||
}
|
||||
|
||||
function showColumn(columnIndex: number) {
|
||||
if (!hiddenColumnIndexes.value.has(columnIndex)) return;
|
||||
hiddenColumnIndexes.value.delete(columnIndex);
|
||||
@@ -133,11 +206,18 @@ export function useDataGridColumnLayoutState(options: {
|
||||
autoHiddenNullColumnIndexes.value = new Set(autoHiddenNullColumnIndexes.value);
|
||||
persistHiddenColumnKeys();
|
||||
}
|
||||
function loadColumnOrder() {
|
||||
|
||||
function loadColumnLayout() {
|
||||
flushPersistColumnLayout();
|
||||
const storedLayout = loadDataGridColumnLayout(toValue(options.layoutScopeKey), toValue(options.columnOrderKeys));
|
||||
const tableScopeKey = toValue(options.tableScopeKey);
|
||||
const tableOrder = tableScopeKey ? loadTableDataGridColumnOrder(tableScopeKey) : [];
|
||||
persistedColumnOrderKeys.value = tableOrder.length ? tableOrder : loadDataGridColumnOrder(toValue(options.layoutScopeKey), toValue(options.columnOrderKeys));
|
||||
persistedColumnOrderKeys.value = tableOrder.length ? tableOrder : (storedLayout?.orderKeys ?? []);
|
||||
persistedHiddenColumnKeys.value = storedLayout?.hiddenKeys ?? [...(toValue(options.initialHiddenColumnKeys) ?? [])];
|
||||
resetColumnVisibility();
|
||||
if (!storedLayout && persistedHiddenColumnKeys.value.length > 0) schedulePersistColumnLayout();
|
||||
}
|
||||
|
||||
function loadFrozenColumnCount() {
|
||||
const state = loadDataGridColumnFrozenState(toValue(options.layoutScopeKey));
|
||||
frozenColumnCount.value = Math.min(state.frozenCount, visibleColumnIndexes.value.length);
|
||||
@@ -159,24 +239,21 @@ export function useDataGridColumnLayoutState(options: {
|
||||
if (selectedVisibleColIdxs.length === 0) return;
|
||||
const sorted = [...selectedVisibleColIdxs].sort((a, b) => a - b);
|
||||
const visibleIdxs = visibleColumnIndexes.value;
|
||||
// 获取选中列的 actualColIdx
|
||||
const selectedActualIdxs = sorted.map((vIdx) => visibleIdxs[vIdx]).filter((idx): idx is number => idx !== undefined);
|
||||
if (selectedActualIdxs.length === 0) return;
|
||||
const selectedSet = new Set(selectedActualIdxs);
|
||||
// 非选中列保持原序
|
||||
const currentOrder = orderedDisplayableColumnIndexes.value;
|
||||
const nonSelectedActualIdxs = currentOrder.filter((idx) => !selectedSet.has(idx));
|
||||
// 保存冻结前的列序快照(仅在首次冻结时保存,避免连续冻结覆盖快照)
|
||||
// 首次冻结时保留原序,连续冻结不能覆盖用户真正的起始顺序。
|
||||
if (columnOrderSnapshotBeforeFreeze.value === null) {
|
||||
columnOrderSnapshotBeforeFreeze.value = [...persistedColumnOrderKeys.value];
|
||||
}
|
||||
// 新列序:选中列在前 + 非选中列在后
|
||||
persistColumnOrder([...selectedActualIdxs, ...nonSelectedActualIdxs]);
|
||||
setFrozenColumnCount(selectedActualIdxs.length);
|
||||
}
|
||||
|
||||
function unfreezeAllColumns() {
|
||||
setFrozenColumnCount(0);
|
||||
// 还原冻结前的列序
|
||||
if (columnOrderSnapshotBeforeFreeze.value !== null) {
|
||||
const snapshot = columnOrderSnapshotBeforeFreeze.value;
|
||||
columnOrderSnapshotBeforeFreeze.value = null;
|
||||
@@ -184,7 +261,7 @@ export function useDataGridColumnLayoutState(options: {
|
||||
resetColumnOrder();
|
||||
} else {
|
||||
persistedColumnOrderKeys.value = snapshot;
|
||||
saveDataGridColumnOrder(toValue(options.layoutScopeKey), toValue(options.columnOrderKeys), snapshot);
|
||||
persistColumnLayoutImmediately();
|
||||
const tableScopeKey = toValue(options.tableScopeKey);
|
||||
if (tableScopeKey) {
|
||||
saveTableDataGridColumnOrder(tableScopeKey, snapshot);
|
||||
@@ -193,35 +270,48 @@ export function useDataGridColumnLayoutState(options: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function persistColumnOrder(indexes: number[]) {
|
||||
const tableScopeKey = toValue(options.tableScopeKey);
|
||||
if (isDefaultColumnOrder(toValue(options.displayableColumnIndexes), indexes)) {
|
||||
removeDataGridColumnOrder(toValue(options.layoutScopeKey));
|
||||
persistedColumnOrderKeys.value = [];
|
||||
persistColumnLayoutImmediately();
|
||||
if (tableScopeKey) {
|
||||
removeTableDataGridColumnOrder(tableScopeKey);
|
||||
notifyTableDataGridColumnOrderChanged(tableScopeKey);
|
||||
}
|
||||
persistedColumnOrderKeys.value = [];
|
||||
return;
|
||||
}
|
||||
const keys = columnOrderKeysForIndexes(indexes, toValue(options.columnOrderKeys));
|
||||
const currentKeys = columnOrderKeysForIndexes(indexes, toValue(options.columnOrderKeys));
|
||||
const keys = mergeUnavailableColumnOrderKeys(currentKeys, persistedColumnOrderKeys.value);
|
||||
persistedColumnOrderKeys.value = keys;
|
||||
saveDataGridColumnOrder(toValue(options.layoutScopeKey), toValue(options.columnOrderKeys), keys);
|
||||
persistColumnLayoutImmediately();
|
||||
if (tableScopeKey) {
|
||||
saveTableDataGridColumnOrder(tableScopeKey, keys);
|
||||
notifyTableDataGridColumnOrderChanged(tableScopeKey);
|
||||
}
|
||||
}
|
||||
|
||||
function moveDisplayableColumn(fromDisplayableIndex: number, toDisplayableIndex: number) {
|
||||
const next = moveDisplayableColumnIndex({
|
||||
orderedIndexes: orderedDisplayableColumnIndexes.value,
|
||||
fromDisplayableIndex,
|
||||
toDisplayableIndex,
|
||||
});
|
||||
persistColumnOrder(next);
|
||||
}
|
||||
|
||||
function resetColumnOrder() {
|
||||
removeDataGridColumnOrder(toValue(options.layoutScopeKey));
|
||||
persistedColumnOrderKeys.value = [];
|
||||
persistColumnLayoutImmediately();
|
||||
const tableScopeKey = toValue(options.tableScopeKey);
|
||||
if (tableScopeKey) {
|
||||
removeTableDataGridColumnOrder(tableScopeKey);
|
||||
notifyTableDataGridColumnOrderChanged(tableScopeKey);
|
||||
}
|
||||
persistedColumnOrderKeys.value = [];
|
||||
if (options.onRefreshMetrics) nextTick(options.onRefreshMetrics);
|
||||
}
|
||||
|
||||
function setNullColumnsHidden(value: boolean) {
|
||||
if (options.hideNullColumns === undefined) localNullColumnsHidden.value = value;
|
||||
else options.onHideNullColumnsChange?.(value);
|
||||
@@ -250,16 +340,17 @@ export function useDataGridColumnLayoutState(options: {
|
||||
if (!(event instanceof CustomEvent)) return;
|
||||
const detail = event.detail as TableDataGridColumnOrderChangedDetail | undefined;
|
||||
if (!detail || detail.scopeKey !== toValue(options.tableScopeKey)) return;
|
||||
loadColumnOrder();
|
||||
persistedColumnOrderKeys.value = loadTableDataGridColumnOrder(detail.scopeKey);
|
||||
if (options.onRefreshMetrics) nextTick(options.onRefreshMetrics);
|
||||
}
|
||||
|
||||
function resetColumnVisibility(hiddenColumnKeys: readonly string[] = []) {
|
||||
function resetColumnVisibility(hiddenColumnKeys: readonly string[] = persistedHiddenColumnKeys.value) {
|
||||
hiddenColumnIndexes.value = hiddenColumnIndexesForKeys(hiddenColumnKeys, toValue(options.columnOrderKeys), toValue(options.displayableColumnIndexes));
|
||||
autoHiddenNullColumnIndexes.value = new Set();
|
||||
applyNullColumnVisibility(nullColumnsHidden.value);
|
||||
}
|
||||
|
||||
onScopeDispose(flushPersistColumnLayout);
|
||||
watch([() => nullColumnsHidden.value, () => [...toValue(options.allNullColumnIndexes)], () => [...toValue(options.displayableColumnIndexes)]], ([hidden]) => applyNullColumnVisibility(hidden as boolean), { immediate: true });
|
||||
watch(
|
||||
() => visibleColumnIndexes.value.length,
|
||||
@@ -271,11 +362,12 @@ export function useDataGridColumnLayoutState(options: {
|
||||
watch(
|
||||
[() => toValue(options.layoutScopeKey), () => toValue(options.tableScopeKey)],
|
||||
() => {
|
||||
loadColumnOrder();
|
||||
loadColumnLayout();
|
||||
loadFrozenColumnCount();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
watch([() => [...toValue(options.columnOrderKeys)], () => [...toValue(options.displayableColumnIndexes)]], () => resetColumnVisibility(), { flush: "sync" });
|
||||
|
||||
return {
|
||||
hiddenColumnIndexes,
|
||||
@@ -287,13 +379,15 @@ export function useDataGridColumnLayoutState(options: {
|
||||
allNullColumnCount,
|
||||
hasCustomColumnOrder,
|
||||
canToggleAllNullColumns,
|
||||
filteredColumnVisibilityOptions,
|
||||
orderedColumnLayoutOptions,
|
||||
filteredColumnLayoutOptions,
|
||||
isColumnVisible,
|
||||
toggleColumnVisibility,
|
||||
showAllColumns,
|
||||
invertColumnVisibility,
|
||||
showColumn,
|
||||
persistColumnOrder,
|
||||
moveDisplayableColumn,
|
||||
resetColumnOrder,
|
||||
toggleAllNullColumns,
|
||||
resetColumnVisibility,
|
||||
|
||||
Reference in new issue
Block a user