mirror of https://github.com/Budibase/budibase.git
2 changed files with 28 additions and 232 deletions
@ -1,209 +0,0 @@ |
|||
// Do not use any aliased imports in common files, as these will be bundled
|
|||
// by multiple bundlers which may not be able to resolve them.
|
|||
// This will eventually be replaced by the new client implementation when we
|
|||
// add a core package.
|
|||
import { writable, derived, get } from "svelte/store" |
|||
import { API } from "api" |
|||
import { LuceneUtils } from "@budibase/frontend-core" |
|||
|
|||
const defaultOptions = { |
|||
tableId: null, |
|||
filters: null, |
|||
limit: 10, |
|||
sortColumn: null, |
|||
sortOrder: "ascending", |
|||
paginate: true, |
|||
schema: null, |
|||
} |
|||
|
|||
export const fetchTableData = opts => { |
|||
// Save option set so we can override it later rather than relying on params
|
|||
let options = { |
|||
...defaultOptions, |
|||
...opts, |
|||
} |
|||
|
|||
// Local non-observable state
|
|||
let query |
|||
let sortType |
|||
let lastBookmark |
|||
|
|||
// Local observable state
|
|||
const store = writable({ |
|||
rows: [], |
|||
schema: null, |
|||
loading: false, |
|||
loaded: false, |
|||
bookmarks: [], |
|||
pageNumber: 0, |
|||
}) |
|||
|
|||
// Derive certain properties to return
|
|||
const derivedStore = derived(store, $store => { |
|||
return { |
|||
...$store, |
|||
hasNextPage: $store.bookmarks[$store.pageNumber + 1] != null, |
|||
hasPrevPage: $store.pageNumber > 0, |
|||
} |
|||
}) |
|||
|
|||
const fetchPage = async bookmark => { |
|||
lastBookmark = bookmark |
|||
const { tableId, limit, sortColumn, sortOrder, paginate } = options |
|||
return await API.searchTable({ |
|||
tableId, |
|||
query, |
|||
limit, |
|||
sort: sortColumn, |
|||
sortOrder: sortOrder?.toLowerCase() ?? "ascending", |
|||
sortType, |
|||
paginate, |
|||
bookmark, |
|||
}) |
|||
} |
|||
|
|||
// Fetches a fresh set of results from the server
|
|||
const fetchData = async () => { |
|||
const { tableId, schema, sortColumn, filters } = options |
|||
|
|||
// Ensure table ID exists
|
|||
if (!tableId) { |
|||
return |
|||
} |
|||
|
|||
// Get and enrich schema.
|
|||
// Ensure there are "name" properties for all fields and that field schema
|
|||
// are objects
|
|||
let enrichedSchema = schema |
|||
if (!enrichedSchema) { |
|||
const definition = await API.fetchTableDefinition(tableId) |
|||
enrichedSchema = definition?.schema ?? null |
|||
} |
|||
if (enrichedSchema) { |
|||
Object.entries(schema).forEach(([fieldName, fieldSchema]) => { |
|||
if (typeof fieldSchema === "string") { |
|||
enrichedSchema[fieldName] = { |
|||
type: fieldSchema, |
|||
name: fieldName, |
|||
} |
|||
} else { |
|||
enrichedSchema[fieldName] = { |
|||
...fieldSchema, |
|||
name: fieldName, |
|||
} |
|||
} |
|||
}) |
|||
|
|||
// Save fixed schema so we can provide it later
|
|||
options.schema = enrichedSchema |
|||
} |
|||
|
|||
// Ensure schema exists
|
|||
if (!schema) { |
|||
return |
|||
} |
|||
store.update($store => ({ ...$store, schema, loading: true })) |
|||
|
|||
// Work out what sort type to use
|
|||
if (!sortColumn || !schema[sortColumn]) { |
|||
sortType = "string" |
|||
} |
|||
const type = schema?.[sortColumn]?.type |
|||
sortType = type === "number" ? "number" : "string" |
|||
|
|||
// Build the lucene query
|
|||
query = LuceneUtils.buildLuceneQuery(filters) |
|||
|
|||
// Actually fetch data
|
|||
const page = await fetchPage() |
|||
store.update($store => ({ |
|||
...$store, |
|||
loading: false, |
|||
loaded: true, |
|||
pageNumber: 0, |
|||
rows: page.rows, |
|||
bookmarks: page.hasNextPage ? [null, page.bookmark] : [null], |
|||
})) |
|||
} |
|||
|
|||
// Fetches the next page of data
|
|||
const nextPage = async () => { |
|||
const state = get(derivedStore) |
|||
if (state.loading || !options.paginate || !state.hasNextPage) { |
|||
return |
|||
} |
|||
|
|||
// Fetch next page
|
|||
store.update($store => ({ ...$store, loading: true })) |
|||
const page = await fetchPage(state.bookmarks[state.pageNumber + 1]) |
|||
|
|||
// Update state
|
|||
store.update($store => { |
|||
let { bookmarks, pageNumber } = $store |
|||
if (page.hasNextPage) { |
|||
bookmarks[pageNumber + 2] = page.bookmark |
|||
} |
|||
return { |
|||
...$store, |
|||
pageNumber: pageNumber + 1, |
|||
rows: page.rows, |
|||
bookmarks, |
|||
loading: false, |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// Fetches the previous page of data
|
|||
const prevPage = async () => { |
|||
const state = get(derivedStore) |
|||
if (state.loading || !options.paginate || !state.hasPrevPage) { |
|||
return |
|||
} |
|||
|
|||
// Fetch previous page
|
|||
store.update($store => ({ ...$store, loading: true })) |
|||
const page = await fetchPage(state.bookmarks[state.pageNumber - 1]) |
|||
|
|||
// Update state
|
|||
store.update($store => { |
|||
return { |
|||
...$store, |
|||
pageNumber: $store.pageNumber - 1, |
|||
rows: page.rows, |
|||
loading: false, |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// Resets the data set and updates options
|
|||
const update = async newOptions => { |
|||
if (newOptions) { |
|||
options = { |
|||
...options, |
|||
...newOptions, |
|||
} |
|||
} |
|||
await fetchData() |
|||
} |
|||
|
|||
// Loads the same page again
|
|||
const refresh = async () => { |
|||
if (get(store).loading) { |
|||
return |
|||
} |
|||
const page = await fetchPage(lastBookmark) |
|||
store.update($store => ({ ...$store, rows: page.rows })) |
|||
} |
|||
|
|||
// Initially fetch data but don't bother waiting for the result
|
|||
fetchData() |
|||
|
|||
// Return our derived store which will be updated over time
|
|||
return { |
|||
subscribe: derivedStore.subscribe, |
|||
nextPage, |
|||
prevPage, |
|||
update, |
|||
refresh, |
|||
} |
|||
} |
|||
Loading…
Reference in new issue