1
0
Fork 0
mirror of synced 2024-09-17 01:38:40 +12:00

Ensure all derived stores have default values

This commit is contained in:
Andrew Kingston 2023-03-11 19:20:38 +00:00
parent 38a3ef0c34
commit d7666272e0
9 changed files with 153 additions and 110 deletions

View file

@ -9,24 +9,32 @@ export const createColumnsStores = context => {
// Derive an enriched version of columns with left offsets and indexes // Derive an enriched version of columns with left offsets and indexes
// automatically calculated // automatically calculated
const enrichedColumns = derived(columns, $columns => { const enrichedColumns = derived(
let offset = 0 columns,
return $columns.map(column => { $columns => {
const enriched = { let offset = 0
...column, return $columns.map(column => {
left: offset, const enriched = {
} ...column,
if (column.visible) { left: offset,
offset += column.width }
} if (column.visible) {
return enriched offset += column.width
}) }
}) return enriched
})
},
[]
)
// Derived list of columns which have not been explicitly hidden // Derived list of columns which have not been explicitly hidden
const visibleColumns = derived(enrichedColumns, $columns => { const visibleColumns = derived(
return $columns.filter(col => col.visible) enrichedColumns,
}) $columns => {
return $columns.filter(col => col.visible)
},
[]
)
// Merge new schema fields with existing schema in order to preserve widths // Merge new schema fields with existing schema in order to preserve widths
schema.subscribe($schema => { schema.subscribe($schema => {

View file

@ -11,7 +11,11 @@ export const createReorderStores = context => {
sheetLeft: 0, sheetLeft: 0,
} }
const reorder = writable(reorderInitialState) 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 // Callback when dragging on a colum header and starting reordering
const startReordering = (column, e) => { const startReordering = (column, e) => {

View file

@ -14,7 +14,7 @@ export const createResizeStores = context => {
left: 0, left: 0,
} }
const resize = writable(initialState) 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 // Starts resizing a certain column
const startResizing = (column, e) => { const startResizing = (column, e) => {

View file

@ -18,21 +18,29 @@ export const createRowsStore = context => {
const sort = writable(initialSortState) const sort = writable(initialSortState)
// Enrich rows with an index property // Enrich rows with an index property
const enrichedRows = derived(rows, $rows => { const enrichedRows = derived(
return $rows.map((row, idx) => ({ rows,
...row, $rows => {
__idx: idx, return $rows.map((row, idx) => ({
})) ...row,
}) __idx: idx,
}))
},
[]
)
// Generate a lookup map to quick find a row by ID // Generate a lookup map to quick find a row by ID
const rowLookupMap = derived(enrichedRows, $rows => { const rowLookupMap = derived(
let map = {} enrichedRows,
for (let row of $rows) { $rows => {
map[row._id] = row.__idx let map = {}
} for (let row of $rows) {
return map map[row._id] = row.__idx
}) }
return map
},
{}
)
// Local cache of row IDs to speed up checking if a row exists // Local cache of row IDs to speed up checking if a row exists
let rowCacheMap = {} let rowCacheMap = {}

View file

@ -9,8 +9,8 @@ export const createScrollStores = context => {
}) })
// Memoize store primitives // Memoize store primitives
const scrollTop = derived(scroll, $scroll => $scroll.top) const scrollTop = derived(scroll, $scroll => $scroll.top, 0)
const scrollLeft = derived(scroll, $scroll => $scroll.left) const scrollLeft = derived(scroll, $scroll => $scroll.left, 0)
// Derive vertical limits // Derive vertical limits
const height = derived(bounds, $bounds => $bounds.height, 0) 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 { return {
scroll, scroll,
contentHeight, contentHeight,

View file

@ -14,7 +14,8 @@ export const createUIStores = context => {
const rowId = $selectedCellId?.split("-")[0] const rowId = $selectedCellId?.split("-")[0]
const index = $rowLookupMap[rowId] const index = $rowLookupMap[rowId]
return $rows[index] return $rows[index]
} },
null
) )
// Ensure we clear invalid rows from state if they disappear // Ensure we clear invalid rows from state if they disappear

View file

@ -5,50 +5,70 @@ export const createUserStores = () => {
const userId = writable(null) const userId = writable(null)
// Enrich users with unique colours // Enrich users with unique colours
const enrichedUsers = derived([users, userId], ([$users, $userId]) => { const enrichedUsers = derived(
return ( [users, userId],
$users ([$users, $userId]) => {
.slice() return (
// Place current user first $users
.sort((a, b) => { .slice()
if (a.id === $userId) { // Place current user first
return -1 .sort((a, b) => {
} else if (b.id === $userId) { if (a.id === $userId) {
return 1 return -1
} else { } else if (b.id === $userId) {
return 0 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}`
} }
} })
// 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 { // Generate friendly label
...user, let label = user.email
color, if (user.firstName) {
label, 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 updateUser = user => {
const $users = get(users) 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 { return {
users: { users: {
...enrichedUsers, ...enrichedUsers,

View file

@ -6,23 +6,32 @@ export const createViewportStores = context => {
const scrollLeft = derived(scroll, $scroll => $scroll.left, 0) const scrollLeft = derived(scroll, $scroll => $scroll.left, 0)
// Derive height and width as primitives to avoid wasted computation // Derive height and width as primitives to avoid wasted computation
const width = derived(bounds, $bounds => $bounds.width) const width = derived(bounds, $bounds => $bounds.width, 0)
const height = derived(bounds, $bounds => $bounds.height) const height = derived(bounds, $bounds => $bounds.height, 0)
// Derive visible rows // Derive visible rows
// Split into multiple stores containing primitives to optimise invalidation // Split into multiple stores containing primitives to optimise invalidation
// as mich as possible // as mich as possible
const firstRowIdx = derived(scrollTop, $scrollTop => { const firstRowIdx = derived(
return Math.floor($scrollTop / cellHeight) scrollTop,
}) $scrollTop => {
const renderedRowCount = derived(height, $height => { return Math.floor($scrollTop / cellHeight)
return Math.ceil($height / cellHeight) },
}) 0
)
const renderedRowCount = derived(
height,
$height => {
return Math.ceil($height / cellHeight)
},
0
)
const renderedRows = derived( const renderedRows = derived(
[rows, firstRowIdx, renderedRowCount], [rows, firstRowIdx, renderedRowCount],
([$rows, $firstRowIdx, $visibleRowCount]) => { ([$rows, $firstRowIdx, $visibleRowCount]) => {
return $rows.slice($firstRowIdx, $firstRowIdx + $visibleRowCount) return $rows.slice($firstRowIdx, $firstRowIdx + $visibleRowCount)
} },
[]
) )
// Derive visible columns // 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 } return { renderedRows, renderedColumns }
} }

View file

@ -419,6 +419,7 @@ export default class DataFetch {
if (state.loading || !this.options.paginate || !state.hasNextPage) { if (state.loading || !this.options.paginate || !state.hasNextPage) {
return return
} }
console.log("NEXT PAGE")
// Fetch next page // Fetch next page
const nextCursor = state.cursors[state.pageNumber + 1] const nextCursor = state.cursors[state.pageNumber + 1]