Commit 2686807f authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '214370-extend-metrics-settings' into 'master'

Make operations/metrics settings extensible

See merge request gitlab-org/gitlab!32494
parents d816cb6c 4a7cdcbf
<script>
import { mapState, mapActions } from 'vuex';
import { GlLink, GlFormGroup, GlFormInput } from '@gitlab/ui';
export default {
components: {
GlLink,
GlFormGroup,
GlFormInput,
},
computed: {
...mapState(['externalDashboard']),
userDashboardUrl: {
get() {
return this.externalDashboard.url;
},
set(url) {
this.setExternalDashboardUrl(url);
},
},
},
methods: {
...mapActions(['setExternalDashboardUrl']),
},
};
</script>
<template>
<gl-form-group
:label="s__('MetricsSettings|External dashboard URL')"
label-for="external-dashboard-url"
>
<template #description>
{{
s__(
'MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard.',
)
}}
<gl-link :href="externalDashboard.helpPage">{{ __('Learn more') }}</gl-link>
</template>
<!-- placeholder with a url is a false positive -->
<!-- eslint-disable @gitlab/vue-require-i18n-attribute-strings -->
<gl-form-input
id="external-dashboard-url"
v-model="userDashboardUrl"
placeholder="https://my-org.gitlab.io/my-dashboards"
/>
<!-- eslint-enable @gitlab/vue-require-i18n-attribute-strings -->
</gl-form-group>
</template>
<script> <script>
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { GlDeprecatedButton, GlFormGroup, GlFormInput, GlLink } from '@gitlab/ui'; import { GlDeprecatedButton, GlLink } from '@gitlab/ui';
import ExternalDashboard from './form_group/external_dashboard.vue';
export default { export default {
components: { components: {
GlDeprecatedButton, GlDeprecatedButton,
GlFormGroup,
GlFormInput,
GlLink, GlLink,
ExternalDashboard,
}, },
computed: { computed: {
...mapState([ ...mapState(['helpPage']),
'externalDashboardHelpPagePath',
'externalDashboardUrl',
'operationsSettingsEndpoint',
]),
userDashboardUrl: { userDashboardUrl: {
get() { get() {
return this.externalDashboardUrl; return this.externalDashboard.url;
}, },
set(url) { set(url) {
this.setExternalDashboardUrl(url); this.setExternalDashboardUrl(url);
...@@ -25,7 +21,7 @@ export default { ...@@ -25,7 +21,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(['setExternalDashboardUrl', 'updateExternalDashboardUrl']), ...mapActions(['saveChanges']),
}, },
}; };
</script> </script>
...@@ -34,36 +30,18 @@ export default { ...@@ -34,36 +30,18 @@ export default {
<section class="settings no-animate"> <section class="settings no-animate">
<div class="settings-header"> <div class="settings-header">
<h3 class="js-section-header h4"> <h3 class="js-section-header h4">
{{ s__('ExternalMetrics|External Dashboard') }} {{ s__('MetricsSettings|Metrics Dashboard') }}
</h3> </h3>
<gl-deprecated-button class="js-settings-toggle">{{ __('Expand') }}</gl-deprecated-button> <gl-deprecated-button class="js-settings-toggle">{{ __('Expand') }}</gl-deprecated-button>
<p class="js-section-sub-header"> <p class="js-section-sub-header">
{{ {{ s__('MetricsSettings|Manage Metrics Dashboard settings.') }}
s__( <gl-link :href="helpPage">{{ __('Learn more') }}</gl-link>
'ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards.',
)
}}
<gl-link :href="externalDashboardHelpPagePath">{{ __('Learn more') }}</gl-link>
</p> </p>
</div> </div>
<div class="settings-content"> <div class="settings-content">
<form> <form>
<gl-form-group <external-dashboard />
:label="s__('ExternalMetrics|Full dashboard URL')" <gl-deprecated-button variant="success" @click="saveChanges">
label-for="full-dashboard-url"
:description="s__('ExternalMetrics|Enter the URL of the dashboard you want to link to')"
>
<!-- placeholder with a url is a false positive -->
<!-- eslint-disable @gitlab/vue-require-i18n-attribute-strings -->
<gl-form-input
id="full-dashboard-url"
v-model="userDashboardUrl"
placeholder="https://my-org.gitlab.io/my-dashboards"
@keydown.enter.native.prevent="updateExternalDashboardUrl"
/>
<!-- eslint-enable @gitlab/vue-require-i18n-attribute-strings -->
</gl-form-group>
<gl-deprecated-button variant="success" @click="updateExternalDashboardUrl">
{{ __('Save Changes') }} {{ __('Save Changes') }}
</gl-deprecated-button> </gl-deprecated-button>
</form> </form>
......
import Vue from 'vue'; import Vue from 'vue';
import store from './store'; import store from './store';
import ExternalDashboardForm from './components/external_dashboard.vue'; import MetricsSettingsForm from './components/metrics_settings.vue';
export default () => { export default () => {
const el = document.querySelector('.js-operation-settings'); const el = document.querySelector('.js-operation-settings');
...@@ -9,7 +9,7 @@ export default () => { ...@@ -9,7 +9,7 @@ export default () => {
el, el,
store: store(el.dataset), store: store(el.dataset),
render(createElement) { render(createElement) {
return createElement(ExternalDashboardForm); return createElement(MetricsSettingsForm);
}, },
}); });
}; };
...@@ -7,19 +7,19 @@ import * as mutationTypes from './mutation_types'; ...@@ -7,19 +7,19 @@ import * as mutationTypes from './mutation_types';
export const setExternalDashboardUrl = ({ commit }, url) => export const setExternalDashboardUrl = ({ commit }, url) =>
commit(mutationTypes.SET_EXTERNAL_DASHBOARD_URL, url); commit(mutationTypes.SET_EXTERNAL_DASHBOARD_URL, url);
export const updateExternalDashboardUrl = ({ state, dispatch }) => export const saveChanges = ({ state, dispatch }) =>
axios axios
.patch(state.operationsSettingsEndpoint, { .patch(state.operationsSettingsEndpoint, {
project: { project: {
metrics_setting_attributes: { metrics_setting_attributes: {
external_dashboard_url: state.externalDashboardUrl, external_dashboard_url: state.externalDashboard.url,
}, },
}, },
}) })
.then(() => dispatch('receiveExternalDashboardUpdateSuccess')) .then(() => dispatch('receiveSaveChangesSuccess'))
.catch(error => dispatch('receiveExternalDashboardUpdateError', error)); .catch(error => dispatch('receiveSaveChangesError', error));
export const receiveExternalDashboardUpdateSuccess = () => { export const receiveSaveChangesSuccess = () => {
/** /**
* The operations_controller currently handles successful requests * The operations_controller currently handles successful requests
* by creating a flash banner messsage to notify the user. * by creating a flash banner messsage to notify the user.
...@@ -27,8 +27,8 @@ export const receiveExternalDashboardUpdateSuccess = () => { ...@@ -27,8 +27,8 @@ export const receiveExternalDashboardUpdateSuccess = () => {
refreshCurrentPage(); refreshCurrentPage();
}; };
export const receiveExternalDashboardUpdateError = (_, error) => { export const receiveSaveChangesError = (_, error) => {
const { response } = error; const { response = {} } = error;
const message = response.data && response.data.message ? response.data.message : ''; const message = response.data && response.data.message ? response.data.message : '';
createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert'); createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
......
...@@ -2,6 +2,6 @@ import * as types from './mutation_types'; ...@@ -2,6 +2,6 @@ import * as types from './mutation_types';
export default { export default {
[types.SET_EXTERNAL_DASHBOARD_URL](state, url) { [types.SET_EXTERNAL_DASHBOARD_URL](state, url) {
state.externalDashboardUrl = url; state.externalDashboard.url = url;
}, },
}; };
export default (initialState = {}) => ({ export default (initialState = {}) => ({
externalDashboardUrl: initialState.externalDashboardUrl || '',
operationsSettingsEndpoint: initialState.operationsSettingsEndpoint, operationsSettingsEndpoint: initialState.operationsSettingsEndpoint,
externalDashboardHelpPagePath: initialState.externalDashboardHelpPagePath, helpPage: initialState.helpPage,
externalDashboard: {
url: initialState.externalDashboardUrl,
helpPage: initialState.externalDashboardHelpPage,
},
}); });
.js-operation-settings{ data: { operations_settings_endpoint: project_settings_operations_path(@project), .js-operation-settings{ data: { operations_settings_endpoint: project_settings_operations_path(@project),
help_page: help_page_path('user/project/integrations/prometheus'),
external_dashboard: { url: metrics_external_dashboard_url, external_dashboard: { url: metrics_external_dashboard_url,
help_page_path: help_page_path('user/project/operations/linking_to_an_external_dashboard') } } } help_page: help_page_path('user/project/operations/linking_to_an_external_dashboard'),
} } }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
= render 'projects/settings/operations/incidents' = render 'projects/settings/operations/incidents'
= render 'projects/settings/operations/error_tracking' = render 'projects/settings/operations/error_tracking'
= render 'projects/settings/operations/prometheus', service: prometheus_service if Feature.enabled?(:settings_operations_prometheus_service) = render 'projects/settings/operations/prometheus', service: prometheus_service if Feature.enabled?(:settings_operations_prometheus_service)
= render 'projects/settings/operations/external_dashboard' = render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/grafana_integration' = render 'projects/settings/operations/grafana_integration'
= render_if_exists 'projects/settings/operations/tracing' = render_if_exists 'projects/settings/operations/tracing'
= render_if_exists 'projects/settings/operations/status_page' = render_if_exists 'projects/settings/operations/status_page'
---
title: Update operations metrics settings title and description to make them general
merge_request: 32494
author:
type: changed
...@@ -9119,18 +9119,6 @@ msgstr "" ...@@ -9119,18 +9119,6 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used." msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "" msgstr ""
msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
msgstr ""
msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
msgstr ""
msgid "ExternalMetrics|External Dashboard"
msgstr ""
msgid "ExternalMetrics|Full dashboard URL"
msgstr ""
msgid "ExternalWikiService|External Wiki" msgid "ExternalWikiService|External Wiki"
msgstr "" msgstr ""
...@@ -13727,6 +13715,18 @@ msgstr "" ...@@ -13727,6 +13715,18 @@ msgstr ""
msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard" msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
msgstr "" msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
msgid "MetricsSettings|Manage Metrics Dashboard settings."
msgstr ""
msgid "MetricsSettings|Metrics Dashboard"
msgstr ""
msgid "Metrics|Add metric" msgid "Metrics|Add metric"
msgstr "" msgstr ""
......
import { mount, shallowMount } from '@vue/test-utils'; import { mount, shallowMount } from '@vue/test-utils';
import { GlDeprecatedButton, GlLink, GlFormGroup, GlFormInput } from '@gitlab/ui'; import { GlDeprecatedButton, GlLink, GlFormGroup, GlFormInput } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import ExternalDashboard from '~/operation_settings/components/external_dashboard.vue'; import MetricsSettings from '~/operation_settings/components/metrics_settings.vue';
import ExternalDashboard from '~/operation_settings/components/form_group/external_dashboard.vue';
import store from '~/operation_settings/store'; import store from '~/operation_settings/store';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility'; import { refreshCurrentPage } from '~/lib/utils/url_utility';
...@@ -12,18 +13,25 @@ jest.mock('~/flash'); ...@@ -12,18 +13,25 @@ jest.mock('~/flash');
describe('operation settings external dashboard component', () => { describe('operation settings external dashboard component', () => {
let wrapper; let wrapper;
const operationsSettingsEndpoint = `${TEST_HOST}/mock/ops/settings/endpoint`; const operationsSettingsEndpoint = `${TEST_HOST}/mock/ops/settings/endpoint`;
const helpPage = `${TEST_HOST}/help/metrics/page/path`;
const externalDashboardUrl = `http://mock-external-domain.com/external/dashboard/url`; const externalDashboardUrl = `http://mock-external-domain.com/external/dashboard/url`;
const externalDashboardHelpPagePath = `${TEST_HOST}/help/page/path`; const externalDashboardHelpPage = `${TEST_HOST}/help/external/page/path`;
const mountComponent = (shallow = true) => { const mountComponent = (shallow = true) => {
const config = [ const config = [
ExternalDashboard, MetricsSettings,
{ {
store: store({ store: store({
operationsSettingsEndpoint, operationsSettingsEndpoint,
helpPage,
externalDashboardUrl, externalDashboardUrl,
externalDashboardHelpPagePath, externalDashboardHelpPage,
}), }),
stubs: {
ExternalDashboard,
},
}, },
]; ];
wrapper = shallow ? shallowMount(...config) : mount(...config); wrapper = shallow ? shallowMount(...config) : mount(...config);
...@@ -44,7 +52,7 @@ describe('operation settings external dashboard component', () => { ...@@ -44,7 +52,7 @@ describe('operation settings external dashboard component', () => {
it('renders header text', () => { it('renders header text', () => {
mountComponent(); mountComponent();
expect(wrapper.find('.js-section-header').text()).toBe('External Dashboard'); expect(wrapper.find('.js-section-header').text()).toBe('Metrics Dashboard');
}); });
describe('expand/collapse button', () => { describe('expand/collapse button', () => {
...@@ -64,16 +72,14 @@ describe('operation settings external dashboard component', () => { ...@@ -64,16 +72,14 @@ describe('operation settings external dashboard component', () => {
}); });
it('renders descriptive text', () => { it('renders descriptive text', () => {
expect(subHeader.text()).toContain( expect(subHeader.text()).toContain('Manage Metrics Dashboard settings.');
'Add a button to the metrics dashboard linking directly to your existing external dashboards.',
);
}); });
it('renders help page link', () => { it('renders help page link', () => {
const link = subHeader.find(GlLink); const link = subHeader.find(GlLink);
expect(link.text()).toBe('Learn more'); expect(link.text()).toBe('Learn more');
expect(link.attributes().href).toBe(externalDashboardHelpPagePath); expect(link.attributes().href).toBe(helpPage);
}); });
}); });
...@@ -82,18 +88,17 @@ describe('operation settings external dashboard component', () => { ...@@ -82,18 +88,17 @@ describe('operation settings external dashboard component', () => {
let formGroup; let formGroup;
beforeEach(() => { beforeEach(() => {
mountComponent(); mountComponent(false);
formGroup = wrapper.find(GlFormGroup); formGroup = wrapper.find(ExternalDashboard).find(GlFormGroup);
}); });
it('uses label text', () => { it('uses label text', () => {
expect(formGroup.attributes().label).toBe('Full dashboard URL'); expect(formGroup.find('label').text()).toBe('External dashboard URL');
}); });
it('uses description text', () => { it('uses description text', () => {
expect(formGroup.attributes().description).toBe( const description = formGroup.find('small');
'Enter the URL of the dashboard you want to link to', expect(description.find('a').attributes('href')).toBe(externalDashboardHelpPage);
);
}); });
}); });
......
...@@ -13,7 +13,7 @@ describe('operation settings mutations', () => { ...@@ -13,7 +13,7 @@ describe('operation settings mutations', () => {
const mockUrl = 'mockUrl'; const mockUrl = 'mockUrl';
mutations.SET_EXTERNAL_DASHBOARD_URL(localState, mockUrl); mutations.SET_EXTERNAL_DASHBOARD_URL(localState, mockUrl);
expect(localState.externalDashboardUrl).toBe(mockUrl); expect(localState.externalDashboard.url).toBe(mockUrl);
}); });
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment