From 724bff60f2bf2041f54c84edc6e63b414eae34ba Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 12 Apr 2023 14:56:22 +0100 Subject: [PATCH] Add persitence to column size and order in sheets --- .../src/components/sheet/stores/columns.js | 26 +++++++++++---- .../src/components/sheet/stores/reorder.js | 32 ++++++++++++++++--- .../src/components/sheet/stores/resize.js | 31 ++++++++++++++++-- .../src/components/sheet/stores/rows.js | 8 ++--- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/packages/frontend-core/src/components/sheet/stores/columns.js b/packages/frontend-core/src/components/sheet/stores/columns.js index 4516678ed1..d9c8d5c06a 100644 --- a/packages/frontend-core/src/components/sheet/stores/columns.js +++ b/packages/frontend-core/src/components/sheet/stores/columns.js @@ -12,10 +12,11 @@ export const createStores = () => { columns, $columns => { let offset = 0 - return $columns.map(column => { + return $columns.map((column, idx) => { const enriched = { ...column, left: offset, + order: idx, } if (column.visible) { offset += column.width @@ -85,15 +86,27 @@ export const deriveStores = context => { } return { name: field, - width: existing?.width || DefaultColumnWidth, + width: existing?.width || schema[field].width || DefaultColumnWidth, schema: schema[field], visible: existing?.visible ?? true, + order: schema[field].order, } }) .sort((a, b) => { - // Sort columns to put auto columns last - let autoColA = a.schema?.autocolumn - let autoColB = b.schema?.autocolumn + // Sort by order first + const orderA = a.order + const orderB = b.order + if (orderA != null && orderB != null) { + return orderA < orderB ? -1 : 1 + } else if (orderA != null) { + return -1 + } else if (orderB != null) { + return 1 + } + + // Then sort by auto columns + const autoColA = a.schema?.autocolumn + const autoColB = b.schema?.autocolumn if (autoColA === autoColB) { return 0 } @@ -115,7 +128,8 @@ export const deriveStores = context => { } stickyColumn.set({ name: primaryDisplay, - width: existing?.width || DefaultColumnWidth, + width: + existing?.width || schema[primaryDisplay].width || DefaultColumnWidth, left: gutterWidth, schema: schema[primaryDisplay], idx: "sticky", diff --git a/packages/frontend-core/src/components/sheet/stores/reorder.js b/packages/frontend-core/src/components/sheet/stores/reorder.js index 525a895063..297c6e40a4 100644 --- a/packages/frontend-core/src/components/sheet/stores/reorder.js +++ b/packages/frontend-core/src/components/sheet/stores/reorder.js @@ -1,4 +1,5 @@ import { get, writable, derived } from "svelte/store" +import { cloneDeep } from "lodash/fp" const reorderInitialState = { sourceColumn: null, @@ -23,7 +24,8 @@ export const createStores = () => { } export const deriveStores = context => { - const { reorder, columns, scroll, bounds, stickyColumn, ui } = context + const { reorder, columns, scroll, bounds, stickyColumn, ui, table, API } = + context // Callback when dragging on a colum header and starting reordering const startReordering = (column, e) => { @@ -88,10 +90,10 @@ export const deriveStores = context => { } // Callback when stopping reordering columns - const stopReordering = () => { + const stopReordering = async () => { // Swap position of columns let { sourceColumn, targetColumn } = get(reorder) - const $columns = get(columns) + let $columns = get(columns) let sourceIdx = $columns.findIndex(x => x.name === sourceColumn) let targetIdx = $columns.findIndex(x => x.name === targetColumn) targetIdx++ @@ -110,9 +112,12 @@ export const deriveStores = context => { // Remove event handlers document.removeEventListener("mousemove", onReorderMouseMove) document.removeEventListener("mouseup", stopReordering) + + // Persist changes + await saveOrderChanges() } - const moveColumnLeft = column => { + const moveColumnLeft = async column => { const $columns = get(columns) const sourceIdx = $columns.findIndex(x => x.name === column) if (sourceIdx === 0) { @@ -124,9 +129,12 @@ export const deriveStores = context => { state[sourceIdx - 1] = tmp return state.slice() }) + + // Persist changes + await saveOrderChanges() } - const moveColumnRight = column => { + const moveColumnRight = async column => { const $columns = get(columns) const sourceIdx = $columns.findIndex(x => x.name === column) if (sourceIdx === $columns.length - 1) { @@ -138,6 +146,20 @@ export const deriveStores = context => { state[sourceIdx + 1] = tmp return state.slice() }) + + // Persist changes + await saveOrderChanges() + } + + // Saves order changes as part of table metadata + const saveOrderChanges = async () => { + const $table = cloneDeep(get(table)) + const $columns = get(columns) + $columns.forEach(column => { + $table.schema[column.name].order = column.order + }) + const newTable = await API.saveTable($table) + table.set(newTable) } return { diff --git a/packages/frontend-core/src/components/sheet/stores/resize.js b/packages/frontend-core/src/components/sheet/stores/resize.js index 5e3ec4a0e8..dab52a2e78 100644 --- a/packages/frontend-core/src/components/sheet/stores/resize.js +++ b/packages/frontend-core/src/components/sheet/stores/resize.js @@ -1,5 +1,6 @@ import { writable, get, derived } from "svelte/store" import { DefaultColumnWidth } from "./columns" +import { cloneDeep } from "lodash/fp" export const MinColumnWidth = 100 @@ -22,7 +23,7 @@ export const createStores = () => { } export const deriveStores = context => { - const { resize, columns, stickyColumn, ui } = context + const { resize, columns, stickyColumn, ui, table, API, rows } = context // Starts resizing a certain column const startResizing = (column, e) => { @@ -83,14 +84,21 @@ export const deriveStores = context => { } // Stop resizing any columns - const stopResizing = () => { + const stopResizing = async () => { + // Reset state + const $resize = get(resize) resize.set(initialState) document.removeEventListener("mousemove", onResizeMouseMove) document.removeEventListener("mouseup", stopResizing) + + // Persist width if it changed + if ($resize.width !== $resize.initialWidth) { + await saveNewColumnWidth($resize.column, $resize.width) + } } // Resets a column size back to default - const resetSize = column => { + const resetSize = async column => { let columnIdx = get(columns).findIndex(col => col.name === column.name) if (columnIdx === -1) { stickyColumn.update(state => ({ @@ -103,6 +111,23 @@ export const deriveStores = context => { return [...state] }) } + await saveNewColumnWidth(column.name, DefaultColumnWidth) + } + + // Saves a new column width as part of table metadata + const saveNewColumnWidth = async (columnName, width) => { + const $table = get(table) + const newDefinition = await API.saveTable({ + ...$table, + schema: { + ...$table.schema, + [columnName]: { + ...$table.schema[columnName], + width, + }, + }, + }) + table.set(newDefinition) } return { diff --git a/packages/frontend-core/src/components/sheet/stores/rows.js b/packages/frontend-core/src/components/sheet/stores/rows.js index f5a961fe3d..27304ec996 100644 --- a/packages/frontend-core/src/components/sheet/stores/rows.js +++ b/packages/frontend-core/src/components/sheet/stores/rows.js @@ -115,6 +115,8 @@ export const deriveStores = context => { // Reset scroll state when data changes if (!get(instanceLoaded)) { + table.set($fetch.definition) + // Reset both top and left for a new table ID instanceLoaded.set(true) scroll.set({ top: 0, left: 0 }) @@ -123,9 +125,6 @@ export const deriveStores = context => { scroll.update(state => ({ ...state, top: 0 })) } - // Update table definition - table.set($fetch.definition) - // Process new rows handleNewRows($fetch.rows, resetRows) @@ -385,7 +384,8 @@ export const deriveStores = context => { // Refreshes the schema of the data fetch subscription const refreshTableDefinition = async () => { - return await get(fetch)?.refreshDefinition() + const definition = await API.fetchTableDefinition(get(tableId)) + table.set(definition) } // Checks if we have a row with a certain ID