Refactor inline searching to be a separate concept from normal filters, and optimise API usage across all datasources

This commit is contained in:
Andrew Kingston 2023-10-13 19:06:53 +01:00
parent b337bd7435
commit e3d6a68ea1
7 changed files with 96 additions and 44 deletions

View File

@ -1,8 +1,9 @@
import { derived, get, writable } from "svelte/store" import { derived, get } from "svelte/store"
import { getDatasourceDefinition } from "../../../fetch" import { getDatasourceDefinition } from "../../../fetch"
import { memo } from "../../../utils"
export const createStores = () => { export const createStores = () => {
const definition = writable(null) const definition = memo(null)
return { return {
definition, definition,

View File

@ -66,6 +66,8 @@ export const initialise = context => {
datasource, datasource,
sort, sort,
filter, filter,
inlineFilters,
allFilters,
nonPlus, nonPlus,
initialFilter, initialFilter,
initialSortColumn, initialSortColumn,
@ -87,6 +89,7 @@ export const initialise = context => {
// Wipe state // Wipe state
filter.set(get(initialFilter)) filter.set(get(initialFilter))
inlineFilters.set([])
sort.set({ sort.set({
column: get(initialSortColumn), column: get(initialSortColumn),
order: get(initialSortOrder) || "ascending", order: get(initialSortOrder) || "ascending",
@ -94,14 +97,14 @@ export const initialise = context => {
// Update fetch when filter changes // Update fetch when filter changes
unsubscribers.push( unsubscribers.push(
filter.subscribe($filter => { allFilters.subscribe($allFilters => {
// Ensure we're updating the correct fetch // Ensure we're updating the correct fetch
const $fetch = get(fetch) const $fetch = get(fetch)
if (!isSameDatasource($fetch?.options?.datasource, $datasource)) { if (!isSameDatasource($fetch?.options?.datasource, $datasource)) {
return return
} }
$fetch.update({ $fetch.update({
filter: $filter, filter: $allFilters,
}) })
}) })
) )

View File

@ -71,6 +71,8 @@ export const initialise = context => {
datasource, datasource,
fetch, fetch,
filter, filter,
inlineFilters,
allFilters,
sort, sort,
table, table,
initialFilter, initialFilter,
@ -93,6 +95,7 @@ export const initialise = context => {
// Wipe state // Wipe state
filter.set(get(initialFilter)) filter.set(get(initialFilter))
inlineFilters.set([])
sort.set({ sort.set({
column: get(initialSortColumn), column: get(initialSortColumn),
order: get(initialSortOrder) || "ascending", order: get(initialSortOrder) || "ascending",
@ -100,14 +103,14 @@ export const initialise = context => {
// Update fetch when filter changes // Update fetch when filter changes
unsubscribers.push( unsubscribers.push(
filter.subscribe($filter => { allFilters.subscribe($allFilters => {
// Ensure we're updating the correct fetch // Ensure we're updating the correct fetch
const $fetch = get(fetch) const $fetch = get(fetch)
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) { if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
return return
} }
$fetch.update({ $fetch.update({
filter: $filter, filter: $allFilters,
}) })
}) })
) )

View File

@ -73,6 +73,8 @@ export const initialise = context => {
sort, sort,
rows, rows,
filter, filter,
inlineFilters,
allFilters,
subscribe, subscribe,
viewV2, viewV2,
initialFilter, initialFilter,
@ -97,6 +99,7 @@ export const initialise = context => {
// Reset state for new view // Reset state for new view
filter.set(get(initialFilter)) filter.set(get(initialFilter))
inlineFilters.set([])
sort.set({ sort.set({
column: get(initialSortColumn), column: get(initialSortColumn),
order: get(initialSortOrder) || "ascending", order: get(initialSortOrder) || "ascending",
@ -143,21 +146,19 @@ export const initialise = context => {
order: $sort.order || "ascending", order: $sort.order || "ascending",
}, },
}) })
await rows.actions.refreshData()
} }
} }
// Otherwise just update the fetch
else { // Also update the fetch to ensure the new sort is respected.
// Ensure we're updating the correct fetch // Ensure we're updating the correct fetch.
const $fetch = get(fetch) const $fetch = get(fetch)
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) { if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
return return
} }
$fetch.update({ $fetch.update({
sortOrder: $sort.order || "ascending", sortOrder: $sort.order,
sortColumn: $sort.column, sortColumn: $sort.column,
}) })
}
}) })
) )
@ -176,20 +177,25 @@ export const initialise = context => {
...$view, ...$view,
query: $filter, query: $filter,
}) })
await rows.actions.refreshData()
} }
} }
// Otherwise just update the fetch })
else { )
// Keep fetch up to date with filters.
// If we're able to save filters against the view then we only need to apply
// inline filters to the fetch, as saved filters are applied server side.
// If we can't save filters, then all filters must be applied to the fetch.
unsubscribers.push(
allFilters.subscribe($allFilters => {
// Ensure we're updating the correct fetch // Ensure we're updating the correct fetch
const $fetch = get(fetch) const $fetch = get(fetch)
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) { if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
return return
} }
$fetch.update({ $fetch.update({
filter: $filter, filter: $allFilters,
}) })
}
}) })
) )

