Skip to content
Snippets Groups Projects
Commit 146954d0 authored by Jose Ivan Vargas Lopez's avatar Jose Ivan Vargas Lopez
Browse files

UX Adjustments for the prometheus dashboard

parent f4ff62fa
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -7,7 +7,8 @@
* @param {String} text
* @returns {String}
*/
export const addDelimiter = text => (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
export const addDelimiter = text =>
(text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
 
/**
* Returns '99+' for numbers bigger than 99.
Loading
Loading
@@ -22,7 +23,8 @@ export const highCountTrim = count => (count > 99 ? '99+' : count);
* @param {String} string
* @requires {String}
*/
export const humanize = string => string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
export const humanize = string =>
string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
 
/**
* Adds an 's' to the end of the string when count is bigger than 0
Loading
Loading
@@ -53,7 +55,7 @@ export const slugify = str => str.trim().toLowerCase();
* @param {Number} maxLength
* @returns {String}
*/
export const truncate = (string, maxLength) => `${string.substr(0, (maxLength - 3))}...`;
export const truncate = (string, maxLength) => `${string.substr(0, maxLength - 3)}...`;
 
/**
* Capitalizes first character
Loading
Loading
@@ -80,3 +82,15 @@ export const stripHtml = (string, replace = '') => string.replace(/<[^>]*>/g, re
* @param {*} string
*/
export const convertToCamelCase = string => string.replace(/(_\w)/g, s => s[1].toUpperCase());
/**
* Converts a sentence to lower case from the second word onwards
* e.g. Hello World => Hello world
*
* @param {*} string
*/
export const convertToSentenceCase = string => {
const splitWord = string.split(' ').map((word, index) => (index > 0 ? word.toLowerCase() : word));
return splitWord.join(' ');
};
Loading
Loading
@@ -255,6 +255,7 @@ export default {
:margin="margin"
:measurements="measurements"
:y-axis-label="yAxisLabel"
:unit-of-display="unitOfDisplay"
/>
<svg
class="graph-data"
Loading
Loading
@@ -304,7 +305,6 @@ export default {
:legend-title="legendTitle"
:time-series="timeSeries"
:current-data-index="currentDataIndex"
:unit-of-display="unitOfDisplay"
/>
</div>
</template>
<script>
import { convertToSentenceCase } from '~/lib/utils/text_utility';
export default {
props: {
graphWidth: {
Loading
Loading
@@ -21,6 +23,10 @@ export default {
type: String,
required: true,
},
unitOfDisplay: {
type: String,
required: true,
},
},
data() {
return {
Loading
Loading
@@ -64,6 +70,10 @@ export default {
this.measurements.axisLabelLineOffset || 0
);
},
yAxisLabelSentenceCase() {
return `${convertToSentenceCase(this.yAxisLabel)} (${this.unitOfDisplay})`;
},
},
mounted() {
this.$nextTick(() => {
Loading
Loading
@@ -106,7 +116,7 @@ export default {
:transform="textTransform"
ref="ylabel"
>
{{ yAxisLabel }}
{{ yAxisLabelSentenceCase }}
</text>
<rect
class="rect-axis-text"
Loading
Loading
Loading
Loading
@@ -181,7 +181,7 @@ export default {
/>
</svg>
</td>
<td>{{ seriesMetricLabel(index, series) }}</td>
<td>{{ series.track }} {{ seriesMetricLabel(index, series) }}</td>
<td>
<strong>{{ seriesMetricValue(series) }}</strong>
</td>
Loading
Loading
Loading
Loading
@@ -15,21 +15,8 @@ export default {
type: Number,
required: true,
},
unitOfDisplay: {
type: String,
required: true,
},
},
methods: {
formatMetricUsage(series) {
const value =
series.values[this.currentDataIndex] && series.values[this.currentDataIndex].value;
if (isNaN(value)) {
return '-';
}
return `${formatRelevantDigits(value)} ${this.unitOfDisplay}`;
},
summaryMetrics(series) {
return `Avg: ${formatRelevantDigits(series.average)} · Max: ${formatRelevantDigits(series.max)}`;
},
Loading
Loading
@@ -49,6 +36,9 @@ export default {
v-for="(series, index) in timeSeries"
:key="index"
>
<td>
<strong>{{ series.track }}</strong>
</td>
<td>
<svg
width="15"
Loading
Loading
@@ -70,17 +60,15 @@ export default {
v-if="timeSeries.length > 1"
>
<template v-if="series.metricTag">
<strong>{{ series.metricTag }}</strong>
{{ formatMetricUsage(series) }} {{ summaryMetrics(series) }}
<strong>{{ series.metricTag }}</strong> {{ summaryMetrics(series) }}
</template>
<template v-else>
<strong>{{ legendTitle }}</strong>
series {{ index + 1 }} {{ formatMetricUsage(series) }} {{ summaryMetrics(series) }}
series {{ index + 1 }} {{ summaryMetrics(series) }}
</template>
</td>
<td v-else>
<strong>{{ legendTitle }}</strong>
{{ formatMetricUsage(series) }} {{ summaryMetrics(series) }}
<strong>{{ legendTitle }}</strong> {{ summaryMetrics(series) }}
</td>
</tr>
</table>
Loading
Loading
Loading
Loading
@@ -3,6 +3,7 @@ import { scaleLinear, scaleTime } from 'd3-scale';
import { line, area, curveLinear } from 'd3-shape';
import { extent, max, sum } from 'd3-array';
import { timeMinute } from 'd3-time';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
 
const d3 = {
scaleLinear,
Loading
Loading
@@ -28,15 +29,7 @@ const defaultColorOrder = ['blue', 'orange', 'red', 'green', 'purple'];
 
const defaultStyleOrder = ['solid', 'dashed', 'dotted'];
 
function queryTimeSeries(
query,
graphWidth,
graphHeight,
graphHeightOffset,
xDom,
yDom,
lineStyle,
) {
function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom, yDom, lineStyle) {
let usedColors = [];
 
function pickColor(name) {
Loading
Loading
@@ -63,12 +56,11 @@ function queryTimeSeries(
const timeSeriesValues = timeSeries.values.map(d => d.value);
const maximumValue = d3.max(timeSeriesValues);
const accum = d3.sum(timeSeriesValues);
const track = capitalizeFirstCharacter(query.track ? query.track : 'Stable');
 
const timeSeriesScaleX = d3.scaleTime().range([0, graphWidth - 70]);
 
const timeSeriesScaleY = d3
.scaleLinear()
.range([graphHeight - graphHeightOffset, 0]);
const timeSeriesScaleY = d3.scaleLinear().range([graphHeight - graphHeightOffset, 0]);
 
timeSeriesScaleX.domain(xDom);
timeSeriesScaleX.ticks(d3.timeMinute, 60);
Loading
Loading
@@ -91,27 +83,18 @@ function queryTimeSeries(
.y0(graphHeight - graphHeightOffset)
.y1(d => timeSeriesScaleY(d.value));
 
const timeSeriesMetricLabel =
timeSeries.metric[Object.keys(timeSeries.metric)[0]];
const timeSeriesMetricLabel = timeSeries.metric[Object.keys(timeSeries.metric)[0]];
const seriesCustomizationData =
query.series != null &&
_.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
query.series != null && _.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
 
if (seriesCustomizationData) {
metricTag = seriesCustomizationData.value || timeSeriesMetricLabel;
[lineColor, areaColor] = pickColor(seriesCustomizationData.color);
} else {
metricTag =
timeSeriesMetricLabel ||
query.label ||
`series ${timeSeriesNumber + 1}`;
metricTag = timeSeriesMetricLabel || query.label || `series ${timeSeriesNumber + 1}`;
[lineColor, areaColor] = pickColor();
}
 
if (query.track) {
metricTag += ` - ${query.track}`;
}
return {
linePath: lineFunction(timeSeries.values),
areaPath: areaFunction(timeSeries.values),
Loading
Loading
@@ -123,23 +106,16 @@ function queryTimeSeries(
lineColor,
areaColor,
metricTag,
track,
};
});
}
 
export default function createTimeSeries(
queries,
graphWidth,
graphHeight,
graphHeightOffset,
) {
export default function createTimeSeries(queries, graphWidth, graphHeight, graphHeightOffset) {
const allValues = queries.reduce(
(allQueryResults, query) =>
allQueryResults.concat(
query.result.reduce(
(allResults, result) => allResults.concat(result.values),
[],
),
query.result.reduce((allResults, result) => allResults.concat(result.values), []),
),
[],
);
Loading
Loading
@@ -150,15 +126,7 @@ export default function createTimeSeries(
return queries.reduce((series, query, index) => {
const lineStyle = defaultStyleOrder[index % defaultStyleOrder.length];
return series.concat(
queryTimeSeries(
query,
graphWidth,
graphHeight,
graphHeightOffset,
xDom,
yDom,
lineStyle,
),
queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom, yDom, lineStyle),
);
}, []);
}
Loading
Loading
@@ -65,11 +65,15 @@ describe('text_utility', () => {
 
describe('stripHtml', () => {
it('replaces html tag with the default replacement', () => {
expect(textUtils.stripHtml('This is a text with <p>html</p>.')).toEqual('This is a text with html.');
expect(textUtils.stripHtml('This is a text with <p>html</p>.')).toEqual(
'This is a text with html.',
);
});
 
it('replaces html tags with the provided replacement', () => {
expect(textUtils.stripHtml('This is a text with <p>html</p>.', ' ')).toEqual('This is a text with html .');
expect(textUtils.stripHtml('This is a text with <p>html</p>.', ' ')).toEqual(
'This is a text with html .',
);
});
});
 
Loading
Loading
@@ -78,4 +82,10 @@ describe('text_utility', () => {
expect(textUtils.convertToCamelCase('snake_case')).toBe('snakeCase');
});
});
describe('convertToSentenceCase', () => {
it('converts Sentence Case to Sentence case', () => {
expect(textUtils.convertToSentenceCase('Hello World')).toBe('Hello world');
});
});
});
Loading
Loading
@@ -17,6 +17,7 @@ const defaultValuesComponent = {
margin: measurements.large.margin,
measurements: measurements.large,
yAxisLabel: 'Values',
unitOfDisplay: 'MB',
};
 
function getTextFromNode(component, selector) {
Loading
Loading
@@ -28,9 +29,7 @@ describe('Axis', () => {
it('textTransform', () => {
const component = createComponent(defaultValuesComponent);
 
expect(component.textTransform).toContain(
'translate(15, 120) rotate(-90)',
);
expect(component.textTransform).toContain('translate(15, 120) rotate(-90)');
});
 
it('xPosition', () => {
Loading
Loading
@@ -48,9 +47,7 @@ describe('Axis', () => {
it('rectTransform', () => {
const component = createComponent(defaultValuesComponent);
 
expect(component.rectTransform).toContain(
'translate(0, 120) rotate(-90)',
);
expect(component.rectTransform).toContain('translate(0, 120) rotate(-90)');
});
});
 
Loading
Loading
@@ -63,8 +60,6 @@ describe('Axis', () => {
it('contains text to signal the usage, title and time with multiple time series', () => {
const component = createComponent(defaultValuesComponent);
 
expect(getTextFromNode(component, '.y-label-text')).toEqual(
component.yAxisLabel,
);
expect(getTextFromNode(component, '.y-label-text')).toEqual('Values (MB)');
});
});
Loading
Loading
@@ -30,14 +30,6 @@ describe('Legend Component', () => {
});
});
 
it('formatMetricUsage should contain the unit of display and the current value selected via "currentDataIndex"', () => {
const formattedMetricUsage = vm.formatMetricUsage(timeSeries[0]);
const valueFromSeries = timeSeries[0].values[vm.currentDataIndex].value;
expect(formattedMetricUsage.indexOf(vm.unitOfDisplay)).not.toEqual(-1);
expect(formattedMetricUsage.indexOf(valueFromSeries)).not.toEqual(-1);
});
it('strokeDashArray', () => {
const dashedArray = vm.strokeDashArray('dashed');
const dottedArray = vm.strokeDashArray('dotted');
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment