From f8087f0fb3cc78f9846040d0a78dfbcce07930a0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 17 Apr 2024 11:45:54 +0100 Subject: [PATCH] Automatically unpin the grid sticky column when available space is restricted --- .../src/components/grid/cells/GridCell.svelte | 3 + .../grid/controls/HideColumnsButton.svelte | 1 + .../grid/overlays/ResizeOverlay.svelte | 1 + .../src/components/grid/stores/columns.js | 64 +++++++++++++------ .../src/components/grid/stores/reorder.js | 19 +++--- .../src/components/grid/stores/ui.js | 2 +- 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/packages/frontend-core/src/components/grid/cells/GridCell.svelte b/packages/frontend-core/src/components/grid/cells/GridCell.svelte index 74d98ec130..32a9dea83b 100644 --- a/packages/frontend-core/src/components/grid/cells/GridCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/GridCell.svelte @@ -43,6 +43,9 @@ on:mouseup on:click on:contextmenu + on:touchstart + on:touchend + on:touchcancel {style} > {#if error} diff --git a/packages/frontend-core/src/components/grid/controls/HideColumnsButton.svelte b/packages/frontend-core/src/components/grid/controls/HideColumnsButton.svelte index 01c9dc648b..4e19e64297 100644 --- a/packages/frontend-core/src/components/grid/controls/HideColumnsButton.svelte +++ b/packages/frontend-core/src/components/grid/controls/HideColumnsButton.svelte @@ -81,6 +81,7 @@ size="S" value={column.visible} on:change={e => toggleVisibility(column, e.detail)} + disabled={column.primaryDisplay} /> {/each} diff --git a/packages/frontend-core/src/components/grid/overlays/ResizeOverlay.svelte b/packages/frontend-core/src/components/grid/overlays/ResizeOverlay.svelte index 1140962583..e96517a434 100644 --- a/packages/frontend-core/src/components/grid/overlays/ResizeOverlay.svelte +++ b/packages/frontend-core/src/components/grid/overlays/ResizeOverlay.svelte @@ -21,6 +21,7 @@ class="resize-slider" class:visible={activeColumn === $stickyColumn.name} on:mousedown={e => resize.actions.startResizing($stickyColumn, e)} + on:touchstart={e => resize.actions.startResizing($stickyColumn, e)} on:dblclick={() => resize.actions.resetSize($stickyColumn)} style="left:{GutterWidth + $stickyColumn.width}px;" > diff --git a/packages/frontend-core/src/components/grid/stores/columns.js b/packages/frontend-core/src/components/grid/stores/columns.js index 31638e7c79..8ceaae105f 100644 --- a/packages/frontend-core/src/components/grid/stores/columns.js +++ b/packages/frontend-core/src/components/grid/stores/columns.js @@ -48,22 +48,28 @@ export const createStores = () => { export const deriveStores = context => { const { columns, stickyColumn } = context - // Derive if we have any normal columns - const hasNonAutoColumn = derived( + // Quick access to all columns + const allColumns = derived( [columns, stickyColumn], ([$columns, $stickyColumn]) => { let allCols = $columns || [] if ($stickyColumn) { allCols = [...allCols, $stickyColumn] } - const normalCols = allCols.filter(column => { - return !column.schema?.autocolumn - }) - return normalCols.length > 0 + return allCols } ) + // Derive if we have any normal columns + const hasNonAutoColumn = derived(allColumns, $allColumns => { + const normalCols = $allColumns.filter(column => { + return !column.schema?.autocolumn + }) + return normalCols.length > 0 + }) + return { + allColumns, hasNonAutoColumn, } } @@ -142,24 +148,26 @@ export const createActions = context => { } export const initialise = context => { - const { definition, columns, stickyColumn, enrichedSchema } = context + const { + definition, + columns, + stickyColumn, + allColumns, + enrichedSchema, + compact, + } = context // Merge new schema fields with existing schema in order to preserve widths - enrichedSchema.subscribe($enrichedSchema => { + const processColumns = $enrichedSchema => { if (!$enrichedSchema) { columns.set([]) stickyColumn.set(null) return } const $definition = get(definition) - const $columns = get(columns) + const $allColumns = get(allColumns) const $stickyColumn = get(stickyColumn) - - // Generate array of all columns to easily find pre-existing columns - let allColumns = $columns || [] - if ($stickyColumn) { - allColumns.push($stickyColumn) - } + const $compact = get(compact) // Find primary display let primaryDisplay @@ -171,7 +179,7 @@ export const initialise = context => { // Get field list let fields = [] Object.keys($enrichedSchema).forEach(field => { - if (field !== primaryDisplay) { + if ($compact || field !== primaryDisplay) { fields.push(field) } }) @@ -181,7 +189,7 @@ export const initialise = context => { fields .map(field => { const fieldSchema = $enrichedSchema[field] - const oldColumn = allColumns?.find(x => x.name === field) + const oldColumn = $allColumns?.find(x => x.name === field) return { name: field, label: fieldSchema.displayName || field, @@ -189,9 +197,18 @@ export const initialise = context => { width: fieldSchema.width || oldColumn?.width || DefaultColumnWidth, visible: fieldSchema.visible ?? true, order: fieldSchema.order ?? oldColumn?.order, + primaryDisplay: field === primaryDisplay, } }) .sort((a, b) => { + // If we don't have a pinned column then primary display will be in + // the normal columns list, and should be first + if (a.name === primaryDisplay) { + return -1 + } else if (b.name === primaryDisplay) { + return 1 + } + // Sort by order first const orderA = a.order const orderB = b.order @@ -214,12 +231,12 @@ export const initialise = context => { ) // Update sticky column - if (!primaryDisplay) { + if ($compact || !primaryDisplay) { stickyColumn.set(null) return } const stickySchema = $enrichedSchema[primaryDisplay] - const oldStickyColumn = allColumns?.find(x => x.name === primaryDisplay) + const oldStickyColumn = $allColumns?.find(x => x.name === primaryDisplay) stickyColumn.set({ name: primaryDisplay, label: stickySchema.displayName || primaryDisplay, @@ -228,6 +245,13 @@ export const initialise = context => { visible: true, order: 0, left: GutterWidth, + primaryDisplay: true, }) - }) + } + + // Process columns when schema changes + enrichedSchema.subscribe(processColumns) + + // Process columns when compact flag changes + compact.subscribe(() => processColumns(get(enrichedSchema))) } diff --git a/packages/frontend-core/src/components/grid/stores/reorder.js b/packages/frontend-core/src/components/grid/stores/reorder.js index 7bf0423b23..30a5c144de 100644 --- a/packages/frontend-core/src/components/grid/stores/reorder.js +++ b/packages/frontend-core/src/components/grid/stores/reorder.js @@ -40,7 +40,6 @@ export const createActions = context => { // Callback when dragging on a colum header and starting reordering const startReordering = (column, e) => { - console.log("start", column) const $visibleColumns = get(visibleColumns) const $bounds = get(bounds) const $stickyColumn = get(stickyColumn) @@ -167,13 +166,6 @@ export const createActions = context => { // Ensure auto-scrolling is stopped stopAutoScroll() - // Swap position of columns - let { sourceColumn, targetColumn } = get(reorder) - moveColumn(sourceColumn, targetColumn) - - // Reset state - reorder.set(reorderInitialState) - // Remove event handlers document.removeEventListener("mousemove", onReorderMouseMove) document.removeEventListener("mouseup", stopReordering) @@ -181,8 +173,15 @@ export const createActions = context => { document.removeEventListener("touchend", stopReordering) document.removeEventListener("touchcancel", stopReordering) - // Save column changes - await columns.actions.saveChanges() + // Ensure there's actually a change + let { sourceColumn, targetColumn } = get(reorder) + if (sourceColumn !== targetColumn) { + moveColumn(sourceColumn, targetColumn) + await columns.actions.saveChanges() + } + + // Reset state + reorder.set(reorderInitialState) } // Moves a column after another columns. diff --git a/packages/frontend-core/src/components/grid/stores/ui.js b/packages/frontend-core/src/components/grid/stores/ui.js index da0558bb5b..928f93f3e1 100644 --- a/packages/frontend-core/src/components/grid/stores/ui.js +++ b/packages/frontend-core/src/components/grid/stores/ui.js @@ -98,7 +98,7 @@ export const deriveStores = context => { // Derive whether we should use the compact UI, depending on width const compact = derived([stickyColumn, width], ([$stickyColumn, $width]) => { - return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100 + return ($stickyColumn?.width || 0) + $width + GutterWidth < 800 }) return {