Ensure all derived stores have default values
This commit is contained in:
parent
38a3ef0c34
commit
d7666272e0
|
@ -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 => {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in New Issue