From 512ed5aa2a1357655b7fc6281a390a9682b7d518 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 3 Nov 2021 15:26:15 +0000 Subject: [PATCH] Add support for tables updating server-side sorting --- .../src/components/app/DataProvider.svelte | 68 +++++++++++++++---- .../src/components/app/table/Table.svelte | 15 +++- packages/client/src/constants.js | 1 + 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/packages/client/src/components/app/DataProvider.svelte b/packages/client/src/components/app/DataProvider.svelte index 54e758ad3c..a8e53f4906 100644 --- a/packages/client/src/components/app/DataProvider.svelte +++ b/packages/client/src/components/app/DataProvider.svelte @@ -35,28 +35,36 @@ let pageNumber = 0 let query = null + // Sorting can be overridden at run time, so we can't use the prop directly + let currentSortColumn = sortColumn + let currentSortOrder = sortOrder + $: query = buildLuceneQuery(filter) $: internalTable = dataSource?.type === "table" $: nestedProvider = dataSource?.type === "provider" $: hasNextPage = bookmarks[pageNumber + 1] != null $: hasPrevPage = pageNumber > 0 $: getSchema(dataSource) - $: sortType = getSortType(schema, sortColumn) + $: sortType = getSortType(schema, currentSortColumn) + + // Wait until schema loads before loading data, so that we can determine + // the correct sort type first time $: { - // Wait until schema loads before loading data, so that we can determine - // the correct sort type first time if (schemaLoaded) { fetchData( dataSource, + schema, query, limit, - sortColumn, - sortOrder, + currentSortColumn, + currentSortOrder, sortType, paginate ) } } + + // Reactively filter and sort rows if required $: { if (internalTable) { // Internal tables are already processed server-side @@ -65,10 +73,17 @@ // For anything else we use client-side implementations to filter, sort // and limit const filtered = luceneQuery(allRows, query) - const sorted = luceneSort(filtered, sortColumn, sortOrder, sortType) + const sorted = luceneSort( + filtered, + currentSortColumn, + currentSortOrder, + sortType + ) rows = luceneLimit(sorted, limit) } } + + // Build our action context $: actions = [ { type: ActionTypes.RefreshDatasource, @@ -79,7 +94,20 @@ type: ActionTypes.SetDataProviderQuery, callback: newQuery => (query = newQuery), }, + { + type: ActionTypes.SetDataProviderSorting, + callback: ({ column, order }) => { + if (column) { + currentSortColumn = column + } + if (order) { + currentSortOrder = order + } + }, + }, ] + + // Build our data context $: dataContext = { rows, schema, @@ -88,7 +116,11 @@ // Undocumented properties. These aren't supposed to be used in builder // bindings, but are used internally by other components id: $component?.id, - state: { query }, + state: { + query, + sortColumn: currentSortColumn, + sortOrder: currentSortOrder, + }, loaded, } @@ -104,10 +136,11 @@ if (schemaLoaded && !nestedProvider) { fetchData( dataSource, + schema, query, limit, - sortColumn, - sortOrder, + currentSortColumn, + currentSortOrder, sortType, paginate ) @@ -116,6 +149,7 @@ const fetchData = async ( dataSource, + schema, query, limit, sortColumn, @@ -125,12 +159,16 @@ ) => { loading = true if (dataSource?.type === "table") { + // Sanity check sort column, as using a non-existant column will prevent + // results coming back at all + const sort = schema?.[sortColumn] ? sortColumn : undefined + // For internal tables we use server-side processing const res = await API.searchTable({ tableId: dataSource.tableId, query, limit, - sort: sortColumn, + sort, sortOrder: sortOrder?.toLowerCase() ?? "ascending", sortType, paginate, @@ -181,13 +219,14 @@ if (!hasNextPage || !internalTable) { return } + const sort = schema?.[currentSortColumn] ? currentSortColumn : undefined const res = await API.searchTable({ tableId: dataSource?.tableId, query, bookmark: bookmarks[pageNumber + 1], limit, - sort: sortColumn, - sortOrder: sortOrder?.toLowerCase() ?? "ascending", + sort, + sortOrder: currentSortOrder?.toLowerCase() ?? "ascending", sortType, paginate: true, }) @@ -202,13 +241,14 @@ if (!hasPrevPage || !internalTable) { return } + const sort = schema?.[currentSortColumn] ? currentSortColumn : undefined const res = await API.searchTable({ tableId: dataSource?.tableId, query, bookmark: bookmarks[pageNumber - 1], limit, - sort: sortColumn, - sortOrder: sortOrder?.toLowerCase() ?? "ascending", + sort, + sortOrder: currentSortOrder?.toLowerCase() ?? "ascending", sortType, paginate: true, }) diff --git a/packages/client/src/components/app/table/Table.svelte b/packages/client/src/components/app/table/Table.svelte index ba9f3aae97..a6508c5763 100644 --- a/packages/client/src/components/app/table/Table.svelte +++ b/packages/client/src/components/app/table/Table.svelte @@ -11,7 +11,11 @@ export let size const component = getContext("component") - const { styleable } = getContext("sdk") + const { styleable, getAction, ActionTypes } = getContext("sdk") + const setSorting = getAction( + dataProvider?.id, + ActionTypes.SetDataProviderSorting + ) const customColumnKey = `custom-${Math.random()}` const customRenderers = [ { @@ -70,6 +74,13 @@ }) return newSchema } + + const onSort = e => { + setSorting({ + column: e.detail.column, + order: e.detail.order, + }) + }
@@ -84,6 +95,8 @@ allowEditRows={false} allowEditColumns={false} showAutoColumns={true} + disableSorting + on:sort={onSort} > diff --git a/packages/client/src/constants.js b/packages/client/src/constants.js index d2237ba3b9..c660d8d86c 100644 --- a/packages/client/src/constants.js +++ b/packages/client/src/constants.js @@ -6,6 +6,7 @@ export const ActionTypes = { ValidateForm: "ValidateForm", RefreshDatasource: "RefreshDatasource", SetDataProviderQuery: "SetDataProviderQuery", + SetDataProviderSorting: "SetDataProviderSorting", ClearForm: "ClearForm", ChangeFormStep: "ChangeFormStep", }