diff options
Diffstat (limited to 'app/assets')
27 files changed, 299 insertions, 41 deletions
diff --git a/app/assets/images/ci_favicons/dev/favicon_status_canceled.ico b/app/assets/images/ci_favicons/dev/favicon_status_canceled.ico Binary files differnew file mode 100644 index 00000000000..4af3582b60d --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_canceled.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_created.ico b/app/assets/images/ci_favicons/dev/favicon_status_created.ico Binary files differnew file mode 100644 index 00000000000..13639da2e8a --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_created.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_failed.ico b/app/assets/images/ci_favicons/dev/favicon_status_failed.ico Binary files differnew file mode 100644 index 00000000000..5f0e711b104 --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_failed.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_manual.ico b/app/assets/images/ci_favicons/dev/favicon_status_manual.ico Binary files differnew file mode 100644 index 00000000000..8b1168a1267 --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_manual.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_not_found.ico b/app/assets/images/ci_favicons/dev/favicon_status_not_found.ico Binary files differnew file mode 100644 index 00000000000..ed19b69e1c5 --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_not_found.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_pending.ico b/app/assets/images/ci_favicons/dev/favicon_status_pending.ico Binary files differnew file mode 100644 index 00000000000..5dfefd4cc5a --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_pending.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_running.ico b/app/assets/images/ci_favicons/dev/favicon_status_running.ico Binary files differnew file mode 100644 index 00000000000..a41539c0e3e --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_running.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_skipped.ico b/app/assets/images/ci_favicons/dev/favicon_status_skipped.ico Binary files differnew file mode 100644 index 00000000000..2c1ae552b93 --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_skipped.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_success.ico b/app/assets/images/ci_favicons/dev/favicon_status_success.ico Binary files differnew file mode 100644 index 00000000000..70f0ca61eca --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_success.ico diff --git a/app/assets/images/ci_favicons/dev/favicon_status_warning.ico b/app/assets/images/ci_favicons/dev/favicon_status_warning.ico Binary files differnew file mode 100644 index 00000000000..db289e03eb1 --- /dev/null +++ b/app/assets/images/ci_favicons/dev/favicon_status_warning.ico diff --git a/app/assets/images/ci_favicons/favicon_status_canceled.ico b/app/assets/images/ci_favicons/favicon_status_canceled.ico Binary files differindex 5a19458f2a2..23adcffff50 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_canceled.ico +++ b/app/assets/images/ci_favicons/favicon_status_canceled.ico diff --git a/app/assets/images/ci_favicons/favicon_status_created.ico b/app/assets/images/ci_favicons/favicon_status_created.ico Binary files differindex 4dca9640cb3..f9d93b390d8 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_created.ico +++ b/app/assets/images/ci_favicons/favicon_status_created.ico diff --git a/app/assets/images/ci_favicons/favicon_status_failed.ico b/app/assets/images/ci_favicons/favicon_status_failed.ico Binary files differindex c961ff9a69b..28a22ebf724 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_failed.ico +++ b/app/assets/images/ci_favicons/favicon_status_failed.ico diff --git a/app/assets/images/ci_favicons/favicon_status_manual.ico b/app/assets/images/ci_favicons/favicon_status_manual.ico Binary files differindex 5fbbc99ea7c..dbbf1abf30c 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_manual.ico +++ b/app/assets/images/ci_favicons/favicon_status_manual.ico diff --git a/app/assets/images/ci_favicons/favicon_status_not_found.ico b/app/assets/images/ci_favicons/favicon_status_not_found.ico Binary files differindex 21afa9c72e6..49b9b232dd1 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_not_found.ico +++ b/app/assets/images/ci_favicons/favicon_status_not_found.ico diff --git a/app/assets/images/ci_favicons/favicon_status_pending.ico b/app/assets/images/ci_favicons/favicon_status_pending.ico Binary files differindex 8be32dab85a..05962f3f148 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_pending.ico +++ b/app/assets/images/ci_favicons/favicon_status_pending.ico diff --git a/app/assets/images/ci_favicons/favicon_status_running.ico b/app/assets/images/ci_favicons/favicon_status_running.ico Binary files differindex f328ff1a5ed..7fa3d4d48d4 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_running.ico +++ b/app/assets/images/ci_favicons/favicon_status_running.ico diff --git a/app/assets/images/ci_favicons/favicon_status_skipped.ico b/app/assets/images/ci_favicons/favicon_status_skipped.ico Binary files differindex b4394e1b4af..b0c26b62068 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_skipped.ico +++ b/app/assets/images/ci_favicons/favicon_status_skipped.ico diff --git a/app/assets/images/ci_favicons/favicon_status_success.ico b/app/assets/images/ci_favicons/favicon_status_success.ico Binary files differindex 4f436c95242..b150960b5be 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_success.ico +++ b/app/assets/images/ci_favicons/favicon_status_success.ico diff --git a/app/assets/images/ci_favicons/favicon_status_warning.ico b/app/assets/images/ci_favicons/favicon_status_warning.ico Binary files differindex 805cc20cdec..7e71d71684d 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_warning.ico +++ b/app/assets/images/ci_favicons/favicon_status_warning.ico diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 004bac09f59..f0066d4ec5d 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -27,6 +27,9 @@ gl.issueBoards.BoardSidebar = Vue.extend({ computed: { showSidebar () { return Object.keys(this.issue).length; + }, + assigneeId() { + return this.issue.assignee ? this.issue.assignee.id : 0; } }, watch: { diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js new file mode 100644 index 00000000000..c3a8da52404 --- /dev/null +++ b/app/assets/javascripts/monitoring/constants.js @@ -0,0 +1,4 @@ +import d3 from 'd3'; + +export const dateFormat = d3.time.format('%b %d, %Y'); +export const timeFormat = d3.time.format('%H:%M%p'); diff --git a/app/assets/javascripts/monitoring/deployments.js b/app/assets/javascripts/monitoring/deployments.js new file mode 100644 index 00000000000..fc92ab61b31 --- /dev/null +++ b/app/assets/javascripts/monitoring/deployments.js @@ -0,0 +1,211 @@ +/* global Flash */ +import d3 from 'd3'; +import { + dateFormat, + timeFormat, +} from './constants'; + +export default class Deployments { + constructor(width, height) { + this.width = width; + this.height = height; + + this.endpoint = document.getElementById('js-metrics').dataset.deploymentEndpoint; + + this.createGradientDef(); + } + + init(chartData) { + this.chartData = chartData; + + this.x = d3.time.scale().range([0, this.width]); + this.x.domain(d3.extent(this.chartData, d => d.time)); + + this.charts = d3.selectAll('.prometheus-graph'); + + this.getData(); + } + + getData() { + $.ajax({ + url: this.endpoint, + dataType: 'JSON', + }) + .fail(() => new Flash('Error getting deployment information.')) + .done((data) => { + this.data = data.deployments.reduce((deploymentDataArray, deployment) => { + const time = new Date(deployment.created_at); + const xPos = Math.floor(this.x(time)); + + time.setSeconds(this.chartData[0].time.getSeconds()); + + if (xPos >= 0) { + deploymentDataArray.push({ + id: deployment.id, + time, + sha: deployment.sha, + tag: deployment.tag, + ref: deployment.ref.name, + xPos, + }); + } + + return deploymentDataArray; + }, []); + + this.plotData(); + }); + } + + plotData() { + this.charts.each((d, i) => { + const svg = d3.select(this.charts[0][i]); + const chart = svg.select('.graph-container'); + const key = svg.node().getAttribute('graph-type'); + + this.createLine(chart, key); + this.createDeployInfoBox(chart, key); + }); + } + + createGradientDef() { + const defs = d3.select('body') + .append('svg') + .attr({ + height: 0, + width: 0, + }) + .append('defs'); + + defs.append('linearGradient') + .attr({ + id: 'shadow-gradient', + }) + .append('stop') + .attr({ + offset: '0%', + 'stop-color': '#000', + 'stop-opacity': 0.4, + }) + .select(this.selectParentNode) + .append('stop') + .attr({ + offset: '100%', + 'stop-color': '#000', + 'stop-opacity': 0, + }); + } + + createLine(chart, key) { + chart.append('g') + .attr({ + class: 'deploy-info', + }) + .selectAll('.deploy-info') + .data(this.data) + .enter() + .append('g') + .attr({ + class: d => `deploy-info-${d.id}-${key}`, + transform: d => `translate(${Math.floor(d.xPos) + 1}, 0)`, + }) + .append('rect') + .attr({ + x: 1, + y: 0, + height: this.height + 1, + width: 3, + fill: 'url(#shadow-gradient)', + }) + .select(this.selectParentNode) + .append('line') + .attr({ + class: 'deployment-line', + x1: 0, + x2: 0, + y1: 0, + y2: this.height + 1, + }); + } + + createDeployInfoBox(chart, key) { + chart.selectAll('.deploy-info') + .selectAll('.js-deploy-info-box') + .data(this.data) + .enter() + .select(d => document.querySelector(`.deploy-info-${d.id}-${key}`)) + .append('svg') + .attr({ + class: 'js-deploy-info-box hidden', + x: 3, + y: 0, + width: 92, + height: 60, + }) + .append('rect') + .attr({ + class: 'rect-text-metric deploy-info-rect rect-metric', + x: 1, + y: 1, + rx: 2, + width: 90, + height: 58, + }) + .select(this.selectParentNode) + .append('g') + .attr({ + transform: 'translate(5, 2)', + }) + .append('text') + .attr({ + class: 'deploy-info-text text-metric-bold', + }) + .text(Deployments.refText) + .select(this.selectParentNode) + .append('text') + .attr({ + class: 'deploy-info-text', + y: 18, + }) + .text(d => dateFormat(d.time)) + .select(this.selectParentNode) + .append('text') + .attr({ + class: 'deploy-info-text text-metric-bold', + y: 38, + }) + .text(d => timeFormat(d.time)); + } + + static toggleDeployTextbox(deploy, key, showInfoBox) { + d3.selectAll(`.deploy-info-${deploy.id}-${key} .js-deploy-info-box`) + .classed('hidden', !showInfoBox); + } + + mouseOverDeployInfo(mouseXPos, key) { + if (!this.data) return false; + + let dataFound = false; + + this.data.forEach((d) => { + if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) { + dataFound = d.xPos + 1; + + Deployments.toggleDeployTextbox(d, key, true); + } else { + Deployments.toggleDeployTextbox(d, key, false); + } + }); + + return dataFound; + } + + /* `this` is bound to the D3 node */ + selectParentNode() { + return this.parentNode; + } + + static refText(d) { + return d.tag ? d.ref : d.sha.slice(0, 6); + } +} diff --git a/app/assets/javascripts/monitoring/prometheus_graph.js b/app/assets/javascripts/monitoring/prometheus_graph.js index 78bb0e6fb47..6af88769129 100644 --- a/app/assets/javascripts/monitoring/prometheus_graph.js +++ b/app/assets/javascripts/monitoring/prometheus_graph.js @@ -3,16 +3,20 @@ import d3 from 'd3'; import statusCodes from '~/lib/utils/http_status'; -import { formatRelevantDigits } from '~/lib/utils/number_utils'; +import Deployments from './deployments'; +import '../lib/utils/common_utils'; +import { formatRelevantDigits } from '../lib/utils/number_utils'; import '../flash'; +import { + dateFormat, + timeFormat, +} from './constants'; const prometheusContainer = '.prometheus-container'; const prometheusParentGraphContainer = '.prometheus-graphs'; const prometheusGraphsContainer = '.prometheus-graph'; const prometheusStatesContainer = '.prometheus-state'; const metricsEndpoint = 'metrics.json'; -const timeFormat = d3.time.format('%H:%M'); -const dayFormat = d3.time.format('%b %e, %a'); const bisectDate = d3.bisector(d => d.time).left; const extraAddedWidthParent = 100; @@ -36,6 +40,7 @@ class PrometheusGraph { this.width = parentContainerWidth - this.margin.left - this.margin.right; this.height = this.originalHeight - this.margin.top - this.margin.bottom; this.backOffRequestCounter = 0; + this.deployments = new Deployments(this.width, this.height); this.configureGraph(); this.init(); } else { @@ -74,6 +79,12 @@ class PrometheusGraph { $(prometheusParentGraphContainer).show(); this.transformData(metricsResponse); this.createGraph(); + + const firstMetricData = this.graphSpecificProperties[ + Object.keys(this.graphSpecificProperties)[0] + ].data; + + this.deployments.init(firstMetricData); } }); } @@ -96,6 +107,7 @@ class PrometheusGraph { .attr('width', this.width + this.margin.left + this.margin.right) .attr('height', this.height + this.margin.bottom + this.margin.top) .append('g') + .attr('class', 'graph-container') .attr('transform', `translate(${this.margin.left},${this.margin.top})`); const axisLabelContainer = d3.select(prometheusGraphContainer) @@ -116,6 +128,7 @@ class PrometheusGraph { .scale(y) .ticks(this.commonGraphProperties.axis_no_ticks) .tickSize(-this.width) + .outerTickSize(0) .orient('left'); this.createAxisLabelContainers(axisLabelContainer, key); @@ -248,7 +261,8 @@ class PrometheusGraph { const d1 = currentGraphProps.data[overlayIndex]; const evalTime = timeValueOverlay - d0.time > d1.time - timeValueOverlay; const currentData = evalTime ? d1 : d0; - const currentTimeCoordinate = currentGraphProps.xScale(currentData.time); + const currentTimeCoordinate = Math.floor(currentGraphProps.xScale(currentData.time)); + const currentDeployXPos = this.deployments.mouseOverDeployInfo(currentXCoordinate, key); const currentPrometheusGraphContainer = `${prometheusGraphsContainer}[graph-type=${key}]`; const maxValueFromData = d3.max(currentGraphProps.data.map(metricValue => metricValue.value)); const maxMetricValue = currentGraphProps.yScale(maxValueFromData); @@ -256,13 +270,12 @@ class PrometheusGraph { // Clear up all the pieces of the flag d3.selectAll(`${currentPrometheusGraphContainer} .selected-metric-line`).remove(); d3.selectAll(`${currentPrometheusGraphContainer} .circle-metric`).remove(); - d3.selectAll(`${currentPrometheusGraphContainer} .rect-text-metric`).remove(); - d3.selectAll(`${currentPrometheusGraphContainer} .text-metric`).remove(); + d3.selectAll(`${currentPrometheusGraphContainer} .rect-text-metric:not(.deploy-info-rect)`).remove(); const currentChart = d3.select(currentPrometheusGraphContainer).select('g'); currentChart.append('line') - .attr('class', 'selected-metric-line') .attr({ + class: `${currentDeployXPos ? 'hidden' : ''} selected-metric-line`, x1: currentTimeCoordinate, y1: currentGraphProps.yScale(0), x2: currentTimeCoordinate, @@ -272,33 +285,45 @@ class PrometheusGraph { currentChart.append('circle') .attr('class', 'circle-metric') .attr('fill', currentGraphProps.line_color) - .attr('cx', currentTimeCoordinate) + .attr('cx', currentDeployXPos || currentTimeCoordinate) .attr('cy', currentGraphProps.yScale(currentData.value)) .attr('r', this.commonGraphProperties.circle_radius_metric); + if (currentDeployXPos) return; + // The little box with text - const rectTextMetric = currentChart.append('g') - .attr('class', 'rect-text-metric') - .attr('translate', `(${currentTimeCoordinate}, ${currentGraphProps.yScale(currentData.value)})`); + const rectTextMetric = currentChart.append('svg') + .attr({ + class: 'rect-text-metric', + x: currentTimeCoordinate, + y: 0, + }); rectTextMetric.append('rect') - .attr('class', 'rect-metric') - .attr('x', currentTimeCoordinate + 10) - .attr('y', maxMetricValue) - .attr('width', this.commonGraphProperties.rect_text_width) - .attr('height', this.commonGraphProperties.rect_text_height); + .attr({ + class: 'rect-metric', + x: 4, + y: 1, + rx: 2, + width: this.commonGraphProperties.rect_text_width, + height: this.commonGraphProperties.rect_text_height, + }); rectTextMetric.append('text') - .attr('class', 'text-metric') - .attr('x', currentTimeCoordinate + 35) - .attr('y', maxMetricValue + 35) + .attr({ + class: 'text-metric text-metric-bold', + x: 8, + y: 35, + }) .text(timeFormat(currentData.time)); rectTextMetric.append('text') - .attr('class', 'text-metric-date') - .attr('x', currentTimeCoordinate + 15) - .attr('y', maxMetricValue + 15) - .text(dayFormat(currentData.time)); + .attr({ + class: 'text-metric-date', + x: 8, + y: 15, + }) + .text(dateFormat(currentData.time)); let currentMetricValue = formatRelevantDigits(currentData.value); if (key === 'cpu_values') { diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index 0344ce9ffb4..68cf9ced3ef 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -30,7 +30,7 @@ $els.each((function(_this) { return function(i, dropdown) { var options = {}; - var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, firstUser, issueURL, selectedId, showAnyUser, showNullUser, showMenuAbove; + var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, defaultNullUser, firstUser, issueURL, selectedId, selectedIdDefault, showAnyUser, showNullUser, showMenuAbove; $dropdown = $(dropdown); options.projectId = $dropdown.data('project-id'); options.groupId = $dropdown.data('group-id'); @@ -38,11 +38,11 @@ options.todoFilter = $dropdown.data('todo-filter'); options.todoStateFilter = $dropdown.data('todo-state-filter'); showNullUser = $dropdown.data('null-user'); + defaultNullUser = $dropdown.data('null-user-default'); showMenuAbove = $dropdown.data('showMenuAbove'); showAnyUser = $dropdown.data('any-user'); firstUser = $dropdown.data('first-user'); options.authorId = $dropdown.data('author-id'); - selectedId = $dropdown.data('selected'); defaultLabel = $dropdown.data('default-label'); issueURL = $dropdown.data('issueUpdate'); $selectbox = $dropdown.closest('.selectbox'); @@ -51,6 +51,8 @@ $value = $block.find('.value'); $collapsedSidebar = $block.find('.sidebar-collapsed-user'); $loading = $block.find('.block-loading').fadeOut(); + selectedIdDefault = (defaultNullUser && showNullUser) ? 0 : null; + selectedId = $dropdown.data('selected') || selectedIdDefault; var updateIssueBoardsIssue = function () { $loading.removeClass('hidden').fadeIn(); @@ -186,12 +188,14 @@ fieldName: $dropdown.data('field-name'), toggleLabel: function(selected, el) { if (selected && 'id' in selected && $(el).hasClass('is-active')) { + $dropdown.find('.dropdown-toggle-text').removeClass('is-default'); if (selected.text) { return selected.text; } else { return selected.name; } } else { + $dropdown.find('.dropdown-toggle-text').addClass('is-default'); return defaultLabel; } }, @@ -204,13 +208,14 @@ }, vue: $dropdown.hasClass('js-issue-board-sidebar'), clicked: function(user, $el, e) { - var isIssueIndex, isMRIndex, page, selected; + var isIssueIndex, isMRIndex, page, selected, isSelecting; page = $('body').data('page'); isIssueIndex = page === 'projects:issues:index'; isMRIndex = (page === page && page === 'projects:merge_requests:index'); + isSelecting = (user.id !== selectedId); + selectedId = isSelecting ? user.id : selectedIdDefault; if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) { e.preventDefault(); - selectedId = user.id; if (selectedId === gon.current_user_id) { $('.assign-to-me-link').hide(); } else { @@ -221,12 +226,11 @@ if ($el.closest('.add-issues-modal').length) { gl.issueBoards.ModalStore.store.filter[$dropdown.data('field-name')] = user.id; } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { - selectedId = user.id; return Issuable.filterResults($dropdown.closest('form')); } else if ($dropdown.hasClass('js-filter-submit')) { return $dropdown.closest('form').submit(); } else if ($dropdown.hasClass('js-issue-board-sidebar')) { - if (user.id) { + if (user.id && isSelecting) { gl.issueBoards.boardStoreIssueSet('assignee', new ListUser({ id: user.id, username: user.username, @@ -248,6 +252,9 @@ }, opened: function(e) { const $el = $(e.currentTarget); + if ($dropdown.hasClass('js-issue-board-sidebar')) { + selectedId = parseInt($dropdown[0].dataset.selected, 10) || selectedIdDefault; + } $el.find('.is-active').removeClass('is-active'); $el.find(`li[data-user-id="${selectedId}"] .dropdown-menu-user-link`).addClass('is-active'); }, diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 1313ea25c2a..73ded9f30d4 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -390,7 +390,8 @@ &::before { position: absolute; left: 6px; - top: 6px; + top: 50%; + transform: translateY(-50%); font: normal normal normal 14px/1 FontAwesome; font-size: inherit; text-rendering: auto; diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 72e7d42858d..026d35295d7 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -157,7 +157,8 @@ .prometheus-graph { text { - fill: $stat-graph-axis-fill; + fill: $gl-text-color; + stroke-width: 0; } .label-axis-text, @@ -210,27 +211,33 @@ .rect-text-metric { fill: $white-light; stroke-width: 1; - stroke: $black; + stroke: $gray-darkest; } .rect-axis-text { fill: $white-light; } -.text-metric, -.text-median-metric, -.text-metric-usage, -.text-metric-date { - fill: $black; +.text-metric { + font-weight: 600; } -.text-metric-date { - font-weight: 200; +.selected-metric-line { + stroke: $gl-gray-dark; + stroke-width: 1; } -.selected-metric-line { +.deployment-line { stroke: $black; - stroke-width: 1; + stroke-width: 2; +} + +.deploy-info-text { + dominant-baseline: text-before-edge; +} + +.text-metric-bold { + font-weight: 600; } .prometheus-state { |