LDAP Roles Pagination (#22985)

* adds pagination to ldap roles list view

* fixes issue with list not refreshing on ldap roles delete
This commit is contained in:
Jordan Reimer
2023-09-12 09:38:26 -06:00
committed by GitHub
parent 21742020f0
commit 8f6535cfaf
15 changed files with 178 additions and 44 deletions

View File

@@ -10,6 +10,7 @@ import type LdapRoleModel from 'vault/models/ldap/role';
import { Breadcrumb, ValidationMap } from 'vault/vault/app-types';
import type FlashMessageService from 'vault/services/flash-messages';
import type RouterService from '@ember/routing/router-service';
import type StoreService from 'vault/services/store';
interface Args {
model: LdapRoleModel;
@@ -25,6 +26,7 @@ interface RoleTypeOption {
export default class LdapCreateAndEditRolePageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service declare readonly store: StoreService;
@tracked modelValidations: ValidationMap | null = null;
@tracked invalidFormMessage = '';
@@ -63,6 +65,9 @@ export default class LdapCreateAndEditRolePageComponent extends Component<Args>
const action = model.isNew ? 'created' : 'updated';
yield model.save();
this.flashMessages.success(`Successfully ${action} the role ${model.name}`);
if (action === 'created') {
this.store.clearDataset('ldap/role');
}
this.router.transitionTo(
'vault.cluster.secrets.backend.ldap.roles.role.details',
model.type,

View File

@@ -9,6 +9,7 @@ import type LdapRoleModel from 'vault/models/ldap/role';
import { Breadcrumb } from 'vault/vault/app-types';
import type FlashMessageService from 'vault/services/flash-messages';
import type RouterService from '@ember/routing/router-service';
import type StoreService from 'vault/services/store';
interface Args {
model: LdapRoleModel;
@@ -18,12 +19,14 @@ interface Args {
export default class LdapRoleDetailsPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service declare readonly store: StoreService;
@action
async delete() {
try {
await this.args.model.destroyRecord();
this.flashMessages.success('Role deleted successfully.');
this.store.clearDataset('ldap/role');
this.router.transitionTo('vault.cluster.secrets.backend.ldap.roles');
} catch (error) {
const message = errorMessage(error, 'Unable to delete role. Please try again or contact support.');

View File

@@ -1,7 +1,13 @@
<TabPageHeader @model={{@backendModel}} @breadcrumbs={{@breadcrumbs}}>
<:toolbarFilters>
{{#if (and (not @promptConfig) @roles)}}
<FilterInput @placeholder="Filter roles" @onInput={{fn (mut this.filterValue)}} />
{{#if (and (not @promptConfig) @roles.meta.total)}}
<FilterInput
@placeholder="Filter roles"
@value={{@pageFilter}}
@wait={{500}}
@autofocus={{true}}
@onInput={{this.onFilterChange}}
/>
{{/if}}
</:toolbarFilters>
<:toolbarActions>
@@ -19,9 +25,9 @@
{{#if @promptConfig}}
<ConfigCta />
{{else if (not this.filteredRoles)}}
{{#if this.filterValue}}
<EmptyState @title="There are no roles matching &quot;{{this.filterValue}}&quot;" />
{{else if (not @roles.meta.filteredTotal)}}
{{#if @pageFilter}}
<EmptyState @title="There are no roles matching &quot;{{@pageFilter}}&quot;" />
{{else}}
<EmptyState
data-test-config-cta
@@ -35,7 +41,7 @@
{{/if}}
{{else}}
<div class="has-bottom-margin-s">
{{#each this.filteredRoles as |role|}}
{{#each @roles as |role|}}
<ListItem @linkPrefix={{this.mountPoint}} @linkParams={{array "roles.role.details" role.type role.name}} as |Item|>
<Item.content>
<Icon @name="user" />
@@ -113,5 +119,15 @@
</Item.menu>
</ListItem>
{{/each}}
<Hds::Pagination::Numbered
@currentPage={{@roles.meta.currentPage}}
@currentPageSize={{@roles.meta.pageSize}}
@route="roles"
@showSizeSelector={{false}}
@totalItems={{@roles.meta.filteredTotal}}
@queryFunction={{this.paginationQueryParams}}
data-test-pagination
/>
</div>
{{/if}}

View File

@@ -4,7 +4,6 @@
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { getOwner } from '@ember/application';
@@ -14,29 +13,34 @@ import type LdapRoleModel from 'vault/models/ldap/role';
import type SecretEngineModel from 'vault/models/secret-engine';
import type FlashMessageService from 'vault/services/flash-messages';
import type { Breadcrumb, EngineOwner } from 'vault/vault/app-types';
import type RouterService from '@ember/routing/router-service';
import type StoreService from 'vault/services/store';
interface Args {
roles: Array<LdapRoleModel>;
promptConfig: boolean;
backendModel: SecretEngineModel;
breadcrumbs: Array<Breadcrumb>;
pageFilter: string;
}
export default class LdapRolesPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@tracked filterValue = '';
@service declare readonly router: RouterService;
@service declare readonly store: StoreService;
get mountPoint(): string {
const owner = getOwner(this) as EngineOwner;
return owner.mountPoint;
}
get filteredRoles() {
const { roles } = this.args;
return this.filterValue
? roles.filter((role) => role.name.toLowerCase().includes(this.filterValue.toLowerCase()))
: roles;
get paginationQueryParams() {
return (page: number) => ({ currentPage: page });
}
@action
onFilterChange(pageFilter: string) {
this.router.transitionTo('vault.cluster.secrets.backend.ldap.roles', { queryParams: { pageFilter } });
}
@action
@@ -55,6 +59,8 @@ export default class LdapRolesPageComponent extends Component<Args> {
try {
const message = `Successfully deleted role ${model.name}.`;
await model.destroyRecord();
this.store.clearDataset('ldap/role');
this.router.transitionTo('vault.cluster.secrets.backend.ldap.roles');
this.flashMessages.success(message);
} catch (error) {
this.flashMessages.danger(`Error deleting role \n ${errorMessage(error)}`);