Geo Replicables List: Add ability to store pagination in URL
Why are we doing this work
The list view is currently going through a migration and may look different depending on if you have the feature flag geo_replicables_filtered_list_view and/or geo_replicables_show_view enabled.
We have begun storing query information in the URL. However, the pagination is not, so users cannot return to a previous page by refresh if they would so desire. In this change we'd suggest hooking up the existing pagination cursor information into the URL.
Relevant links
Demo
Proposal Demo
Screen_Recording_2025-04-11_at_1.38.58_PM
Implementation plan
- Add the ability to manage the
activePaginationin the vuex store (geo_replicable/store)
// state.js
activePagination: {
before: '',
after: '',
first: DEFAULT_PAGE_SIZE,
last: null
},
// mutation_types.js
export const SET_ACTIVE_PAGINATION = 'SET_ACTIVE_PAGINATION';
// mutations.js
[types.SET_ACTIVE_PAGINATION](state, pagination) {
state.activePagination = pagination;
},
// actions.js
export const setActivePagination = ({ commit }, pagination) => {
commit(types.SET_ACTIVE_PAGINATION, pagination);
};
- Update Vuex action
fetchReplicableItemsto get pagination fromactivePagination
// some of file omitted for clarity
// actions.js
--- let before = '';
--- let after = '';
--- // If we are going backwards we want the last 20, otherwise get the first 20.
--- let first = DEFAULT_PAGE_SIZE;
--- let last = null;
--- if (direction === PREV) {
--- before = state.paginationData.startCursor;
--- first = null;
--- last = DEFAULT_PAGE_SIZE;
--- } else if (direction === NEXT) {
--- after = state.paginationData.endCursor;
--- }
--- export const fetchReplicableItems = ({ state, dispatch }, direction) => {
+++ export const fetchReplicableItems = ({ state, dispatch }) => {
dispatch('requestReplicableItems');
const replicationState = state.statusFilter ? state.statusFilter.toUpperCase() : null
+++ const { first, last, before, after } = state.activePagination
// ...
};
- Add support getting the pagination object and processing the pagination object in
geo_replicable/filters.js
// some of file omitted for clarity
// filters.js
export const getPaginationObject = ({ before, after, first, last }) => {
return {
before: before || '',
after: after || '',
first: Number(first) || null,
last: Number(last) || null
}
}
export const processPagination = ({ direction, paginationData }) => {
// If we are going backwards we want the last 20, otherwise get the first 20.
const query = {
before: '',
after: '',
first: DEFAULT_PAGE_SIZE,
last: null
};
if (direction === PREV) {
query.before = paginationData.startCursor;
query.first = null;
query.last = DEFAULT_PAGE_SIZE;
} else if (direction === NEXT) {
query.after = paginationData.endCursor;
}
return { query };
};
- Update
geo_replicable.vueto emit apaginateevent when page change is triggered.
// some of file omitted for clarity
// geo_replicable.vue
<script>
export default {
methods: {
updatePagination(direction) {
this.$emit('paginate', direction)
}
},
}
</script>
<template>
<gl-keyset-pagination
v-bind="paginationData"
@next="updatePagination($options.NEXT)"
@prev="updatePagination($options.PREV)"
/>
</template>
- Add method to handle
onPaginateinapp.vue
// some of file omitted for clarity
// app.vue
onPaginate(direction) {
const { query } = processPagination({ direction, paginationData: this.paginationData })
visitUrl(setUrlParams(query))
}
- Add method to handle
getPaginationFromQueryinapp.vue
// some of file omitted for clarity
// app.vue
<script>
export default {
created() {
if (this.glFeatures.geoReplicablesFilteredListView) {
this.getPaginationFromQuery();
}
},
methods: {
getPaginationFromQuery() {
const { before, after, first, last } = queryToObject(window.location.search || '');
if (before || after || first || last) {
this.setActivePagination(getPaginationObject({ before, after, first, last }))
}
}
}
}
</script>
Edited by 🤖 GitLab Bot 🤖