From 17552aab7d91eaa5d072a4dd04870125419bfc18 Mon Sep 17 00:00:00 2001 From: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Date: Fri, 19 Apr 2024 15:14:46 -0700 Subject: [PATCH] UI: Refactor and resuse UsageStats display template across tabs (#26562) * refactor usage stats to use Hds::Card * use usage stats in other tabs * use flex row and remove verbose grid css classes * cleanup selectors, add arg to usage stat selector * update usage stat test * update token tab usage stat title * add test coverage for description and title --- ui/app/components/clients/page/acme.hbs | 10 +- ui/app/components/clients/page/sync.hbs | 10 +- ui/app/components/clients/page/token.hbs | 36 ++++-- ui/app/components/clients/running-total.hbs | 121 ++++++++++-------- ui/app/components/clients/usage-stats.hbs | 88 ++++--------- ui/app/components/dashboard/overview.hbs | 10 +- .../dashboard/secrets-engines-card.hbs | 2 +- ui/app/styles/core/charts.scss | 30 ----- .../helper-classes/flexbox-and-grid.scss | 8 +- .../addon/components/secrets/landing-cta.hbs | 2 +- .../clients/counts/overview-test.js | 6 +- .../helpers/clients/client-count-selectors.ts | 4 +- .../components/clients/page/acme-test.js | 6 +- .../components/clients/page/sync-test.js | 4 +- .../components/clients/usage-stats-test.js | 84 ++---------- 15 files changed, 167 insertions(+), 254 deletions(-) diff --git a/ui/app/components/clients/page/acme.hbs b/ui/app/components/clients/page/acme.hbs index f63d2823b1..1b7dde64f7 100644 --- a/ui/app/components/clients/page/acme.hbs +++ b/ui/app/components/clients/page/acme.hbs @@ -88,11 +88,7 @@ {{/if}} {{else}} -
-
-

{{this.title}}

-

{{this.description}}

-
- -
+ + + {{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/page/sync.hbs b/ui/app/components/clients/page/sync.hbs index 1a4571bf1b..20b830f6ed 100644 --- a/ui/app/components/clients/page/sync.hbs +++ b/ui/app/components/clients/page/sync.hbs @@ -54,13 +54,9 @@ {{else}} -
-
-

{{this.title}}

-

{{this.description}}

-
- -
+ + + {{/if}} {{else}} {{else}} - {{! UsageStats render when viewing a single, historical month AND activity data predates new client breakdown (< v1.10.0) - or viewing the current month filtered down to auth method }} + {{! Renders when viewing a single month or activity log data that predates the monthly breakdown added in 1.11 }} + > + + + + {{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/running-total.hbs b/ui/app/components/clients/running-total.hbs index e664a63962..06e50130ba 100644 --- a/ui/app/components/clients/running-total.hbs +++ b/ui/app/components/clients/running-total.hbs @@ -43,57 +43,42 @@ {{else}} {{#let (get @byMonthActivityData "0") as |singleMonthData|}} {{#if (and @isHistoricalMonth singleMonthData.new_clients.clients)}} -
-
-

Vault client counts

-

- The total billable clients in the specified date range. This includes entity, non-entity, and Secret sync - clients. The total client count number is an important consideration for Vault billing. -

-
-
-
- -
- + +
- - {{#if @isSecretsSyncActivated}} - - {{/if}} -
-
-
- +
+ + + + {{#if @isSecretsSyncActivated}} + + {{/if}}
- - - - {{#if @isSecretsSyncActivated}} - - {{/if}}
-
+
+ +
+ + + + {{#if @isSecretsSyncActivated}} + + {{/if}} +
+
+
{{else}} {{! Renders when viewing the current month or for activity log data that predates the monthly breakdown added in 1.11 }} + > + + + + + {{#if @isSecretsSyncActivated}} + + {{/if}} + {{/if}} {{/let}} {{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/usage-stats.hbs b/ui/app/components/clients/usage-stats.hbs index 8ce8de30d0..1dade4c6c1 100644 --- a/ui/app/components/clients/usage-stats.hbs +++ b/ui/app/components/clients/usage-stats.hbs @@ -3,68 +3,34 @@ SPDX-License-Identifier: BUSL-1.1 ~}} -
- \ No newline at end of file + \ No newline at end of file diff --git a/ui/app/components/dashboard/overview.hbs b/ui/app/components/dashboard/overview.hbs index d8fca59d94..f87059d5fe 100644 --- a/ui/app/components/dashboard/overview.hbs +++ b/ui/app/components/dashboard/overview.hbs @@ -6,9 +6,9 @@
-
+
{{#if (and @version.isEnterprise (or @license @isRootNamespace))}} -
+
{{#if @license}} {{/if}} @@ -25,7 +25,7 @@
-
+
{{#if @vaultConfiguration}} @@ -37,14 +37,14 @@
{{else}} -
+
-
+
{{#if @vaultConfiguration}} diff --git a/ui/app/components/dashboard/secrets-engines-card.hbs b/ui/app/components/dashboard/secrets-engines-card.hbs index 3eb7756da7..6e4fb2a4ea 100644 --- a/ui/app/components/dashboard/secrets-engines-card.hbs +++ b/ui/app/components/dashboard/secrets-engines-card.hbs @@ -23,7 +23,7 @@ <:body as |B|> {{#each this.firstFiveSecretsEngines as |backend|}} - +
{{#if backend.icon}} diff --git a/ui/app/styles/core/charts.scss b/ui/app/styles/core/charts.scss index 67c51a0bf9..2007776059 100644 --- a/ui/app/styles/core/charts.scss +++ b/ui/app/styles/core/charts.scss @@ -11,36 +11,6 @@ } // GRID LAYOUT // -.single-month-grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 2em; - width: 100%; -} -.single-month-stats { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 1em; - width: 100%; - margin-bottom: 1rem; - .column-start-1 { - grid-column-start: 1; - } - .column-start-2 { - grid-column-start: 2; - } - .column-start-3 { - grid-column-start: 3; - } - .column-start-4 { - grid-column-start: 4; - } -} -.single-month-section-title { - grid-column-start: 1; - grid-column-end: span col3-end; -} - .single-chart-grid { display: grid; grid-template-columns: 1fr 0.3fr 3.7fr; diff --git a/ui/app/styles/helper-classes/flexbox-and-grid.scss b/ui/app/styles/helper-classes/flexbox-and-grid.scss index 868552581f..e8cdada74a 100644 --- a/ui/app/styles/helper-classes/flexbox-and-grid.scss +++ b/ui/app/styles/helper-classes/flexbox-and-grid.scss @@ -46,14 +46,18 @@ flex-direction: row; } -.has-gap-m { +.gap-16 { gap: $spacing-16; } -.has-gap-l { +.gap-24 { gap: $spacing-24; } +.gap-36 { + gap: $spacing-36; +} + // Alignment of the items .is-flex-v-centered { display: flex; diff --git a/ui/lib/sync/addon/components/secrets/landing-cta.hbs b/ui/lib/sync/addon/components/secrets/landing-cta.hbs index 436f03d257..b77c376d79 100644 --- a/ui/lib/sync/addon/components/secrets/landing-cta.hbs +++ b/ui/lib/sync/addon/components/secrets/landing-cta.hbs @@ -39,7 +39,7 @@ {{/if}}
-
+
Secrets sync destinations diagram

diff --git a/ui/tests/acceptance/clients/counts/overview-test.js b/ui/tests/acceptance/clients/counts/overview-test.js index 237a937f6f..3f4afab8cf 100644 --- a/ui/tests/acceptance/clients/counts/overview-test.js +++ b/ui/tests/acceptance/clients/counts/overview-test.js @@ -74,7 +74,7 @@ module('Acceptance | clients | overview', function (hooks) { await click('[data-test-previous-year]'); await click(`[data-test-calendar-month=${ARRAY_OF_MONTHS[LICENSE_START.getMonth()]}]`); assert - .dom(CLIENT_COUNT.runningTotalMonthStats) + .dom(CLIENT_COUNT.usageStats('Vault client counts')) .doesNotExist('running total single month stat boxes do not show'); assert .dom(CLIENT_COUNT.chartContainer('Vault client counts')) @@ -118,7 +118,9 @@ module('Acceptance | clients | overview', function (hooks) { assert.dom('[data-test-display-year]').hasText('2024'); await click('[data-test-previous-year]'); await click('[data-test-calendar-month="September"]'); - assert.dom(CLIENT_COUNT.runningTotalMonthStats).exists('running total single month stat boxes show'); + assert + .dom(CLIENT_COUNT.usageStats('Vault client counts')) + .exists('running total single month usage stats show'); assert .dom(CLIENT_COUNT.chartContainer('Vault client counts')) .doesNotExist('running total month over month charts do not show'); diff --git a/ui/tests/helpers/clients/client-count-selectors.ts b/ui/tests/helpers/clients/client-count-selectors.ts index 3b65f36b59..dba0d85895 100644 --- a/ui/tests/helpers/clients/client-count-selectors.ts +++ b/ui/tests/helpers/clients/client-count-selectors.ts @@ -39,7 +39,7 @@ export const CLIENT_COUNT = { plotPoint: '[data-test-line-chart="plot-point"]', }, }, - usageStats: '[data-test-usage-stats]', + usageStats: (title: string) => `[data-test-usage-stats="${title}"]`, dateDisplay: '[data-test-date-display]', attributionBlock: '[data-test-clients-attribution]', filterBar: '[data-test-clients-filter-bar]', @@ -63,8 +63,6 @@ export const CLIENT_COUNT = { nextYear: '[data-test-next-year]', calendarMonth: (month: string) => `[data-test-calendar-month="${month}"]`, }, - runningTotalMonthStats: '[data-test-running-total="single-month-stats"]', - runningTotalMonthlyCharts: '[data-test-running-total="monthly-charts"]', selectedAuthMount: 'div#mounts-search-select [data-test-selected-option] div', selectedNs: 'div#namespace-search-select [data-test-selected-option] div', upgradeWarning: '[data-test-clients-upgrade-warning]', diff --git a/ui/tests/integration/components/clients/page/acme-test.js b/ui/tests/integration/components/clients/page/acme-test.js index 9306c98e83..daa0566d4a 100644 --- a/ui/tests/integration/components/clients/page/acme-test.js +++ b/ui/tests/integration/components/clients/page/acme-test.js @@ -100,9 +100,9 @@ module('Integration | Component | clients | Clients::Page::Acme', function (hook assert.dom(statText('Average ACME clients per month')).doesNotExist(); assert.dom(statText('Average new ACME clients per month')).doesNotExist(); assert - .dom(usageStats) + .dom(usageStats('ACME usage')) .hasText( - `ACME usage This data can be used to understand how many ACME clients have been used for the queried month. Each ACME request is counted as one client. Total ACME clients ${expectedTotal}`, + `ACME usage Usage metrics tutorial This data can be used to understand how many ACME clients have been used for the queried month. Each ACME request is counted as one client. Total ACME clients ${expectedTotal}`, 'it renders usage stats with single month copy' ); }); @@ -127,7 +127,7 @@ module('Integration | Component | clients | Clients::Page::Acme', function (hook assert.dom(statText('Total ACME clients')).doesNotExist(); assert.dom(statText('Average ACME clients per month')).doesNotExist(); assert.dom(statText('Average new ACME clients per month')).doesNotExist(); - assert.dom(usageStats).doesNotExist(); + assert.dom(usageStats('ACME usage')).doesNotExist(); }); test('it should render empty state when ACME data does not exist for a single month', async function (assert) { diff --git a/ui/tests/integration/components/clients/page/sync-test.js b/ui/tests/integration/components/clients/page/sync-test.js index bf64df84cd..ab9318db4d 100644 --- a/ui/tests/integration/components/clients/page/sync-test.js +++ b/ui/tests/integration/components/clients/page/sync-test.js @@ -119,9 +119,9 @@ module('Integration | Component | clients | Clients::Page::Sync', function (hook assert.dom(charts.chart('Secrets sync usage')).doesNotExist('vertical bar chart does not render'); assert - .dom(usageStats) + .dom(usageStats('Secrets sync usage')) .hasText( - `Secrets sync usage This data can be used to understand how many secrets sync clients have been used for this date range. Each Vault secret that is synced to at least one destination counts as one Vault client. Total sync clients ${total}`, + `Secrets sync usage Usage metrics tutorial This data can be used to understand how many secrets sync clients have been used for this date range. Each Vault secret that is synced to at least one destination counts as one Vault client. Total sync clients ${total}`, 'renders sync stats instead of chart' ); assert.dom(statText('Average total clients per month')).doesNotExist('total sync counts does not exist'); diff --git a/ui/tests/integration/components/clients/usage-stats-test.js b/ui/tests/integration/components/clients/usage-stats-test.js index 15943a8523..c06166acf6 100644 --- a/ui/tests/integration/components/clients/usage-stats-test.js +++ b/ui/tests/integration/components/clients/usage-stats-test.js @@ -11,80 +11,22 @@ import { hbs } from 'ember-cli-htmlbars'; module('Integration | Component | clients/usage-stats', function (hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function () { - this.showSecretSyncs = false; - this.counts = {}; + test('it renders', async function (assert) { + await render( + hbs` + + yielded content! + ` + ); - this.renderComponent = async () => - await render( - hbs`` - ); - }); - - test('it renders defaults', async function (assert) { - await this.renderComponent(); - - assert.dom('[data-test-stat-text]').exists({ count: 4 }, 'Renders 4 Stat texts even with no data passed'); - assert.dom('[data-test-stat-text="Total clients"]').exists('Total clients exists'); - assert.dom('[data-test-stat-text="Total clients"] .stat-value').hasText('-', 'renders dash when no data'); - assert.dom('[data-test-stat-text="Entity"]').exists('Entity exists'); - assert.dom('[data-test-stat-text="Entity"] .stat-value').hasText('-', 'renders dash when no data'); - assert.dom('[data-test-stat-text="Non-entity"]').exists('Non entity clients exists'); - assert.dom('[data-test-stat-text="Non-entity"] .stat-value').hasText('-', 'renders dash when no data'); + assert.dom('[data-test-usage-stats="My stats"]').exists(); + assert.dom('h3').hasText('My stats', 'title renders in h3 tag'); + assert.dom('p').hasText('a very important description', 'description renders in p tag'); + assert + .dom('[data-test-usage-stats="My stats"]') + .hasTextContaining('yielded content!', 'it renders yielded content'); assert .dom('a') .hasAttribute('href', 'https://developer.hashicorp.com/vault/tutorials/monitoring/usage-metrics'); }); - - test('it renders with token data', async function (assert) { - this.counts = { - clients: 17, - entity_clients: 7, - non_entity_clients: 10, - }; - - await this.renderComponent(); - - assert.dom('[data-test-stat-text]').exists({ count: 4 }, 'Renders 4 Stat texts'); - assert - .dom('[data-test-stat-text="Total clients"] .stat-value') - .hasText('17', 'Total clients shows passed value'); - assert - .dom('[data-test-stat-text="Entity"] .stat-value') - .hasText('7', 'entity clients shows passed value'); - assert - .dom('[data-test-stat-text="Non-entity"] .stat-value') - .hasText('10', 'non entity clients shows passed value'); - }); - - module('it renders with full totals data', function (hooks) { - hooks.beforeEach(function () { - this.counts = { - clients: 22, - entity_clients: 7, - non_entity_clients: 10, - secret_syncs: 5, - }; - }); - - test('with secrets sync activated', async function (assert) { - this.showSecretSyncs = true; - - await this.renderComponent(); - - assert.dom('[data-test-stat-text]').exists({ count: 5 }, 'Renders 5 Stat texts'); - assert - .dom('[data-test-stat-text="Secret sync"] .stat-value') - .hasText('5', 'secrets sync clients shows passed value'); - }); - - test('with secrets sync NOT activated', async function (assert) { - this.showSecretSyncs = false; - - await this.renderComponent(); - - assert.dom('[data-test-stat-text]').exists({ count: 4 }, 'Renders 4 Stat texts'); - assert.dom('[data-test-stat-text="Secret sync"] .stat-value').doesNotExist(); - }); - }); });