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:
parent
112d622b40
commit
85b2263dce
|
@ -27,7 +27,7 @@ import { inject as service } from '@ember/service';
|
||||||
* @param {string} startTimeDisplay - start date for CSV modal
|
* @param {string} startTimeDisplay - start date for CSV modal
|
||||||
* @param {string} endTimeDisplay - end 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 {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 {
|
export default class Attribution extends Component {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { LIGHT_AND_DARK_BLUE, SVG_DIMENSIONS, formatNumbers } from '../../utils/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class LineChart extends Component {
|
export default class LineChart extends Component {
|
||||||
// TODO CMB make just one tracked variable tooltipText?
|
|
||||||
@tracked tooltipTarget = '';
|
@tracked tooltipTarget = '';
|
||||||
@tracked tooltipMonth = '';
|
@tracked tooltipMonth = '';
|
||||||
@tracked tooltipTotal = '';
|
@tracked tooltipTotal = '';
|
||||||
|
|
|
@ -9,10 +9,12 @@ import { mean } from 'd3-array';
|
||||||
* ```js
|
* ```js
|
||||||
<Clients::MonthlyUsage
|
<Clients::MonthlyUsage
|
||||||
@chartLegend={{this.chartLegend}}
|
@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
|
* @param {array} verticalBarChartData - array of flattened objects
|
||||||
sample object =
|
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
|
* @param {array} chartLegend - array of objects with key names 'key' and 'label' so data can be stacked
|
||||||
*/
|
*/
|
||||||
export default class MonthlyUsage extends Component {
|
export default class MonthlyUsage extends Component {
|
||||||
|
barChartData = this.args.verticalBarChartData;
|
||||||
|
|
||||||
get averageTotalClients() {
|
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;
|
return Math.round(average) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get averageNewClients() {
|
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;
|
return Math.round(average) || null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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} 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 {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 {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 {
|
export default class RunningTotal extends Component {
|
||||||
get getTotalClients() {
|
get entityClientData() {
|
||||||
return (
|
return {
|
||||||
this.args.chartLegend?.map((legend) => {
|
runningTotal: this.args.runningTotals.entity_clients,
|
||||||
return {
|
averageNewClients: Math.round(mean(this.args.barChartData?.map((d) => d.entity_clients))),
|
||||||
label: legend.label,
|
};
|
||||||
total: this.args.runningTotals[legend.key],
|
|
||||||
};
|
|
||||||
}) || null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get getAverageNewClients() {
|
get nonEntityClientData() {
|
||||||
// maps through legend and creates array of objects
|
return {
|
||||||
// e.g. {label: 'unique entities', average: 43}
|
runningTotal: this.args.runningTotals.non_entity_clients,
|
||||||
return (
|
averageNewClients: Math.round(mean(this.args.barChartData?.map((d) => d.non_entity_clients))),
|
||||||
this.args.chartLegend?.map((legend) => {
|
};
|
||||||
return {
|
|
||||||
label: legend.label,
|
|
||||||
average: Math.round(mean(this.args.barChartData?.map((d) => d[legend.key]))),
|
|
||||||
};
|
|
||||||
}) || null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ export default class VerticalBarChart extends Component {
|
||||||
.nice();
|
.nice();
|
||||||
|
|
||||||
let yAxis = axisLeft(yAxisScale)
|
let yAxis = axisLeft(yAxisScale)
|
||||||
.ticks(6)
|
.ticks(4)
|
||||||
.tickPadding(10)
|
.tickPadding(10)
|
||||||
.tickSizeInner(-SVG_DIMENSIONS.width)
|
.tickSizeInner(-SVG_DIMENSIONS.width)
|
||||||
.tickFormat(formatNumbers);
|
.tickFormat(formatNumbers);
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
grid-column-end: span col4-end;
|
grid-column-end: span col4-end;
|
||||||
grid-row-start: 1;
|
grid-row-start: 1;
|
||||||
box-shadow: inset 0 -1px 0 $vault-gray-200;
|
box-shadow: inset 0 -1px 0 $vault-gray-200;
|
||||||
|
|
||||||
> h2 {
|
|
||||||
padding-bottom: $spacing-xs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.has-header-link {
|
.has-header-link {
|
||||||
|
@ -165,7 +161,7 @@ h2.chart-title {
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
font-size: $size-5;
|
font-size: $size-5;
|
||||||
line-height: $spacing-l;
|
line-height: $spacing-l;
|
||||||
margin-bottom: $spacing-xs;
|
margin-bottom: $spacing-xxs;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.chart-description {
|
p.chart-description {
|
||||||
|
|
|
@ -131,15 +131,18 @@
|
||||||
<LayoutLoading />
|
<LayoutLoading />
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if this.totalUsageCounts}}
|
{{#if this.totalUsageCounts}}
|
||||||
<Clients::RunningTotal
|
{{#unless this.byMonthTotalClients}}
|
||||||
@chartLegend={{this.chartLegend}}
|
<Clients::UsageStats @title="Total usage" @totalUsageCounts={{this.totalUsageCounts}} />
|
||||||
@barChartData={{this.byMonthNewClients}}
|
{{/unless}}
|
||||||
@lineChartData={{this.byMonthTotalClients}}
|
{{#if this.byMonthTotalClients}}
|
||||||
@runningTotals={{this.totalUsageCounts}}
|
<Clients::RunningTotal
|
||||||
@timestamp={{this.responseTimestamp}}
|
@chartLegend={{this.chartLegend}}
|
||||||
/>
|
@lineChartData={{this.byMonthTotalClients}}
|
||||||
{{! TODO CMB: remove UsageStats component from history tab (and update associated tests) }}
|
@barChartData={{this.byMonthNewClients}}
|
||||||
<Clients::UsageStats @title="Total usage" @totalUsageCounts={{this.totalUsageCounts}} />
|
@runningTotals={{this.totalUsageCounts}}
|
||||||
|
@timestamp={{this.responseTimestamp}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
{{#if this.hasAttributionData}}
|
{{#if this.hasAttributionData}}
|
||||||
<Clients::Attribution
|
<Clients::Attribution
|
||||||
@chartLegend={{this.chartLegend}}
|
@chartLegend={{this.chartLegend}}
|
||||||
|
@ -152,6 +155,13 @@
|
||||||
@timestamp={{this.responseTimestamp}}
|
@timestamp={{this.responseTimestamp}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if this.byMonthTotalClients}}
|
||||||
|
<Clients::MonthlyUsage
|
||||||
|
@chartLegend={{this.chartLegend}}
|
||||||
|
@verticalBarChartData={{this.byMonthTotalClients}}
|
||||||
|
@timestamp={{this.responseTimestamp}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else if (and (not @model.startTimeFromLicense) (not this.startTimeFromResponse))}}
|
{{else if (and (not @model.startTimeFromLicense) (not this.startTimeFromResponse))}}
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
<div class="chart-header has-bottom-margin-xl">
|
<div class="chart-header has-bottom-margin-xl">
|
||||||
<h2 class="chart-title">Vault usage</h2>
|
<h2 class="chart-title">Vault usage</h2>
|
||||||
<p class="chart-description">
|
<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
|
This data can be used to understand how many total clients are using Vault each month for this date range.
|
||||||
above.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -14,38 +13,29 @@
|
||||||
<div class="chart-subTitle">
|
<div class="chart-subTitle">
|
||||||
<h2 class="chart-title">Total monthly clients</h2>
|
<h2 class="chart-title">Total monthly clients</h2>
|
||||||
<p class="chart-subtext">
|
<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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-top">
|
<div class="data-details-top">
|
||||||
<h3 class="data-details">Average total clients per month</h3>
|
<h3 class="data-details">Average total clients per month</h3>
|
||||||
<p class="data-details">
|
<p class="data-details">
|
||||||
{{#if this.averageTotalClients}}
|
{{format-number 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}}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-bottom">
|
<div class="data-details-bottom">
|
||||||
<h3 class="data-details">Average new clients per month</h3>
|
<h3 class="data-details">Average new clients per month</h3>
|
||||||
<p class="data-details">
|
<p class="data-details">
|
||||||
{{#if this.averageNewClients}}
|
{{format-number 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}}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="timestamp">
|
<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>
|
||||||
|
|
||||||
<div class="legend-right">
|
<div class="legend-right">
|
||||||
|
|
|
@ -16,23 +16,18 @@
|
||||||
<h2 class="chart-title">Running client total</h2>
|
<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>
|
<p class="chart-subtext">The number of clients which interacted with Vault during this date range. </p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-top">
|
<div class="data-details-top">
|
||||||
{{#let (get this.getTotalClients 0) as |stat|}}
|
<h3 class="data-details">Entity clients</h3>
|
||||||
<h3 class="data-details">Entity clients</h3>
|
<p class="data-details">
|
||||||
<p class="data-details">
|
{{format-number this.entityClientData.runningTotal}}
|
||||||
{{format-number stat.total}}
|
</p>
|
||||||
</p>
|
|
||||||
{{/let}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-bottom">
|
<div class="data-details-bottom">
|
||||||
{{#let (get this.getTotalClients 1) as |stat|}}
|
<h3 class="data-details">Non-entity clients</h3>
|
||||||
<h3 class="data-details">Non-entity clients</h3>
|
<p class="data-details">
|
||||||
<p class="data-details">
|
{{format-number this.nonEntityClientData.runningTotal}}
|
||||||
{{format-number stat.total}}
|
</p>
|
||||||
</p>
|
|
||||||
{{/let}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="legend-right">
|
<div class="legend-right">
|
||||||
|
@ -54,21 +49,17 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-top">
|
<div class="data-details-top">
|
||||||
{{#let (get this.getAverageNewClients 0) as |stat|}}
|
<h3 class="data-details">Average new entity clients per month</h3>
|
||||||
<h3 class="data-details">Average new entity clients per month</h3>
|
<p class="data-details">
|
||||||
<p class="data-details">
|
{{format-number this.entityClientData.averageNewClients}}
|
||||||
{{format-number stat.average}}
|
</p>
|
||||||
</p>
|
|
||||||
{{/let}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="data-details-bottom">
|
<div class="data-details-bottom">
|
||||||
{{#let (get this.getAverageNewClients 1) as |stat|}}
|
<h3 class="data-details">Average new non-entity clients per month</h3>
|
||||||
<h3 class="data-details">Average new non-entity clients per month</h3>
|
<p class="data-details">
|
||||||
<p class="data-details">
|
{{format-number this.nonEntityClientData.averageNewClients}}
|
||||||
{{format-number stat.average}}
|
</p>
|
||||||
</p>
|
|
||||||
{{/let}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="timestamp">
|
<div class="timestamp">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="chart-wrapper" data-test-usage-stats>
|
<div class="chart-wrapper" data-test-usage-stats>
|
||||||
<div class="chart-header has-header-link has-bottom-margin-m">
|
<div class="chart-header has-header-link has-bottom-margin-m">
|
||||||
<div class="header-left">
|
<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>
|
<p class="chart-description"> These totals are within this namespace and all its children. </p>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue