mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-18 18:38:08 -05:00
* =replace client stats with donut chart viz * update chart styling * add a changelog entry * test updates * remove css changes Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com>
This commit is contained in:
parent
67b3e53325
commit
64d421da69
7 changed files with 54 additions and 37 deletions
4
changelog/_9040.txt
Normal file
4
changelog/_9040.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
```release-note:improvement
|
||||
**ui/activity**: Updates running total stats to be displayed via a donut chart.
|
||||
```
|
||||
|
||||
|
|
@ -11,24 +11,8 @@
|
|||
>
|
||||
|
||||
<:dataLeft>
|
||||
<StatText
|
||||
@label="New client total and type distribution"
|
||||
@subText="The number of new clients which interacted with Vault during the selected period."
|
||||
@value={{@runningTotals.clients}}
|
||||
@size="m"
|
||||
@tooltipText="This number is the total for the queried date range. The chart displays a monthly breakdown of total new clients per month."
|
||||
/>
|
||||
|
||||
<div class="has-top-padding-l is-flex-row gap-16">
|
||||
<StatText @label="Entity" @value={{@runningTotals.entity_clients}} @size="m" />
|
||||
<StatText @label="Non-entity" @value={{@runningTotals.non_entity_clients}} @size="m" />
|
||||
</div>
|
||||
<div class="has-top-padding-m is-flex-row gap-16">
|
||||
<StatText @label="ACME" @value={{@runningTotals.acme_clients}} @size="m" />
|
||||
{{#if this.flags.secretsSyncIsActivated}}
|
||||
<StatText @label="Secret sync" @value={{@runningTotals.secret_syncs}} @size="m" />
|
||||
{{/if}}
|
||||
</div>
|
||||
<Hds::Text::Body @tag="p">Client count and type distribution</Hds::Text::Body>
|
||||
<VaultReporting::DonutChart @data={{this.donutChartData}} @title="Total Clients" class="donut-chart" />
|
||||
</:dataLeft>
|
||||
|
||||
<:dataRight>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,17 @@ export default class RunningTotal extends Component<Args> {
|
|||
}));
|
||||
}
|
||||
|
||||
get donutChartData() {
|
||||
return [
|
||||
{ value: this.args.runningTotals.entity_clients, label: 'Entity clients' },
|
||||
{ value: this.args.runningTotals.non_entity_clients, label: 'Non-entity clients' },
|
||||
{ value: this.args.runningTotals.acme_clients, label: 'ACME clients' },
|
||||
...(this.flags.secretsSyncIsActivated
|
||||
? [{ value: this.args.runningTotals.secret_syncs, label: 'Secret sync clients' }]
|
||||
: []),
|
||||
];
|
||||
}
|
||||
|
||||
get chartLegend() {
|
||||
if (this.showStacked) {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -29,10 +29,23 @@
|
|||
gap: 1rem;
|
||||
|
||||
.item-left {
|
||||
flex: 1 1 33.3333%;
|
||||
flex: 1 1 40%;
|
||||
min-width: 0;
|
||||
}
|
||||
.item-right {
|
||||
flex: 2 1 66.6666%;
|
||||
flex: 2 1 60%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
// Stack vertically on smaller screens
|
||||
@media (max-width: 1024px) {
|
||||
flex-direction: column;
|
||||
|
||||
.item-left,
|
||||
.item-right {
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,9 @@ module('Acceptance | clients | overview', function (hooks) {
|
|||
|
||||
await login();
|
||||
await visit('/vault/clients/counts/overview');
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Secret sync')).doesNotExist();
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Entity')).exists('other stats are still visible');
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Secret sync clients')).doesNotExist();
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Entity clients')).exists('other stats are still visible');
|
||||
|
||||
await click(GENERAL.inputByAttr('toggle view'));
|
||||
assert.dom(CHARTS.legend).hasText('Entity clients Non-entity clients ACME clients');
|
||||
});
|
||||
|
|
@ -302,7 +303,9 @@ module('Acceptance | clients | overview', function (hooks) {
|
|||
test('it should show secrets sync stats when the feature is activated', async function (assert) {
|
||||
await login();
|
||||
await visit('/vault/clients/counts/overview');
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Secret sync')).exists('shows secret sync data on overview');
|
||||
assert
|
||||
.dom(CLIENT_COUNT.statLegendValue('Secret sync clients'))
|
||||
.exists('shows secret sync data on overview');
|
||||
await click(GENERAL.inputByAttr('toggle view'));
|
||||
assert
|
||||
.dom(CHARTS.legend)
|
||||
|
|
@ -321,11 +324,10 @@ module('Acceptance | clients | overview', function (hooks) {
|
|||
|
||||
await login();
|
||||
await visit('/vault/clients/counts/overview');
|
||||
|
||||
assert
|
||||
.dom(CLIENT_COUNT.statTextValue('Secret sync'))
|
||||
.dom(CLIENT_COUNT.statLegendValue('Secret sync clients'))
|
||||
.doesNotExist('stat is hidden because feature is not activated');
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Entity')).exists('other stats are still visible');
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Entity clients')).exists('other stats are still visible');
|
||||
await click(GENERAL.inputByAttr('toggle view'));
|
||||
assert
|
||||
.dom(CHARTS.legend)
|
||||
|
|
@ -341,7 +343,7 @@ module('Acceptance | clients | overview', function (hooks) {
|
|||
|
||||
await login();
|
||||
await visit('/vault/clients/counts/overview');
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Secret sync')).exists();
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Secret sync clients')).exists();
|
||||
await click(GENERAL.inputByAttr('toggle view'));
|
||||
assert
|
||||
.dom(CHARTS.legend)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ export const CLIENT_COUNT = {
|
|||
defaultRangeAlert: '[data-test-range-default-alert]',
|
||||
validation: '[data-test-date-range-validation]',
|
||||
},
|
||||
statLegendValue: (label: string) =>
|
||||
label ? `[data-test-vault-reporting-legend-item="${label}"]` : '[data-test-vault-reporting-legend-item',
|
||||
statText: (label: string) => `[data-test-stat-text="${label}"]`,
|
||||
statTextValue: (label: string) =>
|
||||
label ? `[data-test-stat-text="${label}"] .stat-value` : '[data-test-stat-text]',
|
||||
|
|
|
|||
|
|
@ -60,17 +60,16 @@ module('Integration | Component | clients/running-total', function (hooks) {
|
|||
assert.strictEqual(color, expectedColor, `actual color: ${color}, expected color: ${expectedColor}`);
|
||||
|
||||
const expectedValues = {
|
||||
'New client total and type distribution': formatNumber([this.activity.total.clients]),
|
||||
Entity: formatNumber([this.activity.total.entity_clients]),
|
||||
'Non-entity': formatNumber([this.activity.total.non_entity_clients]),
|
||||
ACME: formatNumber([this.activity.total.acme_clients]),
|
||||
'Secret sync': formatNumber([this.activity.total.secret_syncs]),
|
||||
'Entity clients': formatNumber([this.activity.total.entity_clients]),
|
||||
'Non-entity clients': formatNumber([this.activity.total.non_entity_clients]),
|
||||
'ACME clients': formatNumber([this.activity.total.acme_clients]),
|
||||
'Secret sync clients': formatNumber([this.activity.total.secret_syncs]),
|
||||
};
|
||||
for (const label in expectedValues) {
|
||||
assert
|
||||
.dom(CLIENT_COUNT.statTextValue(label))
|
||||
.dom(CLIENT_COUNT.statLegendValue(label))
|
||||
.hasText(
|
||||
`${expectedValues[label]}`,
|
||||
`${expectedValues[label]} ${label}`,
|
||||
`stat label: ${label} renders correct total: ${expectedValues[label]}`
|
||||
);
|
||||
}
|
||||
|
|
@ -162,9 +161,11 @@ module('Integration | Component | clients/running-total', function (hooks) {
|
|||
.dom(CLIENT_COUNT.card('Client usage trends for selected billing period'))
|
||||
.exists('running total component renders');
|
||||
assert.dom(CHARTS.chart('Client usage by month')).exists('bar chart renders');
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Entity')).exists();
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Non-entity')).exists();
|
||||
assert.dom(CLIENT_COUNT.statTextValue('Secret sync')).doesNotExist('does not render secret syncs');
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Entity clients')).exists();
|
||||
assert.dom(CLIENT_COUNT.statLegendValue('Non-entity clients')).exists();
|
||||
assert
|
||||
.dom(CLIENT_COUNT.statLegendValue('Secret sync clients'))
|
||||
.doesNotExist('does not render secret syncs');
|
||||
|
||||
// check toggle view
|
||||
await click(GENERAL.inputByAttr('toggle view'));
|
||||
|
|
|
|||
Loading…
Reference in a new issue