Skip to content

Commit bcc4d5f

Browse files
authored
fix: Data browser pagination is ignored when using browser navigation or page reload (parse-community#3097)
1 parent 186ca40 commit bcc4d5f

File tree

1 file changed

+92
-16
lines changed

1 file changed

+92
-16
lines changed

src/dashboard/Data/Browser/Browser.react.js

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class Browser extends DashboardView {
203203
this.fetchRelationCount = this.fetchRelationCount.bind(this);
204204
this.fetchNextPage = this.fetchNextPage.bind(this);
205205
this.updateFilters = this.updateFilters.bind(this);
206+
this.updateURL = this.updateURL.bind(this);
206207
this.showRemoveColumn = this.showRemoveColumn.bind(this);
207208
this.showDeleteRows = this.showDeleteRows.bind(this);
208209
this.showDropClass = this.showDropClass.bind(this);
@@ -549,6 +550,7 @@ class Browser extends DashboardView {
549550

550551
async prefetchData(props, context) {
551552
const filters = this.extractFiltersFromQuery(props);
553+
const pagination = this.extractPaginationFromQuery(props);
552554
const { className, entityId, relationName } = props.params;
553555
const isRelationRoute = entityId && relationName;
554556

@@ -563,6 +565,11 @@ class Browser extends DashboardView {
563565
const parent = await parentObjectQuery.get(entityId, { useMasterKey });
564566
relation = parent.relation(relationName);
565567
}
568+
569+
// Use pagination from URL if available, otherwise keep current state or use defaults
570+
const skip = pagination.skip;
571+
const limit = pagination.limit !== null ? pagination.limit : this.state.limit;
572+
566573
this.setState(
567574
{
568575
data: isEditFilterMode ? [] : null, // Set empty array in edit mode to avoid loading
@@ -571,6 +578,8 @@ class Browser extends DashboardView {
571578
ordering: ColumnPreferences.getColumnSort(false, context.applicationId, className),
572579
selection: {},
573580
relation: isRelationRoute ? relation : null,
581+
skip,
582+
limit,
574583
},
575584
() => {
576585
// Only fetch data if not in edit filter mode
@@ -626,6 +635,66 @@ class Browser extends DashboardView {
626635
return filters;
627636
}
628637

638+
extractPaginationFromQuery(props) {
639+
const pagination = { skip: 0, limit: null };
640+
if (!props || !props.location || !props.location.search) {
641+
return pagination;
642+
}
643+
const query = new URLSearchParams(props.location.search);
644+
if (query.has('skip')) {
645+
const skip = parseInt(query.get('skip'), 10);
646+
if (!isNaN(skip) && skip >= 0) {
647+
pagination.skip = skip;
648+
}
649+
}
650+
if (query.has('limit')) {
651+
const limit = parseInt(query.get('limit'), 10);
652+
if (!isNaN(limit) && limit > 0) {
653+
pagination.limit = limit;
654+
}
655+
}
656+
return pagination;
657+
}
658+
659+
updateURL(newSkip = null, newLimit = null) {
660+
const source = this.props.params.className;
661+
if (!source || this.state.relation) {
662+
return; // Don't update URL for relations
663+
}
664+
665+
const skip = newSkip !== null ? newSkip : this.state.skip;
666+
const limit = newLimit !== null ? newLimit : this.state.limit;
667+
668+
// Build query parameters preserving existing ones
669+
const currentUrlParams = new URLSearchParams(window.location.search);
670+
const queryParams = new URLSearchParams();
671+
672+
// Preserve filters and filterId
673+
if (currentUrlParams.has('filters')) {
674+
queryParams.set('filters', currentUrlParams.get('filters'));
675+
}
676+
if (currentUrlParams.has('filterId')) {
677+
queryParams.set('filterId', currentUrlParams.get('filterId'));
678+
}
679+
if (currentUrlParams.has('editFilter')) {
680+
queryParams.set('editFilter', currentUrlParams.get('editFilter'));
681+
}
682+
683+
// Add pagination parameters (only if non-default)
684+
if (skip > 0) {
685+
queryParams.set('skip', skip.toString());
686+
}
687+
if (limit !== 100) { // Only include limit if it's not the default
688+
queryParams.set('limit', limit.toString());
689+
}
690+
691+
const queryString = queryParams.toString();
692+
const url = queryString ? `browser/${source}?${queryString}` : `browser/${source}`;
693+
694+
// Push new history entry instead of replacing to enable browser back button
695+
this.props.navigate(generatePath(this.context, url));
696+
}
697+
629698
redirectToFirstClass(classList, context) {
630699
if (!classList.isEmpty()) {
631700
const classes = Object.keys(classList.toObject());
@@ -1327,23 +1396,26 @@ class Browser extends DashboardView {
13271396
const currentUrlParams = new URLSearchParams(window.location.search);
13281397
const currentFilterId = currentUrlParams.get('filterId');
13291398

1330-
let url = `browser/${source}`;
1331-
if (filters.size === 0) {
1332-
// If no filters, don't include any query parameters
1333-
url = `browser/${source}`;
1334-
} else {
1335-
// Build query parameters
1336-
const queryParams = new URLSearchParams();
1399+
// Build query parameters
1400+
const queryParams = new URLSearchParams();
1401+
1402+
if (filters.size > 0) {
13371403
queryParams.set('filters', _filters);
1404+
}
13381405

1339-
// Preserve filterId if it exists in current URL
1340-
if (currentFilterId) {
1341-
queryParams.set('filterId', currentFilterId);
1342-
}
1406+
// Preserve filterId if it exists in current URL
1407+
if (currentFilterId) {
1408+
queryParams.set('filterId', currentFilterId);
1409+
}
13431410

1344-
url = `browser/${source}?${queryParams.toString()}`;
1411+
// Preserve pagination if not default (skip is reset to 0 when filters change)
1412+
if (this.state.limit !== 100) {
1413+
queryParams.set('limit', this.state.limit.toString());
13451414
}
13461415

1416+
const queryString = queryParams.toString();
1417+
const url = queryString ? `browser/${source}?${queryString}` : `browser/${source}`;
1418+
13471419
// filters param change is making the fetch call
13481420
this.props.navigate(generatePath(this.context, url));
13491421
}
@@ -2656,14 +2728,18 @@ class Browser extends DashboardView {
26562728
<BrowserFooter
26572729
skip={this.state.skip}
26582730
setSkip={skip => {
2659-
this.setState({ skip });
2660-
this.updateOrdering(this.state.ordering);
2731+
this.setState({ skip }, () => {
2732+
this.updateURL(skip, null);
2733+
this.updateOrdering(this.state.ordering);
2734+
});
26612735
}}
26622736
count={count}
26632737
limit={this.state.limit}
26642738
setLimit={limit => {
2665-
this.setState({ limit });
2666-
this.updateOrdering(this.state.ordering);
2739+
this.setState({ limit, skip: 0 }, () => {
2740+
this.updateURL(0, limit); // Reset to first page when limit changes
2741+
this.updateOrdering(this.state.ordering);
2742+
});
26672743
}}
26682744
hasSelectedRows={Object.keys(this.state.selection).length > 0}
26692745
selectedRowsMessage={SELECTED_ROWS_MESSAGE}

0 commit comments

Comments
 (0)