diff --git a/changelog/23169.txt b/changelog/23169.txt
new file mode 100644
index 000000000000..4f7d266dfb6f
--- /dev/null
+++ b/changelog/23169.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Implement Helios Design System pagination component
+```
\ No newline at end of file
diff --git a/ui/app/controllers/vault/cluster/access/identity/aliases/index.js b/ui/app/controllers/vault/cluster/access/identity/aliases/index.js
index 3109f51492a7..7f69a355106c 100644
--- a/ui/app/controllers/vault/cluster/access/identity/aliases/index.js
+++ b/ui/app/controllers/vault/cluster/access/identity/aliases/index.js
@@ -7,6 +7,15 @@ import Controller from '@ember/controller';
import ListController from 'core/mixins/list-controller';
export default Controller.extend(ListController, {
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ },
+
actions: {
onDelete() {
this.send('reload');
diff --git a/ui/app/controllers/vault/cluster/access/identity/index.js b/ui/app/controllers/vault/cluster/access/identity/index.js
index 0df094e600c3..db9da7a80abd 100644
--- a/ui/app/controllers/vault/cluster/access/identity/index.js
+++ b/ui/app/controllers/vault/cluster/access/identity/index.js
@@ -10,6 +10,15 @@ import ListController from 'core/mixins/list-controller';
export default Controller.extend(ListController, {
flashMessages: service(),
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ },
+
actions: {
delete(model) {
const type = model.get('identityType');
diff --git a/ui/app/controllers/vault/cluster/access/leases/list.js b/ui/app/controllers/vault/cluster/access/leases/list.js
index 434674f4ba3b..fe79717ac097 100644
--- a/ui/app/controllers/vault/cluster/access/leases/list.js
+++ b/ui/app/controllers/vault/cluster/access/leases/list.js
@@ -14,6 +14,15 @@ export default Controller.extend(ListController, {
store: service(),
clusterController: controller('vault.cluster'),
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ },
+
backendCrumb: computed('clusterController.model.name', function () {
return {
label: 'leases',
diff --git a/ui/app/controllers/vault/cluster/policies/index.js b/ui/app/controllers/vault/cluster/policies/index.js
index a04575cab1e7..4d41580889af 100644
--- a/ui/app/controllers/vault/cluster/policies/index.js
+++ b/ui/app/controllers/vault/cluster/policies/index.js
@@ -24,6 +24,15 @@ export default Controller.extend({
// set via the route `loading` action
isLoading: false,
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ },
+
filterMatchesKey: computed('filter', 'model', 'model.[]', function () {
var filter = this.filter;
var content = this.model;
diff --git a/ui/app/controllers/vault/cluster/secrets/backend/list.js b/ui/app/controllers/vault/cluster/secrets/backend/list.js
index c437ab09b15b..3f63bd1806ab 100644
--- a/ui/app/controllers/vault/cluster/secrets/backend/list.js
+++ b/ui/app/controllers/vault/cluster/secrets/backend/list.js
@@ -18,6 +18,15 @@ export default Controller.extend(ListController, BackendCrumbMixin, WithNavToNea
tab: '',
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ },
+
filterIsFolder: computed('filter', function () {
return !!keyIsFolder(this.filter);
}),
diff --git a/ui/app/styles/components/list-pagination.scss b/ui/app/styles/components/list-pagination.scss
deleted file mode 100644
index 5269c4cb63cd..000000000000
--- a/ui/app/styles/components/list-pagination.scss
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-// This file combines Bulma CSS with our own CSS that previously overrode Bulma. In the future we should adopt the HDS pagination.
-
-.pagination-previous[disabled],
-.pagination-next[disabled],
-.pagination-link[disabled],
-.pagination-ellipsis[disabled] {
- cursor: not-allowed;
-}
-
-.pagination-previous,
-.pagination-next,
-.pagination-link,
-.pagination-ellipsis,
-.tabs {
- user-select: none;
-}
-
-.pagination-previous,
-.pagination-next,
-.pagination-link,
-.pagination-ellipsis {
- align-items: center;
- box-shadow: none;
- display: inline-flex;
- font-size: $size-6;
- justify-content: flex-start;
- line-height: 1.5;
- margin: $size-11;
- padding-bottom: calc(0.5em - 1px);
- padding-left: calc(0.75em - 1px);
- padding-right: calc(0.75em - 1px);
- padding-top: calc(0.5em - 1px);
- position: relative;
- vertical-align: top;
-}
-
-.pagination-link.is-current {
- color: $white;
-}
-
-.pagination-list {
- flex-grow: 1;
- flex-shrink: 1;
- justify-content: flex-start;
- order: 1;
-}
-
-.list-pagination {
- @extend .has-slim-padding;
- position: relative;
- top: 1px;
- background-color: $grey-lightest;
- margin-bottom: $size-4;
-
- a {
- text-decoration: none;
- height: 1.5rem;
- min-width: 1.5rem;
- border: none;
- }
- a.pagination-link {
- width: 3ch;
- }
- a:not(.is-current):hover {
- text-decoration: underline;
- color: $blue;
- }
- a.is-current {
- background-color: $grey;
- }
- .pagination {
- justify-content: center;
- }
-
- .pagination-list {
- flex-grow: 0;
- flex-wrap: wrap;
-
- li {
- list-style: none;
- }
- }
- .pagination,
- .pagination-list {
- align-items: center;
- display: flex;
- justify-content: center;
- text-align: center;
- }
- .pagination-ellipsis {
- margin: 0;
- padding-left: 0;
- padding-right: 0;
- }
-}
-
-.list-pagination .pagination-previous,
-.list-pagination .pagination-next {
- @extend .button;
- @extend .is-primary;
- @extend .is-outlined;
- @extend .is-compact;
- background: $white;
- border-color: $blue-500;
- color: $blue-500;
- max-width: 8rem;
-
- @include until($mobile) {
- max-width: 2rem;
- padding-left: 0;
- padding-right: 0;
- }
-
- .pagination-next-label,
- .pagination-previous-label {
- @include until($mobile) {
- display: none;
- }
- }
-
- .icon {
- height: 1em;
- width: 1em;
- vertical-align: middle;
-
- &:last-child:not(:first-child),
- &:first-child:not(:last-child) {
- margin: -0.1em 0 0;
- }
- }
-
- .button .icon {
- margin: 0;
- }
-}
-
-.pagination-previous {
- order: 1;
-}
-
-.pagination-next {
- order: 3;
-}
-
-.pagination.is-centered {
- &.pagination-previous {
- order: 1;
- }
-
- &.pagination-list {
- justify-content: center;
- order: 2;
- }
-
- &.pagination-next {
- order: 3;
- }
-}
-
-.pagination.is-right {
- &.pagination-previous {
- order: 1;
- }
-
- &.pagination-next {
- order: 2;
- }
-
- &.pagination-list {
- justify-content: flex-end;
- order: 3;
- }
-}
-
-// responsive css
-@media screen and (max-width: 768px) {
- .pagination {
- flex-wrap: wrap;
- }
- .pagination-previous,
- .pagination-next {
- flex-grow: 1;
- flex-shrink: 1;
- }
- .pagination-list li {
- flex-grow: 1;
- flex-shrink: 1;
- }
-}
-
-.list-pagination .pagination-next {
- @include until($mobile) {
- order: 3;
- }
-}
diff --git a/ui/app/styles/core.scss b/ui/app/styles/core.scss
index 48abeb15d1a0..2d506f4f97d9 100644
--- a/ui/app/styles/core.scss
+++ b/ui/app/styles/core.scss
@@ -77,7 +77,6 @@
@import './components/license-banners';
@import './components/linked-block';
@import './components/list-item-row';
-@import './components/list-pagination';
@import './components/loader';
@import './components/login-form';
@import './components/masked-input';
diff --git a/ui/app/templates/vault/cluster/access/identity/aliases/index.hbs b/ui/app/templates/vault/cluster/access/identity/aliases/index.hbs
index 7b20c761f06b..3df1212e27cf 100644
--- a/ui/app/templates/vault/cluster/access/identity/aliases/index.hbs
+++ b/ui/app/templates/vault/cluster/access/identity/aliases/index.hbs
@@ -36,13 +36,16 @@
{{/each}}
- {{#if (gt this.model.meta.lastPage 1)}}
-
- {{/if}}
+
+
+
{{else}}
{{/each}}
- {{#if (gt this.model.meta.lastPage 1)}}
-
- {{/if}}
+
+
+
{{else}}
{{/if}}
-{{#if (gt this.model.meta.lastPage 1)}}
-
-{{/if}}
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/ui/app/templates/vault/cluster/policies/index.hbs b/ui/app/templates/vault/cluster/policies/index.hbs
index 5a2c752e49ac..e5b02ef0836b 100644
--- a/ui/app/templates/vault/cluster/policies/index.hbs
+++ b/ui/app/templates/vault/cluster/policies/index.hbs
@@ -151,13 +151,16 @@
{{else}}
{{/each}}
- {{#if (gt this.model.meta.lastPage 1)}}
-
- {{/if}}
+
+
+
{{else}}
{{/each}}
- {{#if (gt this.model.meta.lastPage 1)}}
-
- {{/if}}
+
+
+
{{else}}
{{#if (eq this.baseKey.id "")}}
{{#if (and options.firstStep (not this.tab))}}
diff --git a/ui/lib/core/addon/components/list-pagination.js b/ui/lib/core/addon/components/list-pagination.js
deleted file mode 100644
index 28f947f9683d..000000000000
--- a/ui/lib/core/addon/components/list-pagination.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-import { gt } from '@ember/object/computed';
-import Component from '@ember/component';
-import { computed } from '@ember/object';
-import { range } from 'ember-composable-helpers/helpers/range';
-import { A } from '@ember/array';
-import layout from '../templates/components/list-pagination';
-
-// In non-dev mode, the pagination defaults to the config/environment variable. Set to 100.
-
-export default Component.extend({
- layout,
- classNames: ['box', 'is-shadowless', 'list-pagination'],
- page: null,
- lastPage: null,
- link: null,
- models: A(),
- // number of links to show on each side of page
- spread: 2,
- hasNext: computed('page', 'lastPage', function () {
- return this.page < this.lastPage;
- }),
- hasPrevious: gt('page', 1),
-
- segmentLinks: gt('lastPage', 10),
-
- pageRange: computed('lastPage', 'page', 'spread', function () {
- const { spread, page, lastPage } = this;
-
- let lower = Math.max(2, page - spread);
- const upper = Math.min(lastPage - 1, lower + spread * 2);
- // we're closer to lastPage than the spread
- if (upper - lower < 5) {
- lower = upper - 4;
- }
- if (lastPage <= 10) {
- return range([1, lastPage, true]);
- }
- return range([lower, upper, true]);
- }),
-});
diff --git a/ui/lib/core/addon/components/list-view.hbs b/ui/lib/core/addon/components/list-view.hbs
index cdf1596315d8..fa6006d7ed3a 100644
--- a/ui/lib/core/addon/components/list-view.hbs
+++ b/ui/lib/core/addon/components/list-view.hbs
@@ -10,12 +10,14 @@
{{else}}
{{yield}}
{{/each}}
- {{#if this.showPagination}}
-
{{/if}}
diff --git a/ui/lib/core/addon/components/list-view.js b/ui/lib/core/addon/components/list-view.js
index 9a37d2603bcc..ac7ceceb3f20 100644
--- a/ui/lib/core/addon/components/list-view.js
+++ b/ui/lib/core/addon/components/list-view.js
@@ -40,11 +40,6 @@ export default class ListView extends Component {
return this.args.itemNoun || 'item';
}
- get showPagination() {
- const meta = this.args.items.meta;
- return this.args.paginationRouteName && meta && meta.lastPage > 1 && meta.total > 0;
- }
-
get emptyTitle() {
const items = pluralize(this.itemNoun);
return `No ${items} yet`;
@@ -54,4 +49,13 @@ export default class ListView extends Component {
const items = pluralize(this.itemNoun);
return `Your ${items} will be listed here. Add your first ${this.itemNoun} to get started.`;
}
+
+ // callback from HDS pagination to set the queryParams page
+ get paginationQueryParams() {
+ return (page) => {
+ return {
+ page,
+ };
+ };
+ }
}
diff --git a/ui/lib/core/addon/templates/components/list-pagination.hbs b/ui/lib/core/addon/templates/components/list-pagination.hbs
deleted file mode 100644
index df0acd8f71e5..000000000000
--- a/ui/lib/core/addon/templates/components/list-pagination.hbs
+++ /dev/null
@@ -1,94 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: BUSL-1.1
-~}}
-
-
\ No newline at end of file
diff --git a/ui/lib/core/app/components/list-pagination.js b/ui/lib/core/app/components/list-pagination.js
deleted file mode 100644
index 80a3c70599f9..000000000000
--- a/ui/lib/core/app/components/list-pagination.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-export { default } from 'core/components/list-pagination';
diff --git a/ui/lib/kv/addon/components/page/list.js b/ui/lib/kv/addon/components/page/list.js
index 8054796df8cf..8afc11cf5da1 100644
--- a/ui/lib/kv/addon/components/page/list.js
+++ b/ui/lib/kv/addon/components/page/list.js
@@ -42,11 +42,11 @@ export default class KvListPageComponent extends Component {
return pathIsDirectory(path) ? 'View list' : 'View secret';
}
- // callback from HDS pagination to set the queryParams currentPage
+ // callback from HDS pagination to set the queryParams page
get paginationQueryParams() {
return (page) => {
return {
- currentPage: page,
+ page,
};
};
}
diff --git a/ui/lib/kv/addon/controllers/list.js b/ui/lib/kv/addon/controllers/list.js
index d1c7e3daa535..00349e2e07f8 100644
--- a/ui/lib/kv/addon/controllers/list.js
+++ b/ui/lib/kv/addon/controllers/list.js
@@ -6,5 +6,5 @@
import Controller from '@ember/controller';
export default class KvListController extends Controller {
- queryParams = ['pageFilter', 'currentPage'];
+ queryParams = ['pageFilter', 'page'];
}
diff --git a/ui/lib/kv/addon/routes/list-directory.js b/ui/lib/kv/addon/routes/list-directory.js
index 297a5e982196..4c77f44f8428 100644
--- a/ui/lib/kv/addon/routes/list-directory.js
+++ b/ui/lib/kv/addon/routes/list-directory.js
@@ -19,7 +19,7 @@ export default class KvSecretsListRoute extends Route {
pageFilter: {
refreshModel: true,
},
- currentPage: {
+ page: {
refreshModel: true,
},
};
@@ -29,7 +29,7 @@ export default class KvSecretsListRoute extends Route {
.lazyPaginatedQuery('kv/metadata', {
backend,
responsePath: 'data.keys',
- page: Number(params.currentPage) || 1,
+ page: Number(params.page) || 1,
size: Number(params.currentPageSize),
pageFilter: params.pageFilter,
pathToSecret,
@@ -90,7 +90,7 @@ export default class KvSecretsListRoute extends Route {
resetController(controller, isExiting) {
if (isExiting) {
controller.set('pageFilter', null);
- controller.set('currentPage', null);
+ controller.set('page', null);
}
}
}
diff --git a/ui/lib/ldap/addon/components/page/roles.ts b/ui/lib/ldap/addon/components/page/roles.ts
index 13a01e1fc5a9..9ec7b0c628c3 100644
--- a/ui/lib/ldap/addon/components/page/roles.ts
+++ b/ui/lib/ldap/addon/components/page/roles.ts
@@ -35,7 +35,7 @@ export default class LdapRolesPageComponent extends Component {
}
get paginationQueryParams() {
- return (page: number) => ({ currentPage: page });
+ return (page: number) => ({ page });
}
@action
diff --git a/ui/lib/ldap/addon/controllers/roles/index.ts b/ui/lib/ldap/addon/controllers/roles/index.ts
index c4903bea59eb..a8eec50870f6 100644
--- a/ui/lib/ldap/addon/controllers/roles/index.ts
+++ b/ui/lib/ldap/addon/controllers/roles/index.ts
@@ -6,5 +6,5 @@
import Controller from '@ember/controller';
export default class LdapRolesController extends Controller {
- queryParams = ['pageFilter', 'currentPage'];
+ queryParams = ['pageFilter', 'page'];
}
diff --git a/ui/lib/ldap/addon/routes/roles/index.ts b/ui/lib/ldap/addon/routes/roles/index.ts
index 1a7596a327a3..678ccbbc2ed2 100644
--- a/ui/lib/ldap/addon/routes/roles/index.ts
+++ b/ui/lib/ldap/addon/routes/roles/index.ts
@@ -25,11 +25,11 @@ interface LdapRolesController extends Controller {
breadcrumbs: Array;
model: LdapRolesRouteModel;
pageFilter: string | undefined;
- currentPage: number | undefined;
+ page: number | undefined;
}
interface LdapRolesRouteParams {
- currentPage?: string;
+ page?: string;
pageFilter: string;
}
@@ -44,7 +44,7 @@ export default class LdapRolesRoute extends Route {
pageFilter: {
refreshModel: true,
},
- currentPage: {
+ page: {
refreshModel: true,
},
};
@@ -58,7 +58,7 @@ export default class LdapRolesRoute extends Route {
'ldap/role',
{
backend: backendModel.id,
- page: Number(params.currentPage) || 1,
+ page: Number(params.page) || 1,
pageFilter: params.pageFilter,
responsePath: 'data.keys',
},
@@ -83,7 +83,7 @@ export default class LdapRolesRoute extends Route {
resetController(controller: LdapRolesController, isExiting: boolean) {
if (isExiting) {
controller.set('pageFilter', undefined);
- controller.set('currentPage', undefined);
+ controller.set('page', undefined);
}
}
}
diff --git a/ui/tests/acceptance/access/namespaces/index-test.js b/ui/tests/acceptance/access/namespaces/index-test.js
index ef3f1952f633..0a64769e2606 100644
--- a/ui/tests/acceptance/access/namespaces/index-test.js
+++ b/ui/tests/acceptance/access/namespaces/index-test.js
@@ -35,6 +35,6 @@ module('Acceptance | Enterprise | /access/namespaces', function (hooks) {
// Default page size is 15
assert.strictEqual(store.peekAll('namespace').length, 15, 'Store has 15 namespaces records');
assert.dom('.list-item-row').exists({ count: 15 });
- assert.dom('[data-test-list-view-pagination]').exists();
+ assert.dom('.hds-pagination').exists();
});
});