Repository navigation
feat(api): add chartsTable with filters, sorting and pagination - #262
Merged
Merged
Conversation
The charts dashboard loads every built chart and chart image through getChartData and searches them in the browser. chartsTable returns one page of both kinds in a single list, with the total count and per-status counts, using the shared table helpers. Both tables are merged in one SQL UNION, so counting, sorting and slicing happen in the database; only the rows of the page are then loaded. Visibility and permission are the same as getChartData. Rows keep their types (TypeResourceChart, TypeResourceChartImage), so existing fragments work unchanged. getChartData is untouched.
Sorting and paging now go through the same helper as the other table queries. Only filtering stays per table, because Django cannot filter after a UNION. Drops the extra id tie-breaker, matching the others.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backend for "Charts Listing API pagination and filters" (https://github.com/CivicDataLab/DataSpace/issues/329), part of https://github.com/CivicDataLab/DataSpace/issues/277.
Adds
chartsTablefor the charts dashboard, built the same way asdatasetsTable(#215) and the use case, collaborative, AI model and publication tables (#254).The existing
getChartDataquery is untouched, so nothing that runs today changes.What you get in one call
A page of rows, the total count, and the per-status numbers for the tabs:
Built charts and uploaded chart images come back in one list, as on the page today.
Rows keep their types,
TypeResourceChartandTypeResourceChartImage(the same uniongetChartDatareturns), so the page's existing fragments, the click-through to the right editor and the delete / unpublish buttons work unchanged:Mapping the table UI
namewithicontainsstatusfilter:DRAFT/PUBLISHED. Numbers for the tab labels come fromstatusCounts; an All tab is their sumdatasetwith the dataset idchart_type=BAR/LINE/BIG_NUMBER. Map:chart_typeinPOLYGON_MAP,POINT_MAP,GEOSPATIAL_MAP,ASSAM_DISTRICT,ASSAM_RC. Uploaded image:kind=IMAGEnamedataset { title }chartType(image rows have none: show "Image")status, for both kinds. Today the page only asks for it on images, which is why built charts show "NA"modifiedsortOptions: [{field: "modified", direction: "desc"}]limit,offset,totalItemsCountidand__typename, unchanged (existing mutations for each kind)The design's Type filter also lists Pie; the backend has no pie chart type yet.
Filters
A list of filters, each: which field, how to compare, what value.
All filters are combined with AND. The value is always a string.
Fields you can filter on:
name,status,chart_type,idkind:CHART(built in the chart builder) orIMAGE(uploaded)dataset(id),dataset__slug,dataset__titlemodified(ISO date, e.g.2026-01-01)Ways to compare: the same as
datasetsTable:exact(default),iexact— equalscontains,icontains— text search (useicontainsfor a search box)startswith,endswithand theiriversionsgt,gte,lt,lte— for datesin— any of a comma-separated listisnull—"true"or"false"Anything outside this list returns a GraphQL error that names the allowed fields.
Sorting
Fields:
name,modified,status,chart_type,kind.Default when omitted: last updated first, the same order as today.
Pagination
limit= page size, 1 to 100 (default 50)offset= rows to skipstatusCountsis computed with every filter applied except the status filter, so the tab numbers do not change when switching tabs.Who sees what
Same rules as
getChartData. Send the usual headers:Authorization: Bearer <token>and, inside an organisation,organization: <slug>.getChartDatadoes today.Full example
Errors
Ordinary GraphQL
errors, for example:idor a date) returns Django's validation message, the same asdatasetsTabletoday.How it works
Built charts and chart images live in two tables. They are merged in one SQL
UNION, so counting, sorting and slicing happen in the database; only the rows of the page are then loaded with their dataset. A page costs the same number of queries however many charts there are. TodaygetChartDataloads both tables in full and sorts them in Python.No migration, no new dependency. Uses the shared helpers in
api/utils/qs_utils.py: sorting and paging go throughget_pagination_windowlike the other tables; filters are applied to each of the two tables before theUNION(Django cannot filter after it); tab counts usestatus_counts.