Skip to content

Commit f879a15

Browse files
committed
WIP: Shared table options
1 parent 4d5db9f commit f879a15

File tree

4 files changed

+293
-202
lines changed

4 files changed

+293
-202
lines changed

src/Exceptionless.Web/ClientApp/src/lib/features/projects/api.svelte.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export function getOrganizationProjectsQuery(request: GetOrganizationProjectsReq
271271

272272
return response;
273273
},
274-
queryKey: queryKeys.organization(request.route.organizationId)
274+
queryKey: [...queryKeys.organization(request.route.organizationId), { params: request.params }]
275275
}));
276276
}
277277

Lines changed: 18 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
1-
import type { FetchClientResponse } from '@exceptionless/fetchclient';
1+
import type { FetchClientResponse, ProblemDetails } from '@exceptionless/fetchclient';
2+
import type { CreateQueryResult } from '@tanstack/svelte-query';
23

34
import NumberFormatter from '$comp/formatters/number.svelte';
45
import ProjectActionsCell from '$features/projects/components/table/project-actions-cell.svelte';
56
import { ViewProject } from '$features/projects/models';
6-
import { DEFAULT_LIMIT } from '$shared/api/api.svelte';
7-
import {
8-
type ColumnDef,
9-
type ColumnSort,
10-
getCoreRowModel,
11-
type PaginationState,
12-
renderComponent,
13-
type RowSelectionState,
14-
type TableOptions,
15-
type Updater,
16-
type VisibilityState
17-
} from '@tanstack/svelte-table';
18-
import { PersistedState } from 'runed';
19-
import { untrack } from 'svelte';
7+
import { getSharedTableOptions } from '$features/shared/table.svelte';
8+
import { type ColumnDef, renderComponent, type TableOptions } from '@tanstack/svelte-table';
209

2110
import type { GetOrganizationProjectsParams, GetProjectsMode } from '../../api.svelte';
2211

@@ -69,164 +58,25 @@ export function getColumns<TProject extends ViewProject>(mode: GetProjectsMode =
6958
return columns;
7059
}
7160

