Commit 9e7622d3 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'tr-remove-alert-service-settings' into 'master'

Remove alert service settings

See merge request gitlab-org/gitlab!53851
parents 5937731a 40d59ec1
<script>
import {
GlButton,
GlFormGroup,
GlFormInput,
GlLink,
GlModal,
GlModalDirective,
GlSprintf,
} from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import axios from '~/lib/utils/axios_utils';
import { s__, __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
export default {
i18n: {
usageSection: s__(
'AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.',
),
setupSection: s__(
"AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
),
},
COPY_TO_CLIPBOARD: __('Copy'),
RESET_KEY: __('Reset key'),
components: {
GlButton,
GlFormGroup,
GlFormInput,
GlLink,
GlModal,
GlSprintf,
ClipboardButton,
ToggleButton,
},
directives: {
'gl-modal': GlModalDirective,
},
props: {
alertsSetupUrl: {
type: String,
required: true,
},
alertsUsageUrl: {
type: String,
required: true,
},
initialAuthorizationKey: {
type: String,
required: false,
default: '',
},
formPath: {
type: String,
required: true,
},
url: {
type: String,
required: true,
},
initialActivated: {
type: Boolean,
required: true,
},
isDisabled: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
activated: this.initialActivated,
loadingActivated: false,
authorizationKey: this.initialAuthorizationKey,
};
},
computed: {
sections() {
return [
{
text: this.$options.i18n.usageSection,
url: this.alertsUsageUrl,
},
{
text: this.$options.i18n.setupSection,
url: this.alertsSetupUrl,
},
];
},
},
methods: {
resetKey() {
return axios
.put(this.formPath, { service: { token: '' } })
.then((res) => {
this.authorizationKey = res.data.token;
})
.catch(() => {
createFlash(__('Failed to reset key. Please try again.'));
});
},
toggleActivated(value) {
this.loadingActivated = true;
return axios
.put(this.formPath, { service: { active: value } })
.then(() => {
this.activated = value;
this.loadingActivated = false;
})
.catch(() => {
createFlash(__('Update failed. Please try again.'));
this.loadingActivated = false;
});
},
},
};
</script>
<template>
<div>
<div data-testid="description">
<p v-for="section in sections" :key="section.text">
<gl-sprintf :message="section.text">
<template #link="{ content }">
<gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
</div>
<gl-form-group :label="__('Active')" label-for="activated" label-class="label-bold">
<toggle-button
id="activated"
:disabled-input="loadingActivated || isDisabled"
:is-loading="loadingActivated"
:value="activated"
@change="toggleActivated"
/>
</gl-form-group>
<gl-form-group :label="__('URL')" label-for="url" label-class="label-bold">
<div class="input-group">
<gl-form-input id="url" :readonly="true" :value="url" />
<span class="input-group-append">
<clipboard-button
:text="url"
:title="$options.COPY_TO_CLIPBOARD"
:disabled="isDisabled"
/>
</span>
</div>
</gl-form-group>
<gl-form-group
:label="__('Authorization key')"
label-for="authorization-key"
label-class="label-bold"
>
<div class="input-group">
<gl-form-input id="authorization-key" :readonly="true" :value="authorizationKey" />
<span class="input-group-append">
<clipboard-button
:text="authorizationKey"
:title="$options.COPY_TO_CLIPBOARD"
:disabled="isDisabled"
/>
</span>
</div>
<gl-button v-gl-modal.authKeyModal class="gl-mt-2" :disabled="isDisabled">{{
$options.RESET_KEY
}}</gl-button>
<gl-modal
modal-id="authKeyModal"
:title="$options.RESET_KEY"
:ok-title="$options.RESET_KEY"
ok-variant="danger"
@ok="resetKey"
>
{{
__(
'Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
)
}}
</gl-modal>
</gl-form-group>
</div>
</template>
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertsServiceForm from './components/alerts_service_form.vue';
export default (el) => {
if (!el) {
return null;
}
const {
activated: activatedStr,
alertsSetupUrl,
alertsUsageUrl,
formPath,
authorizationKey,
url,
disabled,
} = el.dataset;
const activated = parseBoolean(activatedStr);
const isDisabled = parseBoolean(disabled);
return new Vue({
el,
render(createElement) {
return createElement(AlertsServiceForm, {
props: {
alertsSetupUrl,
alertsUsageUrl,
initialActivated: activated,
formPath,
initialAuthorizationKey: authorizationKey,
url,
isDisabled,
},
});
},
});
};
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
......@@ -11,6 +10,4 @@ document.addEventListener('DOMContentLoaded', () => {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
integrationSettingsForm.init();
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
......@@ -11,6 +10,4 @@ document.addEventListener('DOMContentLoaded', () => {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import CustomMetrics from '~/prometheus_metrics/custom_metrics';
import PrometheusAlerts from '~/prometheus_alerts';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
......@@ -15,5 +14,4 @@ document.addEventListener('DOMContentLoaded', () => {
}
PrometheusAlerts();
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
......@@ -2636,12 +2636,6 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
msgid "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
msgstr ""
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
msgstr ""
msgid "AlertSettings|1. Select integration type"
msgstr ""
......@@ -24967,9 +24961,6 @@ msgstr ""
msgid "Reset to project defaults"
msgstr ""
msgid "Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
msgstr ""
msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
msgstr ""
......@@ -31324,9 +31315,6 @@ msgstr ""
msgid "Update failed"
msgstr ""
msgid "Update failed. Please try again."
msgstr ""
msgid "Update it"
msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AlertsServiceForm with default values renders "authorization-key" input 1`] = `"<gl-form-input-stub id=\\"authorization-key\\" readonly=\\"true\\" value=\\"abcedfg123\\"></gl-form-input-stub>"`;
exports[`AlertsServiceForm with default values renders "url" input 1`] = `"<gl-form-input-stub id=\\"url\\" readonly=\\"true\\" value=\\"https://gitlab.com/endpoint-url\\"></gl-form-input-stub>"`;
exports[`AlertsServiceForm with default values renders toggle button 1`] = `"<toggle-button-stub id=\\"activated\\"></toggle-button-stub>"`;
exports[`AlertsServiceForm with default values shows description and docs links 1`] = `"<p><gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub></p><p><gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub></p>"`;
import { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
import AlertsServiceForm from '~/alerts_service_settings/components/alerts_service_form.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
const defaultProps = {
initialAuthorizationKey: 'abcedfg123',
formPath: 'http://invalid',
url: 'https://gitlab.com/endpoint-url',
alertsSetupUrl: 'http://invalid',
alertsUsageUrl: 'http://invalid',
initialActivated: false,
isDisabled: false,
};
describe('AlertsServiceForm', () => {
let wrapper;
let mockAxios;
const createComponent = (props = defaultProps) => {
wrapper = shallowMount(AlertsServiceForm, {
propsData: {
...defaultProps,
...props,
},
});
};
const findUrl = () => wrapper.find('#url');
const findAuthorizationKey = () => wrapper.find('#authorization-key');
const findDescription = () => wrapper.find('[data-testid="description"');
beforeEach(() => {
mockAxios = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
mockAxios.restore();
});
describe('with default values', () => {
beforeEach(() => {
createComponent();
});
it('renders "url" input', () => {
expect(findUrl().html()).toMatchSnapshot();
});
it('renders "authorization-key" input', () => {
expect(findAuthorizationKey().html()).toMatchSnapshot();
});
it('renders toggle button', () => {
expect(wrapper.find(ToggleButton).html()).toMatchSnapshot();
});
it('shows description and docs links', () => {
expect(findDescription().element.innerHTML).toMatchSnapshot();
});
});
describe('reset key', () => {
it('updates the authorization key on success', async () => {
const formPath = 'some/path';
mockAxios.onPut(formPath).replyOnce(200, { token: 'newToken' });
createComponent({ formPath });
wrapper.find(GlModal).vm.$emit('ok');
await axios.waitForAll();
expect(findAuthorizationKey().attributes('value')).toBe('newToken');
});
it('shows flash message on error', () => {
const formPath = 'some/path';
mockAxios.onPut(formPath).replyOnce(404);
createComponent({ formPath });
return wrapper.vm.resetKey().then(() => {
expect(findAuthorizationKey().attributes('value')).toBe(
defaultProps.initialAuthorizationKey,
);
expect(createFlash).toHaveBeenCalled();
});
});
});
describe('activate toggle', () => {
describe('successfully completes', () => {
describe.each`
initialActivated | value
${false} | ${true}
${true} | ${false}
`(
'when initialActivated=$initialActivated and value=$value',
({ initialActivated, value }) => {
beforeEach(() => {
const formPath = 'some/path';
mockAxios
.onPut(formPath, { service: { active: value } })
.replyOnce(200, { active: value });
createComponent({ initialActivated, formPath });
return wrapper.vm.toggleActivated(value);
});
it(`updates toggle button value to ${value}`, () => {
expect(wrapper.find(ToggleButton).props('value')).toBe(value);
});
},
);
});
describe('error is encountered', () => {
beforeEach(() => {
const formPath = 'some/path';
mockAxios.onPut(formPath).replyOnce(500);
});
it('restores previous value', () => {
createComponent({ initialActivated: false });
return wrapper.vm.toggleActivated(true).then(() => {
expect(wrapper.find(ToggleButton).props('value')).toBe(false);
});
});
});
});
describe('form is disabled', () => {
beforeEach(() => {
createComponent({ isDisabled: true });
});
it('cannot be toggled', () => {
wrapper.find(ToggleButton).vm.$emit('change');
return nextTick().then(() => {
expect(wrapper.find(ToggleButton).props('disabledInput')).toBe(true);
});
});
});
});
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