Vault Automation 4ab8b902f2
UI: Allow fallback date querying for client usage when no billing timestamp is provided (#10728) (#10755)
* some change

* add console logs to debug rendering error

* add fallback in case billingStartTime does not exist

* remove console logs

* allow querying dates if there is no billing start timestamp

* add comments and test coverage

* add changelog

* remove extra divs, small copy changes

* remove extra line

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
2025-11-12 14:11:24 -08:00

84 lines
2.9 KiB
TypeScript

/**
* Copyright IBM Corp. 2016, 2025
* SPDX-License-Identifier: BUSL-1.1
*/
import Component from '@glimmer/component';
import { cached, tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { filterTableData, flattenMounts } from 'core/utils/client-count-utils';
import { service } from '@ember/service';
import type ClientsActivityModel from 'vault/vault/models/clients/activity';
import type { ClientFilterTypes } from 'vault/vault/client-counts/activity-api';
import type FlagsService from 'vault/services/flags';
export interface Args {
activity: ClientsActivityModel;
onFilterChange: CallableFunction;
filterQueryParams: Record<ClientFilterTypes, string>;
}
export default class ClientsOverviewPageComponent extends Component<Args> {
@service declare readonly flags: FlagsService;
@tracked selectedMonth = '';
@cached
get byMonthClients() {
// HVD clusters are billed differently and the monthly total is the important metric.
if (this.flags.isHvdManaged) {
return this.args.activity.byMonth || [];
}
// For self-managed clusters only the new_clients per month are relevant because clients accumulate over a billing period.
// (Since "total" per month is not cumulative it's not a useful metric)
return this.args.activity.byMonth?.map((m) => m?.new_clients) || [];
}
// Supplies data passed to dropdown filters (except months which is computed below )
@cached
get activityData() {
// If no month is selected the table displays all of the activity for the queried date range.
const selectedMonth = this.args.filterQueryParams.month;
const namespaceData = selectedMonth
? this.byMonthClients.find((m) => m.timestamp === 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() {
const timestamps = this.byMonthClients.map((m) => m.timestamp);
// display the most recent month at the top of the dropdown
return timestamps.reverse();
}
@cached
get tableData() {
if (this.activityData?.length) {
// Reset the `month` query param because it determines which dataset (see this.activityData)
// is passed to the table and is does not filter for key/value pairs within this dataset.
const filters = { ...this.args.filterQueryParams };
filters.month = '';
return filterTableData(this.activityData, filters);
}
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
handleFilter(filters: Record<ClientFilterTypes, string>) {
this.args.onFilterChange(filters);
}
}