From d7666272e0cfc9c4b58eb555bee34160a513050e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Sat, 11 Mar 2023 19:20:38 +0000 Subject: [PATCH] Ensure all derived stores have default values --- .../src/components/sheet/stores/columns.js | 40 +++--- .../src/components/sheet/stores/reorder.js | 6 +- .../src/components/sheet/stores/resize.js | 2 +- .../src/components/sheet/stores/rows.js | 34 +++-- .../src/components/sheet/stores/scroll.js | 21 +++- .../src/components/sheet/stores/ui.js | 3 +- .../src/components/sheet/stores/users.js | 119 +++++++++--------- .../src/components/sheet/stores/viewport.js | 37 +++--- packages/frontend-core/src/fetch/DataFetch.js | 1 + 9 files changed, 153 insertions(+), 110 deletions(-) diff --git a/packages/frontend-core/src/components/sheet/stores/columns.js b/packages/frontend-core/src/components/sheet/stores/columns.js index 95d1d618fe..ec169cb683 100644 --- a/packages/frontend-core/src/components/sheet/stores/columns.js +++ b/packages/frontend-core/src/components/sheet/stores/columns.js @@ -9,24 +9,32 @@ export const createColumnsStores = context => { // Derive an enriched version of columns with left offsets and indexes // automatically calculated - const enrichedColumns = derived(columns, $columns => { - let offset = 0 - return $columns.map(column => { - const enriched = { - ...column, - left: offset, - } - if (column.visible) { - offset += column.width - } - return enriched - }) - }) + const enrichedColumns = derived( + columns, + $columns => { + let offset = 0 + return $columns.map(column => { + const enriched = { + ...column, + left: offset, + } + if (column.visible) { + offset += column.width + } + return enriched + }) + }, + [] + ) // Derived list of columns which have not been explicitly hidden - const visibleColumns = derived(enrichedColumns, $columns => { - return $columns.filter(col => col.visible) - }) + const visibleColumns = derived( + enrichedColumns, + $columns => { + return $columns.filter(col => col.visible) + }, + [] + ) // Merge new schema fields with existing schema in order to preserve widths schema.subscribe($schema => { diff --git a/packages/frontend-core/src/components/sheet/stores/reorder.js b/packages/frontend-core/src/components/sheet/stores/reorder.js index 699ff0baff..243ab68e3c 100644 --- a/packages/frontend-core/src/components/sheet/stores/reorder.js +++ b/packages/frontend-core/src/components/sheet/stores/reorder.js @@ -11,7 +11,11 @@ export const createReorderStores = context => { sheetLeft: 0, } const reorder = writable(reorderInitialState) - const isReordering = derived(reorder, $reorder => !!$reorder.sourceColumn) + const isReordering = derived( + reorder, + $reorder => !!$reorder.sourceColumn, + false + ) // Callback when dragging on a colum header and starting reordering const startReordering = (column, e) => { diff --git a/packages/frontend-core/src/components/sheet/stores/resize.js b/packages/frontend-core/src/components/sheet/stores/resize.js index 0ef87c96b7..56a63f7bb3 100644 --- a/packages/frontend-core/src/components/sheet/stores/resize.js +++ b/packages/frontend-core/src/components/sheet/stores/resize.js @@ -14,7 +14,7 @@ export const createResizeStores = context => { left: 0, } const resize = writable(initialState) - const isResizing = derived(resize, $resize => $resize.column != null) + const isResizing = derived(resize, $resize => $resize.column != null, false) // Starts resizing a certain column const startResizing = (column, e) => { diff --git a/packages/frontend-core/src/components/sheet/stores/rows.js b/packages/frontend-core/src/components/sheet/stores/rows.js index 883dde78ec..958fd1e569 100644 --- a/packages/frontend-core/src/components/sheet/stores/rows.js +++ b/packages/frontend-core/src/components/sheet/stores/rows.js @@ -18,21 +18,29 @@ export const createRowsStore = context => { const sort = writable(initialSortState) // Enrich rows with an index property - const enrichedRows = derived(rows, $rows => { - return $rows.map((row, idx) => ({ - ...row, - __idx: idx, - })) - }) + const enrichedRows = derived( + rows, + $rows => { + return $rows.map((row, idx) => ({ + ...row, + __idx: idx, + })) + }, + [] + ) // Generate a lookup map to quick find a row by ID - const rowLookupMap = derived(enrichedRows, $rows => { - let map = {} - for (let row of $rows) { - map[row._id] = row.__idx - } - return map - }) + const rowLookupMap = derived( + enrichedRows, + $rows => { + let map = {} + for (let row of $rows) { + map[row._id] = row.__idx + } + return map + }, + {} + ) // Local cache of row IDs to speed up checking if a row exists let rowCacheMap = {} diff --git a/packages/frontend-core/src/components/sheet/stores/scroll.js b/packages/frontend-core/src/components/sheet/stores/scroll.js index 599f16770b..fa88ac46b4 100644 --- a/packages/frontend-core/src/components/sheet/stores/scroll.js +++ b/packages/frontend-core/src/components/sheet/stores/scroll.js @@ -9,8 +9,8 @@ export const createScrollStores = context => { }) // Memoize store primitives - const scrollTop = derived(scroll, $scroll => $scroll.top) - const scrollLeft = derived(scroll, $scroll => $scroll.left) + const scrollTop = derived(scroll, $scroll => $scroll.top, 0) + const scrollLeft = derived(scroll, $scroll => $scroll.left, 0) // Derive vertical limits const height = derived(bounds, $bounds => $bounds.height, 0) @@ -80,6 +80,23 @@ export const createScrollStores = context => { } }) + // Fetch next page when fewer than 50 scrollable rows remaining + const scrollableRows = derived( + [scrollTop, maxScrollTop], + ([$scrollTop, $maxScrollTop]) => { + if (!$maxScrollTop) { + return 100 + } + return ($maxScrollTop - $scrollTop) / cellHeight + }, + 100 + ) + scrollableRows.subscribe(count => { + if (count < 25) { + rows.actions.loadNextPage() + } + }) + return { scroll, contentHeight, diff --git a/packages/frontend-core/src/components/sheet/stores/ui.js b/packages/frontend-core/src/components/sheet/stores/ui.js index 1a90dd75ad..895fe60d12 100644 --- a/packages/frontend-core/src/components/sheet/stores/ui.js +++ b/packages/frontend-core/src/components/sheet/stores/ui.js @@ -14,7 +14,8 @@ export const createUIStores = context => { const rowId = $selectedCellId?.split("-")[0] const index = $rowLookupMap[rowId] return $rows[index] - } + }, + null ) // Ensure we clear invalid rows from state if they disappear diff --git a/packages/frontend-core/src/components/sheet/stores/users.js b/packages/frontend-core/src/components/sheet/stores/users.js index a52ef2b00d..c9a2e13453 100644 --- a/packages/frontend-core/src/components/sheet/stores/users.js +++ b/packages/frontend-core/src/components/sheet/stores/users.js @@ -5,50 +5,70 @@ export const createUserStores = () => { const userId = writable(null) // Enrich users with unique colours - const enrichedUsers = derived([users, userId], ([$users, $userId]) => { - return ( - $users - .slice() - // Place current user first - .sort((a, b) => { - if (a.id === $userId) { - return -1 - } else if (b.id === $userId) { - return 1 - } else { - return 0 - } - }) - // Enrich users with colors - .map((user, idx) => { - // Generate random colour hue - let hue = 1 - for (let i = 0; i < user.email.length && i < 5; i++) { - hue *= user.email.charCodeAt(i) - } - hue = hue % 360 - const color = - idx === 0 - ? "var(--spectrum-global-color-blue-400)" - : `hsl(${hue}, 50%, 40%)` - - // Generate friendly label - let label = user.email - if (user.firstName) { - label = user.firstName - if (user.lastName) { - label += ` ${user.lastName}` + const enrichedUsers = derived( + [users, userId], + ([$users, $userId]) => { + return ( + $users + .slice() + // Place current user first + .sort((a, b) => { + if (a.id === $userId) { + return -1 + } else if (b.id === $userId) { + return 1 + } else { + return 0 } - } + }) + // Enrich users with colors + .map((user, idx) => { + // Generate random colour hue + let hue = 1 + for (let i = 0; i < user.email.length && i < 5; i++) { + hue *= user.email.charCodeAt(i) + } + hue = hue % 360 + const color = + idx === 0 + ? "var(--spectrum-global-color-blue-400)" + : `hsl(${hue}, 50%, 40%)` - return { - ...user, - color, - label, - } - }) - ) - }) + // Generate friendly label + let label = user.email + if (user.firstName) { + label = user.firstName + if (user.lastName) { + label += ` ${user.lastName}` + } + } + + return { + ...user, + color, + label, + } + }) + ) + }, + [] + ) + + // Generate a lookup map of cell ID to the user that has it selected, to make + // lookups inside sheet cells extremely fast + const selectedCellMap = derived( + [enrichedUsers, userId], + ([$enrichedUsers, $userId]) => { + let map = {} + $enrichedUsers.forEach(user => { + if (user.selectedCellId && user.id !== $userId) { + map[user.selectedCellId] = user + } + }) + return map + }, + {} + ) const updateUser = user => { const $users = get(users) @@ -69,21 +89,6 @@ export const createUserStores = () => { }) } - // Generate a lookup map of cell ID to the user that has it selected, to make - // lookups inside sheet cells extremely fast - const selectedCellMap = derived( - [enrichedUsers, userId], - ([$enrichedUsers, $userId]) => { - let map = {} - $enrichedUsers.forEach(user => { - if (user.selectedCellId && user.id !== $userId) { - map[user.selectedCellId] = user - } - }) - return map - } - ) - return { users: { ...enrichedUsers, diff --git a/packages/frontend-core/src/components/sheet/stores/viewport.js b/packages/frontend-core/src/components/sheet/stores/viewport.js index f47e8e0ee0..79a075dee9 100644 --- a/packages/frontend-core/src/components/sheet/stores/viewport.js +++ b/packages/frontend-core/src/components/sheet/stores/viewport.js @@ -6,23 +6,32 @@ export const createViewportStores = context => { const scrollLeft = derived(scroll, $scroll => $scroll.left, 0) // Derive height and width as primitives to avoid wasted computation - const width = derived(bounds, $bounds => $bounds.width) - const height = derived(bounds, $bounds => $bounds.height) + const width = derived(bounds, $bounds => $bounds.width, 0) + const height = derived(bounds, $bounds => $bounds.height, 0) // Derive visible rows // Split into multiple stores containing primitives to optimise invalidation // as mich as possible - const firstRowIdx = derived(scrollTop, $scrollTop => { - return Math.floor($scrollTop / cellHeight) - }) - const renderedRowCount = derived(height, $height => { - return Math.ceil($height / cellHeight) - }) + const firstRowIdx = derived( + scrollTop, + $scrollTop => { + return Math.floor($scrollTop / cellHeight) + }, + 0 + ) + const renderedRowCount = derived( + height, + $height => { + return Math.ceil($height / cellHeight) + }, + 0 + ) const renderedRows = derived( [rows, firstRowIdx, renderedRowCount], ([$rows, $firstRowIdx, $visibleRowCount]) => { return $rows.slice($firstRowIdx, $firstRowIdx + $visibleRowCount) - } + }, + [] ) // Derive visible columns @@ -65,15 +74,5 @@ export const createViewportStores = context => { [] ) - // Fetch next page when approaching end of data - renderedRows.subscribe($renderedRows => { - const lastVisible = $renderedRows[$renderedRows.length - 1] - const $rows = get(rows) - const lastRow = $rows[$rows.length - 1] - if (lastVisible && lastRow && lastVisible._id === lastRow._id) { - rows.actions.loadNextPage() - } - }) - return { renderedRows, renderedColumns } } diff --git a/packages/frontend-core/src/fetch/DataFetch.js b/packages/frontend-core/src/fetch/DataFetch.js index f7afa3e911..6bf453a6dd 100644 --- a/packages/frontend-core/src/fetch/DataFetch.js +++ b/packages/frontend-core/src/fetch/DataFetch.js @@ -419,6 +419,7 @@ export default class DataFetch { if (state.loading || !this.options.paginate || !state.hasNextPage) { return } + console.log("NEXT PAGE") // Fetch next page const nextCursor = state.cursors[state.pageNumber + 1]