Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI/ Client counts range (running total component) #13477

Merged
merged 26 commits into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b131b91
grid for stacked charts
hellobontempo Dec 20, 2021
37c75da
pass in data as arg from parent
hellobontempo Dec 20, 2021
1f37434
pull out vertical bar chart component
hellobontempo Dec 20, 2021
0bbe0b2
refactor to use vertical bar chart component
hellobontempo Dec 20, 2021
07db985
remove any chart handling stuff from parent
hellobontempo Dec 20, 2021
f205420
rename variables
hellobontempo Dec 20, 2021
0b73b0a
refactor horizontal bar chart into separate component
hellobontempo Dec 20, 2021
933004e
move descriptions to inside template (not passed in)
hellobontempo Dec 20, 2021
8768f1f
constructs attribution copy
hellobontempo Dec 21, 2021
7911db3
add sample response to mirage config
hellobontempo Dec 21, 2021
c934ed1
change indenting
hellobontempo Dec 21, 2021
608bfdd
rename to MonthlyUsage
hellobontempo Dec 21, 2021
b097804
change name to running totals
hellobontempo Dec 21, 2021
3befc5e
rename variable
hellobontempo Dec 21, 2021
7f2a109
finishes line chart
hellobontempo Dec 22, 2021
49fc0e2
pull constants to util
hellobontempo Dec 22, 2021
6863af9
cleanup add todos
hellobontempo Dec 23, 2021
41d2bca
fix formatNumbers return"
hellobontempo Dec 23, 2021
26ef446
comments and cleanup
hellobontempo Dec 23, 2021
ee9b44f
adds tooltip to line chart
hellobontempo Dec 23, 2021
ddddace
make cover area larger
hellobontempo Dec 23, 2021
b305b77
fixes tooltip styling
hellobontempo Dec 23, 2021
d473178
adds tooltip styling"
hellobontempo Dec 24, 2021
33f1b2c
adds tooltip modal to horizontal chart
hellobontempo Dec 24, 2021
7988f80
finishes tooltip for horizontal chart
hellobontempo Dec 24, 2021
a4d37a9
remove click event arg
hellobontempo Jan 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions ui/app/components/clients/attribution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Component from '@glimmer/component';

// TODO: fill out below!!
/**
* @module Attribution
* Attribution components are used to...
*
* @example
* ```js
* <Attribution @requiredParam={requiredParam} @optionalParam={optionalParam} @param1={{param1}}>
* Pass in export button
* </Attribution>
* ```
* @param {object} requiredParam - requiredParam is...
* @param {string} [optionalParam] - optionalParam is...
* @param {string} [param1=defaultValue] - param1 is...
*/

export default class Attribution extends Component {
get dateRange() {
// some conditional that returns "date range" or "month" depending on what the params are
return 'date range';
}

get chartText() {
// something that determines if data is by namespace or by auth method
// and returns text
// if byNamespace
return {
description:
'This data shows the top ten namespaces by client count and can be used to understand where clients are originating. Namespaces are identified by path. To see all namespaces, export this data.',
newCopy: `The new clients in the namespace for this ${this.dateRange}.
This aids in understanding which namespaces create and use new clients
${this.dateRange === 'date range' ? ' over time.' : '.'}`,
totalCopy: `The total clients in the namespace for this ${this.dateRange}. This number is useful for identifying overall usage volume.`,
};
// if byAuthMethod
// return
// byAuthMethod = {
// description: "This data shows the top ten authentication methods by client count within this namespace, and can be used to understand where new clients and total clients are originating. Authentication methods are organized by path.",
// newCopy: `The new clients used by the auth method for this {{@range}}. This aids in understanding which auth methods create and use new clients ${this.dateRange === "date range" ? " over time." : "."}`,
// totalCopy: `The total clients used by the auth method for this ${this.dateRange}. This number is useful for identifying overall usage volume. `
// }
}
}
58 changes: 56 additions & 2 deletions ui/app/components/clients/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { format } from 'date-fns';
export default class Dashboard extends Component {
maxNamespaces = 10;
chartLegend = [
{ key: 'distinct_entities', label: 'Direct entities' },
{ key: 'non_entity_tokens', label: 'Active direct tokens' },
{ key: 'distinct_entities', label: 'unique entities' },
{ key: 'non_entity_tokens', label: 'non-entity tokens' },
];
@tracked selectedNamespace = null;

Expand Down Expand Up @@ -62,6 +62,60 @@ export default class Dashboard extends Component {
});
}

// TODO: dataset for line chart
get lineChartData() {
return [
{ month: '1/21', clients: 100, new: 100 },
{ month: '2/21', clients: 300, new: 200 },
{ month: '3/21', clients: 300, new: 0 },
{ month: '4/21', clients: 300, new: 0 },
{ month: '5/21', clients: 300, new: 0 },
{ month: '6/21', clients: 300, new: 0 },
{ month: '7/21', clients: 300, new: 0 },
{ month: '8/21', clients: 350, new: 50 },
{ month: '9/21', clients: 400, new: 50 },
{ month: '10/21', clients: 450, new: 50 },
{ month: '11/21', clients: 500, new: 50 },
{ month: '12/21', clients: 1000, new: 1000 },
];
}

// TODO: dataset for new monthly clients vertical bar chart (manage in serializer?)
get newMonthlyClients() {
return [
{ month: 'January', distinct_entities: 1000, non_entity_tokens: 322, total: 1322 },
{ month: 'February', distinct_entities: 1500, non_entity_tokens: 122, total: 1622 },
{ month: 'March', distinct_entities: 4300, non_entity_tokens: 700, total: 5000 },
{ month: 'April', distinct_entities: 1550, non_entity_tokens: 229, total: 1779 },
{ month: 'May', distinct_entities: 5560, non_entity_tokens: 124, total: 5684 },
{ month: 'June', distinct_entities: 1570, non_entity_tokens: 142, total: 1712 },
{ month: 'July', distinct_entities: 300, non_entity_tokens: 112, total: 412 },
{ month: 'August', distinct_entities: 1610, non_entity_tokens: 130, total: 1740 },
{ month: 'September', distinct_entities: 1900, non_entity_tokens: 222, total: 2122 },
{ month: 'October', distinct_entities: 500, non_entity_tokens: 166, total: 666 },
{ month: 'November', distinct_entities: 480, non_entity_tokens: 132, total: 612 },
{ month: 'December', distinct_entities: 980, non_entity_tokens: 202, total: 1182 },
];
}

// TODO: dataset for vault usage vertical bar chart (manage in serializer?)
get monthlyUsage() {
return [
{ month: 'January', distinct_entities: 1000, non_entity_tokens: 322, total: 1322 },
{ month: 'February', distinct_entities: 1500, non_entity_tokens: 122, total: 1622 },
{ month: 'March', distinct_entities: 4300, non_entity_tokens: 700, total: 5000 },
{ month: 'April', distinct_entities: 1550, non_entity_tokens: 229, total: 1779 },
{ month: 'May', distinct_entities: 5560, non_entity_tokens: 124, total: 5684 },
{ month: 'June', distinct_entities: 1570, non_entity_tokens: 142, total: 1712 },
{ month: 'July', distinct_entities: 300, non_entity_tokens: 112, total: 412 },
{ month: 'August', distinct_entities: 1610, non_entity_tokens: 130, total: 1740 },
{ month: 'September', distinct_entities: 1900, non_entity_tokens: 222, total: 2122 },
{ month: 'October', distinct_entities: 500, non_entity_tokens: 166, total: 666 },
{ month: 'November', distinct_entities: 480, non_entity_tokens: 132, total: 612 },
{ month: 'December', distinct_entities: 980, non_entity_tokens: 202, total: 1182 },
];
}

