UI/Clients monthly usage component (#15012)

* clarify timestamp in jsdocs

* make title bottom margin smaller

* add monthly usage component

* fix doubled up css

* clean up average helpers

* copy update

* change arg to component variable

* fix awkward grammar

* clean up mirage handler

* address comments

* remove prop
This commit is contained in:
claire bontempo 2022-04-12 17:49:35 -05:00 committed by GitHub
parent 112d622b40
commit 85b2263dce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 757 additions and 766 deletions

View File

@ -27,7 +27,7 @@ import { inject as service } from '@ember/service';
* @param {string} startTimeDisplay - start date for CSV modal
* @param {string} endTimeDisplay - end date for CSV modal
* @param {boolean} isDateRange - getter calculated in parent to relay if dataset is a date range or single month
* @param {string} timestamp - timestamp response was received from API
* @param {string} timestamp - ISO timestamp created in serializer to timestamp the response
*/
export default class Attribution extends Component {

View File

@ -22,7 +22,6 @@ import { LIGHT_AND_DARK_BLUE, SVG_DIMENSIONS, formatNumbers } from '../../utils/
*/
export default class LineChart extends Component {
// TODO CMB make just one tracked variable tooltipText?
@tracked tooltipTarget = '';
@tracked tooltipMonth = '';
@tracked tooltipTotal = '';

View File

@ -9,10 +9,12 @@ import { mean } from 'd3-array';
* ```js
<Clients::MonthlyUsage
@chartLegend={{this.chartLegend}}
@verticalBarChartData={{this.byMonth}}
@timestamp={{this.responseTimestamp}}
@verticalBarChartData={{this.byMonthTotalClients}}
/>
* ```
* @param {array} chartLegend - array of objects with key names 'key' and 'label' so data can be stacked
* @param {string} timestamp - ISO timestamp created in serializer to timestamp the response
* @param {array} verticalBarChartData - array of flattened objects
sample object =
{
@ -31,13 +33,15 @@ import { mean } from 'd3-array';
* @param {array} chartLegend - array of objects with key names 'key' and 'label' so data can be stacked
*/
export default class MonthlyUsage extends Component {
barChartData = this.args.verticalBarChartData;
get averageTotalClients() {
let average = mean(this.args.verticalBarChartData?.map((d) => d.total));
let average = mean(this.barChartData?.map((d) => d.total));
return Math.round(average) || null;
}
get averageNewClients() {
let average = mean(this.args.verticalBarChartData?.map((d) => d.new_clients));
let average = mean(this.barChartData?.map((d) => d.new_clients.total));
return Math.round(average) || null;
}
}

View File

@ -34,30 +34,21 @@ import { mean } from 'd3-array';
* @param {array} barChartData - array of objects, object example: { month: '1/22', entity_clients: 11, non_entity_clients: 36, total: 47, namespaces: [] };
* @param {array} chartLegend - array of objects with key names 'key' and 'label' so data can be stacked
* @param {object} runningTotals - top level totals from /activity response { clients: 3517, entity_clients: 1593, non_entity_clients: 1924 }
* @param {string} timestamp - ISO timestamp created in serializer to timestamp the response
*
*/
export default class RunningTotal extends Component {
get getTotalClients() {
return (
this.args.chartLegend?.map((legend) => {
return {
label: legend.label,
total: this.args.runningTotals[legend.key],
};
}) || null
);
get entityClientData() {
return {
runningTotal: this.args.runningTotals.entity_clients,
averageNewClients: Math.round(mean(this.args.barChartData?.map((d) => d.entity_clients))),
};
}
get getAverageNewClients() {
// maps through legend and creates array of objects
// e.g. {label: 'unique entities', average: 43}
return (
this.args.chartLegend?.map((legend) => {
return {
label: legend.label,
average: Math.round(mean(this.args.barChartData?.map((d) => d[legend.key]))),
};
}) || null
);
get nonEntityClientData() {
return {
runningTotal: this.args.runningTotals.non_entity_clients,
averageNewClients: Math.round(mean(this.args.barChartData?.map((d) => d.non_entity_clients))),
};
}
}

View File

@ -91,7 +91,7 @@ export default class VerticalBarChart extends Component {
.nice();
let yAxis = axisLeft(yAxisScale)
.ticks(6)
.ticks(4)
.tickPadding(10)
.tickSizeInner(-SVG_DIMENSIONS.width)
.tickFormat(formatNumbers);

View File

@ -30,10 +30,6 @@
grid-column-end: span col4-end;
grid-row-start: 1;
box-shadow: inset 0 -1px 0 $vault-gray-200;
> h2 {
padding-bottom: $spacing-xs;
}
}
.has-header-link {
@ -165,7 +161,7 @@ h2.chart-title {
font-weight: $font-weight-bold;
font-size: $size-5;
line-height: $spacing-l;
margin-bottom: $spacing-xs;
margin-bottom: $spacing-xxs;
}
p.chart-description {

View File

@ -131,15 +131,18 @@
<LayoutLoading />
{{else}}
{{#if this.totalUsageCounts}}
<Clients::RunningTotal
@chartLegend={{this.chartLegend}}
@barChartData={{this.byMonthNewClients}}
@lineChartData={{this.byMonthTotalClients}}
@runningTotals={{this.totalUsageCounts}}
@timestamp={{this.responseTimestamp}}
/>
{{! TODO CMB: remove UsageStats component from history tab (and update associated tests) }}
<Clients::UsageStats @title="Total usage" @totalUsageCounts={{this.totalUsageCounts}} />
{{#unless this.byMonthTotalClients}}
<Clients::UsageStats @title="Total usage" @totalUsageCounts={{this.totalUsageCounts}} />
{{/unless}}
{{#if this.byMonthTotalClients}}
<Clients::RunningTotal
@chartLegend={{this.chartLegend}}
@lineChartData={{this.byMonthTotalClients}}
@barChartData={{this.byMonthNewClients}}
@runningTotals={{this.totalUsageCounts}}
@timestamp={{this.responseTimestamp}}
/>
{{/if}}
{{#if this.hasAttributionData}}
<Clients::Attribution
@chartLegend={{this.chartLegend}}
@ -152,6 +155,13 @@
@timestamp={{this.responseTimestamp}}
/>
{{/if}}
{{#if this.byMonthTotalClients}}
<Clients::MonthlyUsage
@chartLegend={{this.chartLegend}}
@verticalBarChartData={{this.byMonthTotalClients}}
@timestamp={{this.responseTimestamp}}
/>
{{/if}}
{{/if}}
{{/if}}
{{else if (and (not @model.startTimeFromLicense) (not this.startTimeFromResponse))}}

View File

@ -2,8 +2,7 @@
<div class="chart-header has-bottom-margin-xl">
<h2 class="chart-title">Vault usage</h2>
<p class="chart-description">
This data can be used to understand how many total clients are using Vault each month for the time period selected
above.
This data can be used to understand how many total clients are using Vault each month for this date range.
</p>
</div>
@ -14,38 +13,29 @@
<div class="chart-subTitle">
<h2 class="chart-title">Total monthly clients</h2>
<p class="chart-subtext">
Each unique client is counted once per month. This can help with capacity planning.
Each client is counted once per month. This can help with capacity planning.
</p>
</div>
<div class="data-details-top">
<h3 class="data-details">Average total clients per month</h3>
<p class="data-details">
{{#if this.averageTotalClients}}
{{format-number this.averageTotalClients}}
{{else}}
<span class="has-text-danger is-size-8">
<Icon @name="x-square-fill" />Average cannot be calculated
</span>
{{/if}}
{{format-number this.averageTotalClients}}
</p>
</div>
<div class="data-details-bottom">
<h3 class="data-details">Average new clients per month</h3>
<p class="data-details">
{{#if this.averageNewClients}}
{{format-number this.averageNewClients}}
{{else}}
<span class="has-text-danger is-size-8">
<Icon @name="x-square-fill" />Average cannot be calculated
</span>
{{/if}}
{{format-number this.averageNewClients}}
</p>
</div>
<div class="timestamp">
Updated Nov 15 2021, 4:07:32 pm
{{#if @timestamp}}
Updated
{{date-format @timestamp "MMM d yyyy, h:mm:ss aaa"}}
{{/if}}
</div>
<div class="legend-right">

View File

@ -16,23 +16,18 @@
<h2 class="chart-title">Running client total</h2>
<p class="chart-subtext">The number of clients which interacted with Vault during this date range. </p>
</div>
<div class="data-details-top">
{{#let (get this.getTotalClients 0) as |stat|}}
<h3 class="data-details">Entity clients</h3>
<p class="data-details">
{{format-number stat.total}}
</p>
{{/let}}
<h3 class="data-details">Entity clients</h3>
<p class="data-details">
{{format-number this.entityClientData.runningTotal}}
</p>
</div>
<div class="data-details-bottom">
{{#let (get this.getTotalClients 1) as |stat|}}
<h3 class="data-details">Non-entity clients</h3>
<p class="data-details">
{{format-number stat.total}}
</p>
{{/let}}
<h3 class="data-details">Non-entity clients</h3>
<p class="data-details">
{{format-number this.nonEntityClientData.runningTotal}}
</p>
</div>
<div class="legend-right">
@ -54,21 +49,17 @@
</div>
<div class="data-details-top">
{{#let (get this.getAverageNewClients 0) as |stat|}}
<h3 class="data-details">Average new entity clients per month</h3>
<p class="data-details">
{{format-number stat.average}}
</p>
{{/let}}
<h3 class="data-details">Average new entity clients per month</h3>
<p class="data-details">
{{format-number this.entityClientData.averageNewClients}}
</p>
</div>
<div class="data-details-bottom">
{{#let (get this.getAverageNewClients 1) as |stat|}}
<h3 class="data-details">Average new non-entity clients per month</h3>
<p class="data-details">
{{format-number stat.average}}
</p>
{{/let}}
<h3 class="data-details">Average new non-entity clients per month</h3>
<p class="data-details">
{{format-number this.nonEntityClientData.averageNewClients}}
</p>
</div>
<div class="timestamp">

View File

@ -1,7 +1,7 @@
<div class="chart-wrapper" data-test-usage-stats>
<div class="chart-header has-header-link has-bottom-margin-m">
<div class="header-left">
<h2 class="chart-title has-bottom-margin-xs">{{@title}}</h2>
<h2 class="chart-title">{{@title}}</h2>
<p class="chart-description"> These totals are within this namespace and all its children. </p>
</div>
<div class="header-right">

File diff suppressed because it is too large Load Diff