summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriel Santiago <adriel@gitlab.com>2019-04-29 17:06:37 -0400
committerAdriel Santiago <adriel@gitlab.com>2019-05-07 11:09:55 -0400
commitd32bb780e39740ee4472e15bad7683171e07ad9e (patch)
tree9b520fc2c17a1600f4117658aa08bc3b81a0a9ba
parent5c07f932bb7f99f231d83351e9a0f500d98074a2 (diff)
downloadgitlab-ce-ce-4452-in-line-chart-designer-mvc.tar.gz
Add custom metrics form to dashboardce-4452-in-line-chart-designer-mvc
Use existing form to allow users to add custom metrics via the dashboard
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue168
-rw-r--r--app/assets/stylesheets/framework/common.scss24
-rw-r--r--app/assets/stylesheets/framework/variables.scss8
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js7
5 files changed, 150 insertions, 60 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index a2bf58d007c..ff1e1805948 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,5 +1,12 @@
<script>
-import { GlButton, GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlModalDirective,
+ GlLink,
+} from '@gitlab/ui';
import _ from 'underscore';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
@@ -27,8 +34,11 @@ export default {
GlDropdown,
GlDropdownItem,
GlLink,
+ GlModal,
+ },
+ directives: {
+ GlModalDirective,
},
-
props: {
externalDashboardPath: {
type: String,
@@ -102,6 +112,19 @@ export default {
type: Boolean,
required: true,
},
+ customMetricsAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ customMetricsPath: {
+ type: String,
+ required: true,
+ },
+ validateQueryPath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -111,8 +134,14 @@ export default {
elWidth: 0,
selectedTimeWindow: '',
selectedTimeWindowKey: '',
+ formIsValid: null,
};
},
+ computed: {
+ canAddMetrics() {
+ return this.customMetricsAvailable && this.customMetricsPath.length;
+ },
+ },
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
@@ -193,11 +222,20 @@ export default {
this.state = 'unableToConnect';
});
},
+ hideAddMetricModal() {
+ this.$refs.addMetricModal.hide();
+ },
onSidebarMutation() {
setTimeout(() => {
this.elWidth = this.$el.clientWidth;
}, sidebarAnimationDuration);
},
+ setFormValidity(isValid) {
+ this.formIsValid = isValid;
+ },
+ submitCustomMetricsForm() {
+ this.$refs.customMetricsForm.submit();
+ },
activeTimeWindow(key) {
return this.timeWindows[key] === this.selectedTimeWindow;
},
@@ -205,57 +243,97 @@ export default {
return `?time_window=${key}`;
},
},
+ addMetric: {
+ title: s__('Metrics|Add metric'),
+ modalId: 'add-metric',
+ },
};
</script>
<template>
- <div v-if="!showEmptyState" class="prometheus-graphs prepend-top-default">
- <div
- v-if="environmentsEndpoint"
- class="dropdowns d-flex align-items-center justify-content-between"
- >
- <div class="d-flex align-items-center">
- <strong>{{ s__('Metrics|Environment') }}</strong>
- <gl-dropdown
- class="prepend-left-10 js-environments-dropdown"
- toggle-class="dropdown-menu-toggle"
- :text="currentEnvironmentName"
- :disabled="store.environmentsData.length === 0"
- >
- <gl-dropdown-item
- v-for="environment in store.environmentsData"
- :key="environment.id"
- :href="environment.metrics_path"
- :active="environment.name === currentEnvironmentName"
- active-class="is-active"
- >{{ environment.name }}</gl-dropdown-item
+ <div v-if="!showEmptyState" class="prometheus-graphs">
+ <div class="gl-p-3 border-bottom bg-gray-light d-flex justify-content-between">
+ <div
+ v-if="environmentsEndpoint"
+ class="dropdowns d-flex align-items-center justify-content-between"
+ >
+ <div class="d-flex align-items-center">
+ <strong>{{ s__('Metrics|Environment') }}</strong>
+ <gl-dropdown
+ class="prepend-left-10 js-environments-dropdown"
+ toggle-class="dropdown-menu-toggle"
+ :text="currentEnvironmentName"
+ :disabled="store.environmentsData.length === 0"
+ >
+ <gl-dropdown-item
+ v-for="environment in store.environmentsData"
+ :key="environment.id"
+ :active="environment.name === currentEnvironmentName"
+ active-class="is-active"
+ >{{ environment.name }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ <div v-if="showTimeWindowDropdown" class="d-flex align-items-center">
+ <strong>{{ s__('Metrics|Show last') }}</strong>
+ <gl-dropdown
+ class="prepend-left-10 js-time-window-dropdown"
+ toggle-class="dropdown-menu-toggle"
+ :text="selectedTimeWindow"
>
- </gl-dropdown>
+ <gl-dropdown-item
+ v-for="(value, key) in timeWindows"
+ :key="key"
+ :active="activeTimeWindow(key)"
+ ><gl-link :href="setTimeWindowParameter(key)">{{ value }}</gl-link></gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
</div>
- <div v-if="showTimeWindowDropdown" class="d-flex align-items-center">
- <strong>{{ s__('Metrics|Show last') }}</strong>
- <gl-dropdown
- class="prepend-left-10 js-time-window-dropdown"
- toggle-class="dropdown-menu-toggle"
- :text="selectedTimeWindow"
- >
- <gl-dropdown-item
- v-for="(value, key) in timeWindows"
- :key="key"
- :active="activeTimeWindow(key)"
- ><gl-link :href="setTimeWindowParameter(key)">{{ value }}</gl-link></gl-dropdown-item
+ <div class="d-flex">
+ <div v-if="isEE && canAddMetrics">
+ <gl-button
+ v-gl-modal-directive="$options.addMetric.modalId"
+ class="js-add-metric-button text-success border-success"
>
- </gl-dropdown>
+ {{ $options.addMetric.title }}
+ </gl-button>
+ <gl-modal
+ ref="addMetricModal"
+ :modal-id="$options.addMetric.modalId"
+ :title="$options.addMetric.title"
+ >
+ <form ref="customMetricsForm" :action="customMetricsPath" method="post">
+ <custom-metrics-form-fields
+ :validate-query-path="validateQueryPath"
+ form-operation="post"
+ @formValidation="setFormValidity"
+ />
+ </form>
+ <div slot="modal-footer">
+ <gl-button @click="hideAddMetricModal">
+ {{ __('Cancel') }}
+ </gl-button>
+ <gl-button
+ :disabled="!formIsValid"
+ variant="success"
+ @click="submitCustomMetricsForm"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ </div>
+ </gl-modal>
+ </div>
+ <gl-button
+ v-if="externalDashboardPath.length"
+ class="js-external-dashboard-link prepend-left-8"
+ variant="primary"
+ :href="externalDashboardPath"
+ >
+ {{ __('View full dashboard') }}
+ <icon name="external-link" />
+ </gl-button>
</div>
- <gl-button
- v-if="externalDashboardPath.length"
- class="js-external-dashboard-link"
- variant="primary"
- :href="externalDashboardPath"
- >
- {{ __('View full dashboard') }}
- <icon name="external-link" />
- </gl-button>
</div>
<graph-group
v-for="(groupData, index) in store.groups"
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index dffd5e70edb..2b499e50ea3 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -48,6 +48,10 @@
color: $brand-info;
}
+.bg-gray-light {
+ background-color: $gray-light;
+}
+
.text-break-word {
word-break: break-all;
}
@@ -446,19 +450,13 @@ img.emoji {
}
/** COMMON SPACING CLASSES **/
-.gl-pl-0 { padding-left: 0; }
-.gl-pl-1 { padding-left: #{0.5 * $grid-size}; }
-.gl-pl-2 { padding-left: $grid-size; }
-.gl-pl-3 { padding-left: #{2 * $grid-size}; }
-.gl-pl-4 { padding-left: #{3 * $grid-size}; }
-.gl-pl-5 { padding-left: #{4 * $grid-size}; }
-
-.gl-pr-0 { padding-right: 0; }
-.gl-pr-1 { padding-right: #{0.5 * $grid-size}; }
-.gl-pr-2 { padding-right: $grid-size; }
-.gl-pr-3 { padding-right: #{2 * $grid-size}; }
-.gl-pr-4 { padding-right: #{3 * $grid-size}; }
-.gl-pr-5 { padding-right: #{4 * $grid-size}; }
+@each $index, $padding in $spacing-scale {
+ #{'.gl-p-#{$index}'} { padding: $padding; }
+ #{'.gl-pl-#{$index}'} { padding-left: $padding; }
+ #{'.gl-pr-#{$index}'} { padding-right: $padding; }
+ #{'.gl-pt-#{$index}'} { padding-top: $padding; }
+ #{'.gl-pb-#{$index}'} { padding-bottom: $padding; }
+}
/**
* Removes browser specific clear icon from input fields in
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index da1f196afdb..4a034e1e547 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -11,6 +11,14 @@ $default-transition-duration: 0.15s;
$contextual-sidebar-width: 220px;
$contextual-sidebar-collapsed-width: 50px;
$toggle-sidebar-height: 48px;
+$spacing-scale: (
+ 0: 0,
+ 1: #{0.5 * $grid-size},
+ 2: $grid-size,
+ 3: #{2 * $grid-size},
+ 4: #{3 * $grid-size},
+ 5: #{4 * $grid-size}
+);
/*
* Color schema
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 05e56f2b89d..86f7ade9ceb 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5905,6 +5905,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index fc722867b0b..e9bd6050d68 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -20,6 +20,9 @@ const propsData = {
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
currentEnvironmentName: 'production',
+ customMetricsAvailable: false,
+ customMetricsPath: '',
+ validateQueryPath: '',
};
export default propsData;
@@ -163,7 +166,7 @@ describe('Dashboard', () => {
});
});
- it('renders the environments dropdown with a single is-active element', done => {
+ it('renders the environments dropdown with a single active element', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
@@ -178,7 +181,7 @@ describe('Dashboard', () => {
setTimeout(() => {
const dropdownItems = component.$el.querySelectorAll(
- '.js-environments-dropdown .dropdown-item.is-active',
+ '.js-environments-dropdown .dropdown-item[active="true"]',
);
expect(dropdownItems.length).toEqual(1);