mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-20 22:21:09 +02:00
* rename store to pagination, remove store extension * initial update of service test * remove superfluous helper * replace store with pagination service in main app * update kmip engine syntax * add pagination to kmip engine * update to pagination in config-ui engine * update sync engine to use pagination service * use pagination service in kv engine * use pagination service in ldap engine * use pagination in pki engine * update renaming clearDataset functions * link to jira VAULT-31721 * remove comment
111 lines
4.0 KiB
TypeScript
111 lines
4.0 KiB
TypeScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import Component from '@glimmer/component';
|
|
import { service } from '@ember/service';
|
|
import { action } from '@ember/object';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { getOwner } from '@ember/owner';
|
|
import errorMessage from 'vault/utils/error-message';
|
|
import { findDestination, syncDestinations } from 'core/helpers/sync-destinations';
|
|
import { next } from '@ember/runloop';
|
|
|
|
import type SyncDestinationModel from 'vault/vault/models/sync/destination';
|
|
import type RouterService from '@ember/routing/router-service';
|
|
import type PaginationService from 'vault/services/pagination';
|
|
import type FlashMessageService from 'vault/services/flash-messages';
|
|
import type { EngineOwner } from 'vault/vault/app-types';
|
|
import type { SyncDestinationName, SyncDestinationType } from 'vault/vault/helpers/sync-destinations';
|
|
import type Transition from '@ember/routing/transition';
|
|
|
|
interface Args {
|
|
destinations: Array<SyncDestinationModel>;
|
|
nameFilter: SyncDestinationName;
|
|
typeFilter: SyncDestinationType;
|
|
}
|
|
|
|
export default class SyncSecretsDestinationsPageComponent extends Component<Args> {
|
|
@service('app-router') declare readonly router: RouterService;
|
|
@service declare readonly pagination: PaginationService;
|
|
@service declare readonly flashMessages: FlashMessageService;
|
|
|
|
@tracked destinationToDelete: SyncDestinationModel | null = null;
|
|
// for some reason there isn't a full page refresh happening when transitioning on filter change
|
|
// when the transition happens it causes the FilterInput component to lose focus since it can only focus on didInsert
|
|
// to work around this, verify that a transition from this route was completed and then focus the input
|
|
constructor(owner: unknown, args: Args) {
|
|
super(owner, args);
|
|
this.router.on('routeDidChange', this.focusNameFilter);
|
|
}
|
|
|
|
willDestroy(): void {
|
|
this.router.off('routeDidChange', this.focusNameFilter);
|
|
super.willDestroy();
|
|
}
|
|
|
|
focusNameFilter(transition?: Transition) {
|
|
const route = 'vault.cluster.sync.secrets.destinations.index';
|
|
if (transition?.from?.name === route && transition?.to?.name === route) {
|
|
next(() => document.getElementById('name-filter')?.focus());
|
|
}
|
|
}
|
|
|
|
// typeFilter arg comes in as destination type but we need to pass the destination display name into the SearchSelect
|
|
get typeFilterName() {
|
|
return findDestination(this.args.typeFilter)?.name;
|
|
}
|
|
|
|
get destinationTypes() {
|
|
return syncDestinations().map((d) => ({ id: d.name, name: d.type }));
|
|
}
|
|
|
|
get mountPoint(): string {
|
|
const owner = getOwner(this) as EngineOwner;
|
|
return owner.mountPoint;
|
|
}
|
|
|
|
get paginationQueryParams() {
|
|
return (page: number) => ({ page });
|
|
}
|
|
|
|
get noResultsMessage() {
|
|
const { nameFilter, typeFilter } = this.args;
|
|
if (nameFilter && typeFilter) {
|
|
return `There are no ${this.typeFilterName || typeFilter} destinations matching "${nameFilter}".`;
|
|
}
|
|
if (nameFilter) {
|
|
return `There are no destinations matching "${nameFilter}".`;
|
|
}
|
|
if (typeFilter) {
|
|
return `There are no ${this.typeFilterName || typeFilter} destinations.`;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
@action
|
|
onFilterChange(key: string, value: { id: string; name: string }[] | string | undefined) {
|
|
const queryValue = Array.isArray(value) ? value[0]?.name : value;
|
|
this.router.transitionTo('vault.cluster.sync.secrets.destinations', {
|
|
queryParams: { [key]: queryValue },
|
|
});
|
|
}
|
|
|
|
@action
|
|
async onDelete(destination: SyncDestinationModel) {
|
|
try {
|
|
const { name } = destination;
|
|
const message = `Destination ${name} has been queued for deletion.`;
|
|
await destination.destroyRecord();
|
|
this.pagination.clearDataset('sync/destination');
|
|
this.router.transitionTo('vault.cluster.sync.secrets.overview');
|
|
this.flashMessages.success(message);
|
|
} catch (error) {
|
|
this.flashMessages.danger(`Error deleting destination \n ${errorMessage(error)}`);
|
|
} finally {
|
|
this.destinationToDelete = null;
|
|
}
|
|
}
|
|
}
|