72-
export function getTableContext<TProject extends ViewProject>(
73-
params: GetOrganizationProjectsParams,
61+
export function getTableOptions<TProject extends ViewProject>(
62+
queryParameters: GetOrganizationProjectsParams,
63+
queryResponse: CreateQueryResult<FetchClientResponse<TProject[]>, ProblemDetails>,
7464
configureOptions: (options: TableOptions<TProject>) => TableOptions<TProject> = (options) => options
7565
) {
76-
let _parameters = $state(params);
77-
let _pageCount = $state(0);
78-
let _columns = $state(getColumns<TProject>(untrack(() => _parameters.mode)));
79-
let _data = $state([] as TProject[]);
80-
let _loading = $state(false);
81-
let _meta = $state({} as FetchClientResponse<unknown>['meta']);
82-
83-
const [columnVisibility, setColumnVisibility] = createPersistedTableState('project-column-visibility', <VisibilityState>{});
84-
const [pagination, setPagination] = createTableState<PaginationState>({
85-
pageIndex: 0,
86-
pageSize: untrack(() => _parameters.limit) ?? DEFAULT_LIMIT
87-
});
88-
const [sorting, setSorting] = createTableState<ColumnSort[]>([
66+
return getSharedTableOptions<TProject>(
8967
{
90-
desc: true,
91-
id: 'name'
92-
}
93-
]);
94-
const [rowSelection, setRowSelection] = createTableState<RowSelectionState>({});
95-
const onPaginationChange = (updaterOrValue: Updater<PaginationState>) => {
96-
if (_loading) {
97-
return;
98-
}
99-
100-
_loading = true;
101-
setPagination(updaterOrValue);
102-
103-
const currentPageInfo = pagination();
104-
const nextLink = _meta.links?.next?.after as string;
105-
const previousLink = _meta.links?.previous?.before as string;
106-
107-
_parameters = {
108-
..._parameters,
109-
limit: currentPageInfo.pageSize,
110-
page: !nextLink && !previousLink && currentPageInfo.pageIndex !== 0 ? currentPageInfo.pageIndex + 1 : undefined
111-
};
112-
};
113-
114-
const onSortingChange = (updaterOrValue: Updater<ColumnSort[]>) => {
115-
setSorting(updaterOrValue);
116-
117-
_parameters = {
118-
..._parameters,
119-
page: undefined,
120-
sort:
121-
sorting().length > 0
122-
? sorting()
123-
.map((sort) => `${sort.desc ? '-' : ''}${sort.id}`)
124-
.join(',')
125-
: undefined
126-
};
127-
};
128-
129-
const options = configureOptions({
130-
get columns() {
131-
return _columns;
132-
},
133-
set columns(value) {
134-
_columns = value;
135-
},
136-
get data() {
137-
return _data;
138-
},
139-
set data(value) {
140-
_data = value;
141-
},
142-
enableMultiRowSelection: true,
143-
enableRowSelection: true,
144-
enableSortingRemoval: false,
145-
getCoreRowModel: getCoreRowModel(),
146-
getRowId: (originalRow) => originalRow.id,
147-
manualPagination: true,
148-
manualSorting: true,
149-
onColumnVisibilityChange: setColumnVisibility,
150-
onPaginationChange,
151-
onRowSelectionChange: setRowSelection,
152-
onSortingChange,
153-
get pageCount() {
154-
return _pageCount;
155-
},
156-
state: {
157-
get columnVisibility() {
158-
return columnVisibility();
68+
columnPersistenceKey: 'project',
69+
get columns() {
70+
return getColumns<TProject>(queryParameters.mode);
15971
},
160-
get pagination() {
161-
return pagination();
72+
paginationStrategy: 'offset',
73+
get queryParameters() {
74+
return queryParameters;
16275
},
163-
get rowSelection() {
164-
return rowSelection();
165-
},
166-
get sorting() {
167-
return sorting();
76+
get queryResponse() {
77+
return queryResponse.data;
16878
}
169-
}
170-
});
171-
172-
return {
173-
get data() {
174-
return _data;
175-
},
176-
set data(value) {
177-
_data = value;
17879
},
179-
get loading() {
180-
return _loading;
181-
},
182-
get meta() {
183-
return _meta;
184-
},
185-
set meta(value) {
186-
_meta = value;
187-
188-
const limit = _parameters.limit ?? DEFAULT_LIMIT;
189-
const total = (_meta?.total as number) ?? 0;
190-
_pageCount = Math.ceil(total / limit);
191-
192-
_loading = false;
193-
},
194-
options,
195-
get pageCount() {
196-
return _pageCount;
197-
},
198-
get parameters() {
199-
return _parameters;
200-
}
201-
};
202-
}
203-
204-
function createPersistedTableState<T>(key: string, initialValue: T): [() => T, (updater: Updater<T>) => void] {
205-
const persistedValue = new PersistedState<T>(key, initialValue);
206-
207-
return [
208-
() => persistedValue.current,
209-
(updater: Updater<T>) => {
210-
if (updater instanceof Function) {
211-
persistedValue.current = updater(persistedValue.current);
212-
} else {
213-
persistedValue.current = updater;
214-
}
215-
}
216-
];
217-
}
218-
219-
function createTableState<T>(initialValue: T): [() => T, (updater: Updater<T>) => void] {
220-
let value = $state(initialValue);
221-
222-
return [
223-
() => value,
224-
(updater: Updater<T>) => {
225-
if (updater instanceof Function) {
226-
value = updater(value);
227-
} else {
228-
value = updater;
229-
}
230-
}
231-
];
80+
configureOptions
81+
);
23282
}

0 commit comments

Comments
 (0)