View File

@ -1,4 +1,4 @@
import { writable, get } from "svelte/store" import { writable, get, derived } from "svelte/store"
import { FieldType } from "@budibase/types" import { FieldType } from "@budibase/types"
export const createStores = context => { export const createStores = context => {
@ -6,14 +6,31 @@ export const createStores = context => {
// Initialise to default props // Initialise to default props
const filter = writable(get(props).initialFilter) const filter = writable(get(props).initialFilter)
const inlineFilters = writable([])
return { return {
filter, filter,
inlineFilters,
}
}
export const deriveStores = context => {
const { filter, inlineFilters } = context
const allFilters = derived(
[filter, inlineFilters],
([$filter, $inlineFilters]) => {
return [...($filter || []), ...$inlineFilters]
}
)
return {
allFilters,
} }
} }
export const createActions = context => { export const createActions = context => {
const { filter } = context const { filter, inlineFilters } = context
const addInlineFilter = (column, value) => { const addInlineFilter = (column, value) => {
const filterId = `inline-${column.name}` const filterId = `inline-${column.name}`
@ -38,16 +55,15 @@ export const createActions = context => {
} }
// Add this filter // Add this filter
filter.update($filter => { inlineFilters.update($inlineFilters => {
// Remove any existing inline filter // Remove any existing inline filter for this column
if ($filter?.length) { $inlineFilters = $inlineFilters?.filter(x => x.id !== filterId)
$filter = $filter?.filter(x => x.id !== filterId)
}
// Add new one if a value exists // Add new one if a value exists
if (value) { if (value) {
$filter = [...($filter || []), inlineFilter] $inlineFilters.push(inlineFilter)
} }
return $filter return $inlineFilters
}) })
} }

View File

@ -68,7 +68,7 @@ export const createActions = context => {
rows, rows,
rowLookupMap, rowLookupMap,
definition, definition,
filter, allFilters,
loading, loading,
sort, sort,
datasource, datasource,
@ -111,7 +111,7 @@ export const createActions = context => {
// Tick to allow other reactive logic to update stores when datasource changes // Tick to allow other reactive logic to update stores when datasource changes
// before proceeding. This allows us to wipe filters etc if needed. // before proceeding. This allows us to wipe filters etc if needed.
await tick() await tick()
const $filter = get(filter) const $allFilters = get(allFilters)
const $sort = get(sort) const $sort = get(sort)
// Determine how many rows to fetch per page // Determine how many rows to fetch per page
@ -123,7 +123,7 @@ export const createActions = context => {
API, API,
datasource: $datasource, datasource: $datasource,
options: { options: {
filter: $filter, filter: $allFilters,
sortColumn: $sort.column, sortColumn: $sort.column,
sortOrder: $sort.order, sortOrder: $sort.order,
limit, limit,

View File

@ -35,9 +35,32 @@ export default class ViewV2Fetch extends DataFetch {
} }
async getData() { async getData() {
const { datasource, limit, sortColumn, sortOrder, sortType, paginate } = const {
this.options datasource,
const { cursor, query } = get(this.store) limit,
sortColumn,
sortOrder,
sortType,
paginate,
filter,
} = this.options
const { cursor, query, definition } = get(this.store)
// If sort params are not defined, update options to store the sorting
// params built in to this view. This ensures that we can accurately
// compare old and new sorting params and skip a redundant API call.
if (!sortColumn && definition.sort?.field) {
this.options.sortColumn = definition.sort.field
this.options.sortOrder = definition.sort.order
}
// If sort params are not defined, update options to store the sorting
// params built in to this view. This ensures that we can accurately
// compare old and new sorting params and skip a redundant API call.
if (!filter?.length && definition.query?.length) {
this.options.filter = definition.query
}
try { try {
const res = await this.API.viewV2.fetch({ const res = await this.API.viewV2.fetch({
viewId: datasource.id, viewId: datasource.id,