Vault Automation db994695e0
Backport UI: Reorganize client components into ce/main (#8826)
* UI: Reorganize client components (#8742)

* remove complex logic from running totals component

* move byMonthNewClients getter to overview

* organization: remove unused @versionHistory, update tests

* rename namespaceLabels getter

* refactor filter-toolbar to manage drodown Sets

* add search bar to filter toolbar

* make export request

* finish adding search logic to dropdown

* rename route method

* move typescript declarations because all of the client ones are in client-count-utils

* add error template for failed export request

* update tests

* stub activity export adapter method instead of trying to mock readable stream

* lint

---------

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
Co-authored-by: claire bontempo <cbontempo@hashicorp.com>
2025-09-02 15:54:52 -07:00

73 lines
2.3 KiB
TypeScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import ActivityComponent from '../activity';
import { service } from '@ember/service';
import { cached, tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { HTMLElementEvent } from 'vault/forms';
import { parseAPITimestamp } from 'core/utils/date-formatters';
import { filterTableData, flattenMounts } from 'core/utils/client-count-utils';
import type FlagsService from 'vault/services/flags';
import type RouterService from '@ember/routing/router-service';
export default class ClientsOverviewPageComponent extends ActivityComponent {
@service declare readonly flags: FlagsService;
@service('app-router') declare readonly router: RouterService;
@tracked selectedMonth = '';
@cached
get byMonthNewClients() {
return this.args.activity.byMonth?.map((m) => m?.new_clients) || [];
}
@cached
// Supplies data passed to dropdown filters
get activityData() {
// Find the namespace data for the selected month
// If no month is selected the table displays all of the activity for the queried date range
const namespaceData = this.selectedMonth
? this.byMonthNewClients.find((m) => m.timestamp === this.selectedMonth)?.namespaces
: this.args.activity.byNamespace;
// Get the array of "mounts" data nested in each namespace object and flatten
return flattenMounts(namespaceData || []);
}
@cached
get months() {
return this.byMonthNewClients
.reverse()
.map((m) => ({ timestamp: m.timestamp, display: parseAPITimestamp(m.timestamp, 'MMMM yyyy') }));
}
get tableData() {
if (this.activityData?.length) {
return filterTableData(this.activityData, this.args.filterQueryParams);
}
return null;
}
get tableColumns() {
return [
{ key: 'namespace_path', label: 'Namespace', isSortable: true },
{ key: 'mount_path', label: 'Mount path', isSortable: true },
{ key: 'mount_type', label: 'Mount type', isSortable: true },
{ key: 'clients', label: 'Client count', isSortable: true },
];
}
@action
selectMonth(e: HTMLElementEvent<HTMLInputElement>) {
this.selectedMonth = e.target.value;
// Reset filters when no month is selected
if (this.selectedMonth === '') {
this.resetFilters();
}
}
}