// Create namespaces data for csv format
get getCsvData() {
if (!this.args.model.activity || !this.args.model.activity.byNamespace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { select, event, selectAll } from 'd3-selection';
import { scaleLinear, scaleBand } from 'd3-scale';
import { axisLeft } from 'd3-axis';
import { max, maxIndex } from 'd3-array';
import { BAR_COLOR_HOVER, GREY, LIGHT_AND_DARK_BLUE } from '../../utils/chart-helpers';
import { tracked } from '@glimmer/tracking';

/**
* @module HorizontalBarChart
Expand All @@ -30,74 +32,10 @@ const TRANSLATE = { down: 13 };
const CHAR_LIMIT = 15; // character count limit for y-axis labels to trigger truncating
const LINE_HEIGHT = 24; // each bar w/ padding is 24 pixels thick

// COLOR THEME:
const BAR_COLOR_DEFAULT = ['#BFD4FF', '#1563FF'];
const BAR_COLOR_HOVER = ['#1563FF', '#0F4FD1'];
const BACKGROUND_BAR_COLOR = '#EBEEF2';

const SAMPLE_DATA = [
{
label: 'longlongsuperlongnamespace80/',
non_entity_tokens: 1696,
distinct_entities: 1652,
total: 3348,
},
{
label: 'namespace12/',
non_entity_tokens: 1568,
distinct_entities: 1663,
total: 3231,
},
{
label: 'namespace44/',
non_entity_tokens: 1511,
distinct_entities: 1708,
total: 3219,
},
{
label: 'namespace36/',
non_entity_tokens: 1574,
distinct_entities: 1553,
total: 3127,
},
{
label: 'namespace2/',
non_entity_tokens: 1784,
distinct_entities: 1333,
total: 3117,
},
{
label: 'namespace82/',
non_entity_tokens: 1245,
distinct_entities: 1702,
total: 2947,
},
{
label: 'namespace28/',
non_entity_tokens: 1579,
distinct_entities: 1364,
total: 2943,
},
{
label: 'namespace60/',
non_entity_tokens: 1962,
distinct_entities: 929,
total: 2891,
},
{
label: 'namespace5/',
non_entity_tokens: 1448,
distinct_entities: 1418,
total: 2866,
},
{
label: 'namespace67/',
non_entity_tokens: 1758,
distinct_entities: 1065,
total: 2823,
},
];
export default class HorizontalBarChart extends Component {
@tracked tooltipTarget = '';
@tracked tooltipText = '';

get labelKey() {
return this.args.labelKey || 'label';
}
Expand All @@ -110,6 +48,10 @@ export default class HorizontalBarChart extends Component {
return this.args.dataset[maxIndex(this.args.dataset, d => d.total)];
}

@action removeTooltip() {
this.tooltipTarget = null;
}

@action
renderChart(element, args) {
// chart legend tells stackFunction how to stack/organize data
Expand All @@ -120,7 +62,6 @@ export default class HorizontalBarChart extends Component {
// let dataset = SAMPLE_DATA;
let stackedData = stackFunction(dataset);
let labelKey = this.labelKey;
let handleClick = this.args.onClick;

let xScale = scaleLinear()
.domain([0, max(dataset.map(d => d.total))])
Expand All @@ -144,7 +85,7 @@ export default class HorizontalBarChart extends Component {
.append('g')
// shifts chart to accommodate y-axis legend
.attr('transform', `translate(${CHART_MARGIN.left}, ${CHART_MARGIN.top})`)
.style('fill', (d, i) => BAR_COLOR_DEFAULT[i]);
.style('fill', (d, i) => LIGHT_AND_DARK_BLUE[i]);

let yAxis = axisLeft(yScale).tickSize(0);
yAxis(chartSvg.append('g').attr('transform', `translate(${CHART_MARGIN.left}, ${CHART_MARGIN.top})`));
Expand Down Expand Up @@ -184,7 +125,7 @@ export default class HorizontalBarChart extends Component {
.attr('height', `${LINE_HEIGHT}px`)
.attr('x', '0')
.attr('y', chartData => yScale(chartData[labelKey]))
.style('fill', `${BACKGROUND_BAR_COLOR}`)
.style('fill', `${GREY}`)
.style('opacity', '0')
.style('mix-blend-mode', 'multiply');

Expand All @@ -204,59 +145,45 @@ export default class HorizontalBarChart extends Component {

let dataBars = chartSvg.selectAll('rect.data-bar');
let actionBarSelection = chartSvg.selectAll('rect.action-bar');

let compareAttributes = (elementA, elementB, attr) =>
select(elementA).attr(`${attr}`) === elementB.getAttribute(`${attr}`);
select(elementA).attr(`${attr}`) === select(elementB).attr(`${attr}`);

// MOUSE AND CLICK EVENTS FOR DATA BARS
// MOUSE EVENTS FOR DATA BARS
actionBars
.on('click', function(chartData) {
if (handleClick) {
handleClick(chartData);
}
})
.on('mouseover', function() {
select(this).style('opacity', 1);
.on('mouseover', data => {
let hoveredElement = actionBars.filter(bar => bar.label === data.label).node();
this.tooltipTarget = hoveredElement;
this.tooltipText = `${Math.round((data.total * 100) / 19000)}% of total client counts:
${data.non_entity_tokens} non-entity tokens, ${data.distinct_entities} unique entities.`;

select(hoveredElement).style('opacity', 1);

dataBars
.filter(function() {
return compareAttributes(this, event.target, 'y');
return compareAttributes(this, hoveredElement, 'y');
})
.style('fill', (b, i) => `${BAR_COLOR_HOVER[i]}`);
// TODO: change to use modal instead of tooltip div
select('.chart-tooltip')
.transition()
.duration(200)
.style('opacity', 1);
})
.on('mouseout', function() {
select(this).style('opacity', 0);
select('.chart-tooltip').style('opacity', 0);
dataBars
.filter(function() {
return compareAttributes(this, event.target, 'y');
})
.style('fill', (b, i) => `${BAR_COLOR_DEFAULT[i]}`);
})
.on('mousemove', function(chartData) {
select('.chart-tooltip')
.style('opacity', 1)
.style('max-width', '200px')
.style('left', `${event.pageX - 325}px`)
.style('top', `${event.pageY - 140}px`)
.text(
`${Math.round((chartData.total * 100) / 19000)}% of total client counts:
${chartData.non_entity_tokens} non-entity tokens, ${chartData.distinct_entities} unique entities.
`
);
.style('fill', (b, i) => `${LIGHT_AND_DARK_BLUE[i]}`);
});

// MOUSE EVENTS FOR Y-AXIS LABELS
yLegendBars
.on('click', function(chartData) {
if (handleClick) {
handleClick(chartData);
.on('mouseover', data => {
if (data.label.length >= CHAR_LIMIT) {
let hoveredElement = yLegendBars.filter(bar => bar.label === data.label).node();
this.tooltipTarget = hoveredElement;
this.tooltipText = data.label;
} else {
this.tooltipTarget = null;
}
})
.on('mouseover', function(chartData) {
dataBars
.filter(function() {
return compareAttributes(this, event.target, 'y');
Expand All @@ -267,36 +194,19 @@ export default class HorizontalBarChart extends Component {
return compareAttributes(this, event.target, 'y');
})
.style('opacity', '1');
if (chartData.label.length >= CHAR_LIMIT) {
select('.chart-tooltip')
.transition()
.duration(200)
.style('opacity', 1);
}
})
.on('mouseout', function() {
select('.chart-tooltip').style('opacity', 0);
this.tooltipTarget = null;
dataBars
.filter(function() {
return compareAttributes(this, event.target, 'y');
})
.style('fill', (b, i) => `${BAR_COLOR_DEFAULT[i]}`);
.style('fill', (b, i) => `${LIGHT_AND_DARK_BLUE[i]}`);
actionBarSelection
.filter(function() {
return compareAttributes(this, event.target, 'y');
})
.style('opacity', '0');
})
.on('mousemove', function(chartData) {
if (chartData.label.length >= CHAR_LIMIT) {
select('.chart-tooltip')
.style('left', `${event.pageX - 300}px`)
.style('top', `${event.pageY - 100}px`)
.text(`${chartData.label}`)
.style('max-width', 'fit-content');
} else {
select('.chart-tooltip').style('opacity', 0);
}
});

// add client count total values to the right
Expand Down
Loading