vault/ui/app/components/clients/activity.ts
lane-wetmore cdbb0c49cc
UI: Vault update client count charts to show new clients only (#30506)
* increase bar width, show new clients only, add timestamp to header, update bar color

* remove extra timestamps, switch to basic bar chart

* update docs and styling

* remove unneeded timestamp args

* show new client running totatls

* initial test updates

* update test

* clean up new client total calc into util fn

* bits of clean up and todos

* update tests

* update to avoid activity call when in CE and missing either start or end time

* update todos

* update tests

* tidying

* move new client total onto payload for easier access

* update more tests to align with copy changes and new client totals

* remove addressed TODOs

* Update comment

* add changelog entry

* revert to using total, update tests and clean up

* Update ui/app/components/clients/page/counts.hbs

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>

* remove duplicate charts and update descriptions

* update tests after removing extra charts

* tidy

* update instances of byMonthActivityData to use byMonthNewClients and update tests

* Update ui/app/components/clients/running-total.ts

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>

* update chart styles

---------

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
2025-05-19 15:57:32 -05:00

103 lines
3.2 KiB
TypeScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
// base component for counts child routes that can be extended as needed
// contains getters that filter and extract data from activity model for use in charts
import Component from '@glimmer/component';
import { isSameMonth } from 'date-fns';
import { parseAPITimestamp } from 'core/utils/date-formatters';
import { calculateAverage } from 'vault/utils/chart-helpers';
import {
filterByMonthDataForMount,
filteredTotalForMount,
filterVersionHistory,
} from 'core/utils/client-count-utils';
import { service } from '@ember/service';
import { sanitizePath } from 'core/utils/sanitize-path';
import type ClientsActivityModel from 'vault/models/clients/activity';
import type ClientsVersionHistoryModel from 'vault/models/clients/version-history';
import type {
ByMonthNewClients,
MountNewClients,
NamespaceByKey,
NamespaceNewClients,
TotalClients,
} from 'core/utils/client-count-utils';
import type NamespaceService from 'vault/services/namespace';
interface Args {
activity: ClientsActivityModel;
versionHistory: ClientsVersionHistoryModel[];
startTimestamp: string;
endTimestamp: string;
namespace: string;
mountPath: string;
}
export default class ClientsActivityComponent extends Component<Args> {
@service declare readonly namespace: NamespaceService;
average = (
data:
| (ByMonthNewClients | NamespaceNewClients | MountNewClients | undefined)[]
| (NamespaceByKey | undefined)[],
key: string
) => {
return calculateAverage(data, key);
};
// path of the filtered namespace OR current one, for filtering relevant data
get namespacePathForFilter() {
const { namespace } = this.args;
const currentNs = this.namespace.currentNamespace;
return sanitizePath(namespace || currentNs || 'root');
}
get byMonthNewClients() {
const { activity, mountPath } = this.args;
const nsPath = this.namespacePathForFilter;
const data = mountPath
? filterByMonthDataForMount(activity.byMonth, nsPath, mountPath)
: activity.byMonth;
return data ? data?.map((m) => m?.new_clients) : [];
}
get isCurrentMonth() {
const { activity } = this.args;
const current = parseAPITimestamp(activity.responseTimestamp) as Date;
const start = parseAPITimestamp(activity.startTime) as Date;
const end = parseAPITimestamp(activity.endTime) as Date;
return isSameMonth(start, current) && isSameMonth(end, current);
}
get isDateRange() {
const { activity } = this.args;
return !isSameMonth(
parseAPITimestamp(activity.startTime) as Date,
parseAPITimestamp(activity.endTime) as Date
);
}
// (object) top level TOTAL client counts for given date range
get totalUsageCounts(): TotalClients {
const { namespace, activity, mountPath } = this.args;
// only do this if we have a mountPath filter.
// namespace is filtered on API layer
if (activity?.byNamespace && namespace && mountPath) {
return filteredTotalForMount(activity.byNamespace, namespace, mountPath);
}
return activity?.total;
}
get upgradesDuringActivity() {
const { versionHistory, activity } = this.args;
return filterVersionHistory(versionHistory, activity.startTime, activity.endTime);
}
}