diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared')
-rw-r--r-- | app/assets/javascripts/vue_shared/ci_action_icons.js | 4 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/loading_icon.vue | 33 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/memory_graph.js | 107 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/table_pagination.vue (renamed from app/assets/javascripts/vue_shared/components/table_pagination.js) | 38 |
4 files changed, 150 insertions, 32 deletions
diff --git a/app/assets/javascripts/vue_shared/ci_action_icons.js b/app/assets/javascripts/vue_shared/ci_action_icons.js index 734b3c6c45e..ee41dc95beb 100644 --- a/app/assets/javascripts/vue_shared/ci_action_icons.js +++ b/app/assets/javascripts/vue_shared/ci_action_icons.js @@ -1,6 +1,7 @@ import cancelSVG from 'icons/_icon_action_cancel.svg'; import retrySVG from 'icons/_icon_action_retry.svg'; import playSVG from 'icons/_icon_action_play.svg'; +import stopSVG from 'icons/_icon_action_stop.svg'; export default function getActionIcon(action) { let icon; @@ -14,6 +15,9 @@ export default function getActionIcon(action) { case 'icon_action_play': icon = playSVG; break; + case 'icon_action_stop': + icon = stopSVG; + break; default: icon = ''; } diff --git a/app/assets/javascripts/vue_shared/components/loading_icon.vue b/app/assets/javascripts/vue_shared/components/loading_icon.vue new file mode 100644 index 00000000000..41b1d0165b0 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/loading_icon.vue @@ -0,0 +1,33 @@ +<script> + export default { + props: { + label: { + type: String, + required: false, + default: 'Loading', + }, + + size: { + type: String, + required: false, + default: '1', + }, + }, + + computed: { + cssClass() { + return `fa-${this.size}x`; + }, + }, + }; +</script> +<template> + <div class="text-center"> + <i + class="fa fa-spin fa-spinner" + :class="cssClass" + aria-hidden="true" + :aria-label="label"> + </i> + </div> +</template> diff --git a/app/assets/javascripts/vue_shared/components/memory_graph.js b/app/assets/javascripts/vue_shared/components/memory_graph.js index 2a605b24339..643b77e04c7 100644 --- a/app/assets/javascripts/vue_shared/components/memory_graph.js +++ b/app/assets/javascripts/vue_shared/components/memory_graph.js @@ -2,6 +2,7 @@ export default { name: 'MemoryGraph', props: { metrics: { type: Array, required: true }, + deploymentTime: { type: Number, required: true }, width: { type: String, required: true }, height: { type: String, required: true }, }, @@ -9,27 +10,105 @@ export default { return { pathD: '', pathViewBox: '', - // dotX: '', - // dotY: '', + dotX: '', + dotY: '', }; }, + computed: { + getFormattedMedian() { + const deployedSince = gl.utils.getTimeago().format(this.deploymentTime * 1000); + return `Deployed ${deployedSince}`; + }, + }, + methods: { + /** + * Returns metric value index in metrics array + * with timestamp closest to matching median + */ + getMedianMetricIndex(median, metrics) { + let matchIndex = 0; + let timestampDiff = 0; + let smallestDiff = 0; + + const metricTimestamps = metrics.map(v => v[0]); + + // Find metric timestamp which is closest to deploymentTime + timestampDiff = Math.abs(metricTimestamps[0] - median); + metricTimestamps.forEach((timestamp, index) => { + if (index === 0) { // Skip first element + return; + } + + smallestDiff = Math.abs(timestamp - median); + if (smallestDiff < timestampDiff) { + matchIndex = index; + timestampDiff = smallestDiff; + } + }); + + return matchIndex; + }, + + /** + * Get Graph Plotting values to render Line and Dot + */ + getGraphPlotValues(median, metrics) { + const renderData = metrics.map(v => v[1]); + const medianMetricIndex = this.getMedianMetricIndex(median, metrics); + let cx = 0; + let cy = 0; + + // Find Maximum and Minimum values from `renderData` array + const maxMemory = Math.max.apply(null, renderData); + const minMemory = Math.min.apply(null, renderData); + + // Find difference between extreme ends + const diff = maxMemory - minMemory; + const lineWidth = renderData.length; + + // Iterate over metrics values and perform following + // 1. Find x & y co-ords for deploymentTime's memory value + // 2. Return line path against maxMemory + const linePath = renderData.map((y, x) => { + if (medianMetricIndex === x) { + cx = x; + cy = maxMemory - y; + } + return `${x} ${maxMemory - y}`; + }); + + return { + pathD: linePath, + pathViewBox: { + lineWidth, + diff, + }, + dotX: cx, + dotY: cy, + }; + }, + + /** + * Render Graph based on provided median and metrics values + */ + renderGraph(median, metrics) { + const { pathD, pathViewBox, dotX, dotY } = this.getGraphPlotValues(median, metrics); + + // Set props and update graph on UI. + this.pathD = `M ${pathD}`; + this.pathViewBox = `0 0 ${pathViewBox.lineWidth} ${pathViewBox.diff}`; + this.dotX = dotX; + this.dotY = dotY; + }, + }, mounted() { - const renderData = this.$props.metrics.map(v => v[1]); - const maxMemory = Math.max.apply(null, renderData); - const minMemory = Math.min.apply(null, renderData); - const diff = maxMemory - minMemory; - // const cx = 0; - // const cy = 0; - const lineWidth = renderData.length; - const linePath = renderData.map((y, x) => `${x} ${maxMemory - y}`); - this.pathD = `M ${linePath}`; - this.pathViewBox = `0 0 ${lineWidth} ${diff}`; + this.renderGraph(this.deploymentTime, this.metrics); }, template: ` <div class="memory-graph-container"> - <svg :width="width" :height="height" xmlns="http://www.w3.org/2000/svg"> + <svg class="has-tooltip" :title="getFormattedMedian" :width="width" :height="height" xmlns="http://www.w3.org/2000/svg"> <path :d="pathD" :viewBox="pathViewBox" /> - <!--<circle r="0.8" :cx="dotX" :cy="dotY" tranform="translate(0 -1)" /> --> + <circle r="1.5" :cx="dotX" :cy="dotY" tranform="translate(0 -1)" /> </svg> </div> `, diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.js b/app/assets/javascripts/vue_shared/components/table_pagination.vue index ebb14912b00..5e7df22dd83 100644 --- a/app/assets/javascripts/vue_shared/components/table_pagination.js +++ b/app/assets/javascripts/vue_shared/components/table_pagination.vue @@ -1,3 +1,4 @@ +<script> const PAGINATION_UI_BUTTON_LIMIT = 4; const UI_LIMIT = 6; const SPREAD = '...'; @@ -114,22 +115,23 @@ export default { return items; }, }, - template: ` - <div class="gl-pagination"> - <ul class="pagination clearfix"> - <li v-for='item in getItems' - :class='{ - page: item.page, - prev: item.prev, - next: item.next, - separator: item.separator, - active: item.active, - disabled: item.disabled - }' - > - <a @click="changePage($event)">{{item.title}}</a> - </li> - </ul> - </div> - `, }; +</script> +<template> + <div class="gl-pagination"> + <ul class="pagination clearfix"> + <li + v-for="item in getItems" + :class="{ + page: item.page, + prev: item.prev, + next: item.next, + separator: item.separator, + active: item.active, + disabled: item.disabled + }"> + <a @click="changePage($event)">{{item.title}}</a> + </li> + </ul> + </div> +</template> |