diff options
author | Jose Ivan Vargas <jvargas@gitlab.com> | 2018-04-02 16:50:39 -0500 |
---|---|---|
committer | Jose Ivan Vargas <jvargas@gitlab.com> | 2018-04-06 14:37:46 -0500 |
commit | 146954d0bbf149a4f5c9cf206024dc192e84231f (patch) | |
tree | 33a4d10d6c728dcf178ce02f96b8077af0c3372a | |
parent | f4ff62fa64c4d161b2265094022e699084a2dbbd (diff) | |
download | gitlab-ce-146954d0bbf149a4f5c9cf206024dc192e84231f.tar.gz |
UX Adjustments for the prometheus dashboard
9 files changed, 63 insertions, 86 deletions
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index 94d03621bff..b54ecd2d543 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -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. @@ -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 @@ -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 @@ -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(' '); +}; diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue index 9bf32d8a2da..d9f2b9ba7cb 100644 --- a/app/assets/javascripts/monitoring/components/graph.vue +++ b/app/assets/javascripts/monitoring/components/graph.vue @@ -255,6 +255,7 @@ export default { :margin="margin" :measurements="measurements" :y-axis-label="yAxisLabel" + :unit-of-display="unitOfDisplay" /> <svg class="graph-data" @@ -304,7 +305,6 @@ export default { :legend-title="legendTitle" :time-series="timeSeries" :current-data-index="currentDataIndex" - :unit-of-display="unitOfDisplay" /> </div> </template> diff --git a/app/assets/javascripts/monitoring/components/graph/axis.vue b/app/assets/javascripts/monitoring/components/graph/axis.vue index ae397fc39e2..6e15f938ab7 100644 --- a/app/assets/javascripts/monitoring/components/graph/axis.vue +++ b/app/assets/javascripts/monitoring/components/graph/axis.vue @@ -1,4 +1,6 @@ <script> +import { convertToSentenceCase } from '~/lib/utils/text_utility'; + export default { props: { graphWidth: { @@ -21,6 +23,10 @@ export default { type: String, required: true, }, + unitOfDisplay: { + type: String, + required: true, + }, }, data() { return { @@ -64,6 +70,10 @@ export default { this.measurements.axisLabelLineOffset || 0 ); }, + + yAxisLabelSentenceCase() { + return `${convertToSentenceCase(this.yAxisLabel)} (${this.unitOfDisplay})`; + }, }, mounted() { this.$nextTick(() => { @@ -106,7 +116,7 @@ export default { :transform="textTransform" ref="ylabel" > - {{ yAxisLabel }} + {{ yAxisLabelSentenceCase }} </text> <rect class="rect-axis-text" diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue index 8e6a830f08c..02f62ca2c40 100644 --- a/app/assets/javascripts/monitoring/components/graph/flag.vue +++ b/app/assets/javascripts/monitoring/components/graph/flag.vue @@ -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> diff --git a/app/assets/javascripts/monitoring/components/graph/legend.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue index ca3081a6306..140190d34a9 100644 --- a/app/assets/javascripts/monitoring/components/graph/legend.vue +++ b/app/assets/javascripts/monitoring/components/graph/legend.vue @@ -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)}`; }, @@ -50,6 +37,9 @@ export default { :key="index" > <td> + <strong>{{ series.track }}</strong> + </td> + <td> <svg width="15" height="6" @@ -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> diff --git a/app/assets/javascripts/monitoring/utils/multiple_time_series.js b/app/assets/javascripts/monitoring/utils/multiple_time_series.js index 95db31c7a2a..633f3509f3c 100644 --- a/app/assets/javascripts/monitoring/utils/multiple_time_series.js +++ b/app/assets/javascripts/monitoring/utils/multiple_time_series.js @@ -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, @@ -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) { @@ -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); @@ -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), @@ -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), []), ), [], ); @@ -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), ); }, []); } diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js index e57a55fa71a..ae00fb76714 100644 --- a/spec/javascripts/lib/utils/text_utility_spec.js +++ b/spec/javascripts/lib/utils/text_utility_spec.js @@ -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 .', + ); }); }); @@ -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'); + }); + }); }); diff --git a/spec/javascripts/monitoring/graph/axis_spec.js b/spec/javascripts/monitoring/graph/axis_spec.js index a251a72cfcf..c7adba00637 100644 --- a/spec/javascripts/monitoring/graph/axis_spec.js +++ b/spec/javascripts/monitoring/graph/axis_spec.js @@ -17,6 +17,7 @@ const defaultValuesComponent = { margin: measurements.large.margin, measurements: measurements.large, yAxisLabel: 'Values', + unitOfDisplay: 'MB', }; function getTextFromNode(component, selector) { @@ -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', () => { @@ -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)'); }); }); @@ -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)'); }); }); diff --git a/spec/javascripts/monitoring/graph/legend_spec.js b/spec/javascripts/monitoring/graph/legend_spec.js index b571450fcc2..32ae28fd06d 100644 --- a/spec/javascripts/monitoring/graph/legend_spec.js +++ b/spec/javascripts/monitoring/graph/legend_spec.js @@ -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'); |