diff --git a/ui/app/styles/components/stat-text.scss b/ui/app/styles/components/stat-text.scss
index efd76fa621..129771435f 100644
--- a/ui/app/styles/components/stat-text.scss
+++ b/ui/app/styles/components/stat-text.scss
@@ -9,6 +9,7 @@
.stat-label {
font-size: $size-5;
font-weight: $font-weight-semibold;
+ margin-bottom: $spacing-xxs;
line-height: inherit;
}
.stat-text {
diff --git a/ui/app/templates/components/clients/history.hbs b/ui/app/templates/components/clients/history.hbs
index 9d9e0a9039..8963e9f619 100644
--- a/ui/app/templates/components/clients/history.hbs
+++ b/ui/app/templates/components/clients/history.hbs
@@ -138,13 +138,14 @@
@title="Top 10 Namespaces"
@description="Each namespace's client count includes clients in child namespaces."
@dataset={{this.barChartDataset}}
+ @tooltipData={{or @model.activity.clients @model.activity.total.clients}}
@onClick={{action this.selectNamespace}}
@mapLegend={{array
(hash key='non_entity_tokens' label='Non-entity tokens')
(hash key='distinct_entities' label='Unique entities')
}}
>
-
+
@@ -186,4 +187,4 @@
{{/unless}}
{{/if}}
-{{/if}}
\ No newline at end of file
+{{/if}}
diff --git a/ui/app/templates/components/pricing-metrics-dates.hbs b/ui/app/templates/components/pricing-metrics-dates.hbs
index 9b565d5fee..826405fbdc 100644
--- a/ui/app/templates/components/pricing-metrics-dates.hbs
+++ b/ui/app/templates/components/pricing-metrics-dates.hbs
@@ -38,7 +38,7 @@
{{#if (and resultStart resultEnd)}}
- {{date-format resultStart "MMM dd, yyyy"}} through {{date-format resultEnd "MMM dd, yyyy"}}
+ {{date-format resultStart "MMM dd, yyyy" dateOnly=true}} through {{date-format resultEnd "MMM dd, yyyy" dateOnly=true}}
{{/if}}
diff --git a/ui/lib/core/addon/components/bar-chart.js b/ui/lib/core/addon/components/bar-chart.js
index f875fcd769..bcc49e074f 100644
--- a/ui/lib/core/addon/components/bar-chart.js
+++ b/ui/lib/core/addon/components/bar-chart.js
@@ -19,6 +19,7 @@
* @param {string} title - title of the chart
* @param {array} mapLegend - array of objects with key names 'key' and 'label' for the map legend
* @param {object} dataset - dataset for the chart
+ * @param {array} tooltipData - misc. information needed to display tooltip (i.e. total clients from query params)
* @param {string} [description] - description of the chart
* @param {string} [labelKey=label] - labelKey is the key name in the dataset passed in that corresponds to the value labeling the y-axis
* @param {function} [onClick] - takes function from parent and passes it to click event on data bars
@@ -74,10 +75,10 @@ class BarChartComponent extends Component {
}
@action
- renderBarChart(element, data) {
+ renderBarChart(element, args) {
let elementId = guidFor(element);
- let [dataset] = data;
- let totalCount = dataset.reduce((prevValue, currValue) => prevValue + currValue.total, 0);
+ let dataset = args[0];
+ let totalCount = args[1];
let handleClick = this.args.onClick;
let labelKey = this.labelKey;
let stackFunction = stack().keys(this.mapLegend.map(l => l.key));
@@ -140,7 +141,7 @@ class BarChartComponent extends Component {
.append('rect')
.attr('class', 'data-bar')
.style('cursor', 'pointer')
- .attr('width', chartData => `${xScale(chartData[1] - chartData[0] - 5)}%`)
+ .attr('width', chartData => `${xScale(chartData[1] - chartData[0]) - 0.25}%`)
.attr('height', yScale.bandwidth())
.attr('x', chartData => `${xScale(chartData[0])}%`)
.attr('y', ({ data }) => yScale(data[labelKey]))
@@ -213,8 +214,8 @@ class BarChartComponent extends Component {
select('.chart-tooltip')
.style('opacity', 1)
.style('max-width', '200px')
- .style('left', `${event.pageX - 400}px`)
- .style('top', `${event.pageY - 150}px`)
+ .style('left', `${event.pageX - 325}px`)
+ .style('top', `${event.pageY - 140}px`)
.text(
`${Math.round((chartData.total * 100) / totalCount)}% of total client counts:
${chartData.non_entity_tokens} non-entity tokens, ${chartData.distinct_entities} unique entities.
@@ -263,7 +264,7 @@ class BarChartComponent extends Component {
.on('mousemove', function(chartData) {
if (chartData.label.length >= CHAR_LIMIT) {
select('.chart-tooltip')
- .style('left', `${event.pageX - 400}px`)
+ .style('left', `${event.pageX - 300}px`)
.style('top', `${event.pageY - 100}px`)
.text(`${chartData.label}`)
.style('max-width', 'fit-content');
diff --git a/ui/lib/core/addon/helpers/date-format.js b/ui/lib/core/addon/helpers/date-format.js
index 9f50d0c8e1..f2f8f9ec4b 100644
--- a/ui/lib/core/addon/helpers/date-format.js
+++ b/ui/lib/core/addon/helpers/date-format.js
@@ -1,11 +1,16 @@
import { helper } from '@ember/component/helper';
import { format, parseISO } from 'date-fns';
-export function dateFormat([date, style], { isFormatted = false }) {
+export function dateFormat([date, style], { isFormatted = false, dateOnly = false }) {
// see format breaking in upgrade to date-fns 2.x https://github.com/date-fns/date-fns/blob/master/CHANGELOG.md#changed-5
if (isFormatted) {
return format(new Date(date), style);
}
+ // when date is in '2021-09-01T00:00:00Z' format
+ // remove hours so date displays unaffected by timezone
+ if (dateOnly && typeof date === 'string') {
+ date = date.split('T')[0];
+ }
let number = typeof date === 'string' ? parseISO(date) : date;
if (!number) {
return;
diff --git a/ui/lib/core/addon/helpers/format-number.js b/ui/lib/core/addon/helpers/format-number.js
index a782e37de3..1d863c5c27 100644
--- a/ui/lib/core/addon/helpers/format-number.js
+++ b/ui/lib/core/addon/helpers/format-number.js
@@ -1,6 +1,9 @@
import { helper } from '@ember/component/helper';
export function formatNumber([number]) {
+ if (typeof number !== 'number') {
+ return number;
+ }
// formats a number according to the locale
return new Intl.NumberFormat().format(number);
}
diff --git a/ui/lib/core/addon/templates/components/bar-chart.hbs b/ui/lib/core/addon/templates/components/bar-chart.hbs
index 584aa02e05..6ac736d2cd 100644
--- a/ui/lib/core/addon/templates/components/bar-chart.hbs
+++ b/ui/lib/core/addon/templates/components/bar-chart.hbs
@@ -19,8 +19,8 @@
diff --git a/ui/lib/core/addon/templates/components/stat-text.hbs b/ui/lib/core/addon/templates/components/stat-text.hbs
index 9d4bb916d1..1e50a78358 100644
--- a/ui/lib/core/addon/templates/components/stat-text.hbs
+++ b/ui/lib/core/addon/templates/components/stat-text.hbs
@@ -3,5 +3,5 @@
{{#if @subText}}
{{@subText}}
{{/if}}
- {{@value}}
+ {{format-number @value}}
diff --git a/ui/mirage/config.js b/ui/mirage/config.js
index 81cb56c563..b3a2b0df7a 100644
--- a/ui/mirage/config.js
+++ b/ui/mirage/config.js
@@ -31,6 +31,218 @@ export default function() {
};
});
+ this.get('/sys/internal/counters/activity/monthly', function() {
+ return {
+ data: {
+ by_namespace: [
+ {
+ namespace_id: 'Z4Rzh',
+ namespace_path: 'namespace1/',
+ counts: {
+ distinct_entities: 867,
+ non_entity_tokens: 939,
+ clients: 1806,
+ },
+ },
+ {
+ namespace_id: 'DcgzU',
+ namespace_path: 'namespace17/',
+ counts: {
+ distinct_entities: 966,
+ non_entity_tokens: 550,
+ clients: 1516,
+ },
+ },
+ {
+ namespace_id: '5SWT8',
+ namespace_path: 'namespacelonglonglong4/',
+ counts: {
+ distinct_entities: 996,
+ non_entity_tokens: 417,
+ clients: 1413,
+ },
+ },
+ {
+ namespace_id: 'XGu7R',
+ namespace_path: 'namespace12/',
+ counts: {
+ distinct_entities: 829,
+ non_entity_tokens: 540,
+ clients: 1369,
+ },
+ },
+ {
+ namespace_id: 'yHcL9',
+ namespace_path: 'namespace11/',
+ counts: {
+ distinct_entities: 563,
+ non_entity_tokens: 705,
+ clients: 1268,
+ },
+ },
+ {
+ namespace_id: 'F0xGm',
+ namespace_path: 'namespace10/',
+ counts: {
+ distinct_entities: 925,
+ non_entity_tokens: 255,
+ clients: 1180,
+ },
+ },
+ {
+ namespace_id: 'aJuQG',
+ namespace_path: 'namespace9/',
+ counts: {
+ distinct_entities: 935,
+ non_entity_tokens: 239,
+ clients: 1174,
+ },
+ },
+ {
+ namespace_id: 'bw5UO',
+ namespace_path: 'namespace6/',
+ counts: {
+ distinct_entities: 810,
+ non_entity_tokens: 363,
+ clients: 1173,
+ },
+ },
+ {
+ namespace_id: 'IeyJp',
+ namespace_path: 'namespace14/',
+ counts: {
+ distinct_entities: 774,
+ non_entity_tokens: 392,
+ clients: 1166,
+ },
+ },
+ {
+ namespace_id: 'Uc0o8',
+ namespace_path: 'namespace16/',
+ counts: {
+ distinct_entities: 408,
+ non_entity_tokens: 743,
+ clients: 1151,
+ },
+ },
+ {
+ namespace_id: 'R6L40',
+ namespace_path: 'namespace2/',
+ counts: {
+ distinct_entities: 292,
+ non_entity_tokens: 736,
+ clients: 1028,
+ },
+ },
+ {
+ namespace_id: 'Rqa3W',
+ namespace_path: 'namespace13/',
+ counts: {
+ distinct_entities: 160,
+ non_entity_tokens: 803,
+ clients: 963,
+ },
+ },
+ {
+ namespace_id: 'MSgZE',
+ namespace_path: 'namespace7/',
+ counts: {
+ distinct_entities: 201,
+ non_entity_tokens: 657,
+ clients: 858,
+ },
+ },
+ {
+ namespace_id: 'kxU4t',
+ namespace_path: 'namespacelonglonglong3/',
+ counts: {
+ distinct_entities: 742,
+ non_entity_tokens: 26,
+ clients: 768,
+ },
+ },
+ {
+ namespace_id: '5xKya',
+ namespace_path: 'namespace15/',
+ counts: {
+ distinct_entities: 663,
+ non_entity_tokens: 19,
+ clients: 682,
+ },
+ },
+ {
+ namespace_id: '5KxXA',
+ namespace_path: 'namespace18anotherlong/',
+ counts: {
+ distinct_entities: 470,
+ non_entity_tokens: 196,
+ clients: 666,
+ },
+ },
+ {
+ namespace_id: 'AAidI',
+ namespace_path: 'namespace20/',
+ counts: {
+ distinct_entities: 429,
+ non_entity_tokens: 60,
+ clients: 489,
+ },
+ },
+ {
+ namespace_id: 'BCl56',
+ namespace_path: 'namespace8/',
+ counts: {
+ distinct_entities: 61,
+ non_entity_tokens: 201,
+ clients: 262,
+ },
+ },
+ {
+ namespace_id: 'yYNw2',
+ namespace_path: 'namespace19/',
+ counts: {
+ distinct_entities: 165,
+ non_entity_tokens: 85,
+ clients: 250,
+ },
+ },
+ {
+ namespace_id: 'root',
+ namespace_path: '',
+ counts: {
+ distinct_entities: 67,
+ non_entity_tokens: 9,
+ clients: 76,
+ },
+ },
+ ],
+ distinct_entities: 11323,
+ non_entity_tokens: 7935,
+ clients: 19258,
+ },
+ };
+ });
+
+ this.get('/sys/health', function() {
+ return {
+ initialized: true,
+ sealed: false,
+ standby: false,
+ license: {
+ expiry: '2021-05-12T23:20:50.52Z',
+ state: 'stored',
+ },
+ performance_standby: false,
+ replication_performance_mode: 'disabled',
+ replication_dr_mode: 'disabled',
+ server_time_utc: 1622562585,
+ version: '1.9.0+ent',
+ cluster_name: 'vault-cluster-e779cd7c',
+ cluster_id: '5f20f5ab-acea-0481-787e-71ec2ff5a60b',
+ last_wal: 121,
+ };
+ });
+
this.get('/sys/license/status', function() {
return {
data: {
@@ -60,25 +272,5 @@ export default function() {
};
});
- this.get('/sys/health', function() {
- return {
- initialized: true,
- sealed: false,
- standby: false,
- license: {
- expiry: '2021-05-12T23:20:50.52Z',
- state: 'stored',
- },
- performance_standby: false,
- replication_performance_mode: 'disabled',
- replication_dr_mode: 'disabled',
- server_time_utc: 1622562585,
- version: '1.9.0+ent',
- cluster_name: 'vault-cluster-e779cd7c',
- cluster_id: '5f20f5ab-acea-0481-787e-71ec2ff5a60b',
- last_wal: 121,
- };
- });
-
this.passthrough();
}
diff --git a/ui/tests/integration/components/stat-text-test.js b/ui/tests/integration/components/stat-text-test.js
index 2c1f2bf61a..554c5dbf91 100644
--- a/ui/tests/integration/components/stat-text-test.js
+++ b/ui/tests/integration/components/stat-text-test.js
@@ -1,6 +1,6 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
-import { render } from '@ember/test-helpers';
+import { render, settled } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | StatText', function(hooks) {
@@ -14,16 +14,21 @@ module('Integration | Component | StatText', function(hooks) {
test('it renders passed in attributes', async function(assert) {
this.set('label', 'A Label');
- this.set('value', '9,999');
+ this.set('value', 'A value');
this.set('size', 'l');
this.set('subText', 'This is my description');
await render(
hbs` `
);
-
assert.dom('.stat-label').hasText(this.label, 'renders label');
assert.dom('.stat-text').hasText(this.subText, 'renders subtext');
- assert.dom('.stat-value').hasText(this.value, 'renders value');
+ assert.dom('.stat-value').hasText(this.value, 'renders a non-integer value');
+
+ this.set('value', 604099);
+ await settled();
+
+ let formattedNumber = '604,099';
+ assert.dom('.stat-value').hasText(formattedNumber, 'renders correctly formatted integer value');
});
});
diff --git a/ui/tests/integration/helpers/date-format-test.js b/ui/tests/integration/helpers/date-format-test.js
index 644874d4a4..029d0dd53a 100644
--- a/ui/tests/integration/helpers/date-format-test.js
+++ b/ui/tests/integration/helpers/date-format-test.js
@@ -53,4 +53,14 @@ module('Integration | Helper | date-format', function(hooks) {
);
assert.dom('[data-test-date-format]').includesText(format(formattedDate, 'MMMM dd, yyyy hh:mm:ss a'));
});
+
+ test('displays correct date when timestamp is in ISO 8601 format', async function(assert) {
+ let timestampDate = '2021-09-01T00:00:00Z';
+ this.set('timestampDate', timestampDate);
+
+ await render(
+ hbs`Date: {{date-format timestampDate 'MMM dd, yyyy' dateOnly=true}}
`
+ );
+ assert.dom('[data-test-date-format]').includesText('Date: Sep 01, 2021');
+ });
});