UI: Fix Namespace url and content on page synchronization with pagination (#14095) (#14140)

* adding handlers to keep track of current page and page size, adds them to url

* pr comments

Co-authored-by: Dan Rivera <dan.rivera@hashicorp.com>
This commit is contained in:
Vault Automation 2026-04-21 12:27:32 -04:00 committed by GitHub
parent 8b448ab7af
commit 1024ffd532
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 61 additions and 8 deletions

View file

@ -82,7 +82,14 @@
</Toolbar>
{{#if @model.namespaces.length}}
<ListTable @columns={{this.tableColumns}} @data={{this.namespaceIds}}>
<ListTable
@columns={{this.tableColumns}}
@data={{this.namespaceIds}}
@pageSize={{@model.pageSize}}
@page={{@model.page}}
@onPageChange={{this.handlePageChange}}
@onPageSizeChange={{this.handlePageSizeChange}}
>
<:popupMenu as |rowData|>
<Hds::Dropdown @isInline={{true}} @listPosition="bottom-right" as |dd|>
<dd.ToggleIcon

View file

@ -34,10 +34,13 @@ import type { PaginatedMetadata } from 'core/utils/paginate-list';
interface Args {
model: {
namespaces: NamespaceModel[] & PaginatedMetadata;
page: number;
pageSize: number;
pageFilter: string | null;
};
onFilterChange: CallableFunction;
onRefresh: CallableFunction;
onPageChange: CallableFunction;
}
interface NamespaceModel {
@ -147,7 +150,7 @@ export default class PageNamespacesComponent extends Component<Args> {
@action
handleSearch(evt: HTMLElementEvent<HTMLInputElement>) {
evt.preventDefault();
this.args.onFilterChange(this.query);
this.args.onFilterChange({ pageFilter: this.query });
}
@action
@ -187,8 +190,14 @@ export default class PageNamespacesComponent extends Component<Args> {
this.shouldRenderIntroModal = true;
}
@action handlePageChange() {
this.args.onRefresh();
// handles page change but keeps pageFilters if there are any
@action handlePageChange(page: number) {
this.args.onPageChange({ page: page, pageFilter: this.query, pageSize: this.args.model.pageSize });
}
// handles page size change but keeps any current pageFilters
@action handlePageSizeChange(pageSize: number) {
this.args.onPageChange({ page: 1, pageFilter: this.query, pageSize: pageSize });
}
@action

View file

@ -27,7 +27,16 @@ export default class ManageNamespacesController extends Controller {
@action
navigate(pageFilter) {
const route = 'vault.cluster.access.namespaces.index';
const args = [route, { queryParams: { page: 1, pageFilter: pageFilter || null } }];
const args = [
route,
{
queryParams: {
page: pageFilter.page || 1,
pageFilter: pageFilter.pageFilter || null,
pageSize: pageFilter.pageSize || null,
},
},
];
this.router.transitionTo(...args);
}

View file

@ -23,6 +23,9 @@ export default class NamespaceListRoute extends Route {
page: {
refreshModel: true,
},
pageSize: {
refreshModel: true,
},
};
beforeModel() {
@ -56,6 +59,8 @@ export default class NamespaceListRoute extends Route {
const { pageFilter } = params;
return hash({
namespaces: this.fetchNamespaces(params),
page: Number(params?.page) || 1,
pageSize: Number(params?.pageSize) || 10,
pageFilter,
});
}

View file

@ -3,4 +3,9 @@
SPDX-License-Identifier: BUSL-1.1
}}
<Page::Namespaces @model={{this.model}} @onFilterChange={{this.navigate}} @onRefresh={{this.refreshRoute}} />
<Page::Namespaces
@model={{this.model}}
@onFilterChange={{this.navigate}}
@onRefresh={{this.refreshRoute}}
@onPageChange={{this.navigate}}
/>

View file

@ -55,15 +55,26 @@ interface Args {
data: Array<object>;
columns: TableColumn[];
selectionKeyField?: string;
page?: number; // optional page number to set current page, needed to keep pagination sync with url query param
pageSize?: number; // optional page size, needed to keep pagination sync with url query param & keep page size
onSelectionChange?: OnSelectionChange;
onPageChange?: CallableFunction;
onPageSizeChange?: CallableFunction;
}
export default class ListTable extends Component<Args> {
@tracked currentPage = 1;
@tracked pageSize = 10;
@tracked currentPage;
@tracked pageSize;
// WORKAROUND to manually re-render Hds::Pagination::Numbered to force update @currentPage
@tracked renderPagination = true;
constructor(owner: unknown, args: Args) {
super(owner, args);
this.currentPage = args.page || 1;
this.pageSize = args.pageSize || 10;
}
get paginatedTableData() {
const paginated = paginate(this.args.data, {
page: this.currentPage,
@ -76,8 +87,15 @@ export default class ListTable extends Component<Args> {
async handlePaginationChange(action: 'currentPage' | 'pageSize', value: number) {
if (action === 'pageSize') {
await this.resetPagination();
// external callback to handle page size changes and bubble up to parent component
this.args.onPageSizeChange?.(value);
}
this[action] = value;
// external callback to handle current page changes and bubble up to parent component
if (action === 'currentPage') {
this.args.onPageChange?.(value);
}
}
@action