Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-04 15:09:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-04 15:09:14 +0300
commit8a9cbfa9c56792d8e338c289eb803fb0ebde2083 (patch)
treefa5ff83fa919ae9a1c37cd8146b78a4a04c9ab7c /app/assets/javascripts/alerts_settings
parentfc7ce8aea5b2eca1aaf510667c79b3e7e72f2f3f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/alerts_settings')
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue32
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue9
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue287
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue55
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue91
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js17
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql12
-rw-r--r--app/assets/javascripts/alerts_settings/index.js12
9 files changed, 443 insertions, 82 deletions
diff --git a/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue b/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue
new file mode 100644
index 00000000000..674e3696eb5
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alert_settings_form_help_block.vue
@@ -0,0 +1,32 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ props: {
+ message: {
+ type: String,
+ required: true,
+ },
+ link: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <span class="gl-text-gray-500">
+ <gl-sprintf :message="message">
+ <template #link="{ content }">
+ <gl-link class="gl-display-inline-block" :href="link" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
index 432271d2075..1c22f035a15 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -81,7 +81,6 @@ export default {
<div class="incident-management-list">
<h5 class="gl-font-lg">{{ $options.i18n.title }}</h5>
<gl-table
- :empty-text="$options.i18n.emptyState"
:items="integrations"
:fields="$options.fields"
:busy="loading"
@@ -115,6 +114,14 @@ export default {
<template #table-busy>
<gl-loading-icon size="lg" color="dark" class="mt-3" />
</template>
+
+ <template #empty>
+ <div
+ class="gl-border-t-solid gl-border-b-solid gl-border-1 gl-border gl-border-gray-100 mt-n3"
+ >
+ <p class="gl-text-gray-400 gl-py-3 gl-my-3">{{ $options.i18n.emptyState }}</p>
+ </div>
+ </template>
</gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue
index 1490723ff76..84ee2fb524d 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_new.vue
@@ -6,63 +6,166 @@ import {
GlFormGroup,
GlFormSelect,
GlFormInput,
- GlLink,
- GlSprintf,
+ GlFormInputGroup,
+ GlFormTextarea,
+ GlModal,
+ GlModalDirective,
+ GlToggle,
} from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale';
-import { integrationTypes } from '../constants';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import AlertSettingsFormHelpBlock from './alert_settings_form_help_block.vue';
+import {
+ integrationTypesNew,
+ JSON_VALIDATE_DELAY,
+ targetPrometheusUrlPlaceholder,
+ typeSet,
+} from '../constants';
export default {
+ targetPrometheusUrlPlaceholder,
+ JSON_VALIDATE_DELAY,
+ typeSet,
i18n: {
- integrationsInfo: s__(
- 'AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}',
- ),
integrationFormSteps: {
- step1: { title: s__('AlertSettings|1. Select integration type') },
- step2: { title: s__('AlertSettings|2. Name integration') },
+ step1: {
+ label: s__('AlertSettings|1. Select integration type'),
+ help: s__('AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}'),
+ },
+ step2: {
+ label: s__('AlertSettings|2. Name integration'),
+ placeholder: s__('AlertSettings|Enter integration name'),
+ },
+ step3: {
+ label: s__('AlertSettings|3. Set up webhook'),
+ help: s__(
+ 'AlertSettings|Utilize the URL and authorization key below to authorize an external service to send Alerts to GitLab. Review your chosen services documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.',
+ ),
+ info: s__('AlertSettings|Authorization key'),
+ reset: s__('AlertSettings|Reset Key'),
+ },
+ step4: {
+ label: s__('AlertSettings|4. Test integration(optional)'),
+ help: s__(
+ 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with to send a test alert to the %{linkStart}alerts page%{linkEnd}. This payload can be used to test the integration using the "save and test payload" button.',
+ ),
+ placeholder: s__('AlertSettings|Enter test alert JSON....'),
+ },
step5: {
- title: s__('AlertSettings|5. Map fields (optional)'),
+ label: s__('AlertSettings|5. Map fields (optional)'),
intro: s__(
'AlertSettings|The default GitLab alert keys are listed below. In the event an exact match could be found in the sample payload provided, that key will be mapped automatically. In all other cases, please define which payload key should map to the specified GitLab key. Any payload keys not shown in this list will not display in the alert list, but will display on the alert details page.',
),
},
+ prometheusFormUrl: {
+ label: s__('AlertSettings|Prometheus API base URL'),
+ help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
+ },
},
},
components: {
+ ClipboardButton,
GlButton,
GlCollapse,
GlForm,
GlFormGroup,
GlFormInput,
+ GlFormInputGroup,
+ GlFormTextarea,
GlFormSelect,
- GlLink,
- GlSprintf,
+ GlModal,
+ GlToggle,
+ AlertSettingsFormHelpBlock,
+ },
+ directives: {
+ 'gl-modal': GlModalDirective,
+ },
+ inject: {
+ generic: {
+ default: {},
+ },
+ prometheus: {
+ default: {},
+ },
},
mixins: [glFeatureFlagsMixin()],
+ props: {
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ },
data() {
return {
- selectedIntegration: integrationTypes[0].value,
- options: integrationTypes,
+ selectedIntegration: integrationTypesNew[0].value,
+ options: integrationTypesNew,
formVisible: false,
- form: {
+ integrationForm: {
name: '',
+ integrationTestPayload: {
+ json: null,
+ error: null,
+ },
+ active: false,
+ authKey: '',
+ url: '',
+ apiUrl: '',
},
};
},
+ computed: {
+ jsonIsValid() {
+ return this.integrationForm.integrationTestPayload.error === null;
+ },
+ selectedIntegrationType() {
+ switch (this.selectedIntegration) {
+ case this.$options.typeSet.http:
+ return this.generic;
+ case this.$options.typeSet.prometheus:
+ return this.prometheus;
+ default:
+ return {};
+ }
+ },
+ },
methods: {
onIntegrationTypeSelect() {
- if (this.selectedIntegration === integrationTypes[0].value) {
+ if (this.selectedIntegration === integrationTypesNew[0].value) {
this.formVisible = false;
} else {
this.formVisible = true;
}
},
+ onSubmitWithTestPayload() {
+ // TODO: Test payload before saving via GraphQL
+ this.onSubmit();
+ },
onSubmit() {
- // TODO Add GraphQL method
+ const { name, apiUrl, active } = this.integrationForm;
+ const variables =
+ this.selectedIntegration === this.$options.typeSet.http
+ ? { name, active }
+ : { apiUrl, active };
+ this.$emit('on-create-new-integration', { type: this.selectedIntegration, variables });
},
onReset() {
- this.form.name = '';
+ // TODO: Reset form values
+ },
+ onResetAuthKey() {
+ // TODO: Handle reset auth key via GraphQL
+ },
+ validateJson() {
+ this.integrationForm.integrationTestPayload.error = null;
+ if (this.integrationForm.integrationTestPayload.json === '') {
+ return;
+ }
+
+ try {
+ JSON.parse(this.integrationForm.integrationTestPayload.json);
+ } catch (e) {
+ this.integrationForm.integrationTestPayload.error = JSON.stringify(e.message);
+ }
},
},
};
@@ -74,7 +177,7 @@ export default {
<gl-form-group
id="integration-type"
- :label="$options.i18n.integrationFormSteps.step1.title"
+ :label="$options.i18n.integrationFormSteps.step1.label"
label-for="integration-type"
>
<gl-form-select
@@ -82,54 +185,158 @@ export default {
:options="options"
@change="onIntegrationTypeSelect"
/>
- <span class="gl-text-gray-500">
- <gl-sprintf :message="$options.i18n.integrationsInfo">
- <template #link="{ content }">
- <gl-link
- class="gl-display-inline-block"
- href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
- target="_blank"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </span>
+
+ <alert-settings-form-help-block
+ :message="$options.i18n.integrationFormSteps.step1.help"
+ link="https://gitlab.com/groups/gitlab-org/-/epics/4390"
+ />
</gl-form-group>
<gl-collapse v-model="formVisible" class="gl-mt-3">
<gl-form-group
id="name-integration"
- :label="$options.i18n.integrationFormSteps.step2.title"
+ :label="$options.i18n.integrationFormSteps.step2.label"
label-for="name-integration"
>
<gl-form-input
- v-model="form.name"
+ v-model="integrationForm.name"
type="text"
- :placeholder="s__('AlertSettings|Enter integration name')"
+ :placeholder="$options.i18n.integrationFormSteps.step2.placeholder"
+ />
+ </gl-form-group>
+ <gl-form-group
+ id="integration-webhook"
+ :label="$options.i18n.integrationFormSteps.step3.label"
+ label-for="integration-webhook"
+ >
+ <alert-settings-form-help-block
+ :message="$options.i18n.integrationFormSteps.step3.help"
+ link="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
+ />
+
+ <gl-toggle
+ v-model="integrationForm.active"
+ :is-loading="loading"
+ :label="__('Active')"
+ class="gl-my-4 gl-font-weight-normal"
+ />
+
+ <div v-if="selectedIntegration === $options.typeSet.prometheus" class="gl-my-4">
+ <span>
+ {{ $options.i18n.integrationFormSteps.prometheusFormUrl.label }}
+ </span>
+
+ <gl-form-input
+ id="integration-apiUrl"
+ v-model="integrationForm.apiUrl"
+ type="text"
+ :placeholder="$options.targetPrometheusUrlPlaceholder"
+ />
+
+ <span class="gl-text-gray-400">
+ {{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
+ </span>
+ </div>
+
+ <div class="gl-my-4">
+ <span>
+ {{ s__('AlertSettings|Webhook URL') }}
+ </span>
+
+ <gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
+ <template #append>
+ <clipboard-button
+ :text="selectedIntegrationType.url || ''"
+ :title="__('Copy')"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+ </div>
+
+ <div class="gl-my-4">
+ <span>
+ {{ $options.i18n.integrationFormSteps.step3.info }}
+ </span>
+
+ <gl-form-input-group
+ id="authorization-key"
+ class="gl-mb-2"
+ readonly
+ :value="selectedIntegrationType.authKey"
+ >
+ <template #append>
+ <clipboard-button
+ :text="selectedIntegrationType.authKey || ''"
+ :title="__('Copy')"
+ class="gl-m-0!"
+ />
+ </template>
+ </gl-form-input-group>
+
+ <gl-button v-gl-modal.authKeyModal :disabled="!integrationForm.active" class="gl-mt-3">{{
+ $options.i18n.integrationFormSteps.step3.reset
+ }}</gl-button>
+ <gl-modal
+ modal-id="authKeyModal"
+ :title="$options.i18n.integrationFormSteps.step3.reset"
+ :ok-title="$options.i18n.integrationFormSteps.step3.reset"
+ ok-variant="danger"
+ @ok="() => {}"
+ >
+ {{ $options.i18n.integrationFormSteps.step3.reset }}
+ </gl-modal>
+ </div>
+ </gl-form-group>
+ <gl-form-group
+ id="test-integration"
+ :label="$options.i18n.integrationFormSteps.step4.label"
+ label-for="test-integration"
+ :invalid-feedback="integrationForm.integrationTestPayload.error"
+ >
+ <alert-settings-form-help-block
+ :message="$options.i18n.integrationFormSteps.step4.help"
+ :link="generic.alertsUsageUrl"
+ />
+
+ <gl-form-textarea
+ id="test-integration"
+ v-model.trim="integrationForm.integrationTestPayload.json"
+ :disabled="!integrationForm.active"
+ :state="jsonIsValid"
+ :placeholder="$options.i18n.integrationFormSteps.step4.placeholder"
+ class="gl-my-4"
+ :debounce="$options.JSON_VALIDATE_DELAY"
+ rows="6"
+ max-rows="10"
+ @input="validateJson"
/>
</gl-form-group>
<gl-form-group
v-if="glFeatures.multipleHttpIntegrationsCustomMapping"
id="mapping-builder"
- :label="$options.i18n.integrationFormSteps.step5.title"
+ :label="$options.i18n.integrationFormSteps.step5.label"
label-for="mapping-builder"
>
<span class="gl-text-gray-500">{{ $options.i18n.integrationFormSteps.step5.intro }}</span>
<!--mapping builder will be added here-->
</gl-form-group>
-
<div class="gl-display-flex gl-justify-content-end">
<gl-button type="reset" class="gl-mr-3 js-no-auto-disable">{{ __('Cancel') }}</gl-button>
<gl-button
- type="submit"
category="secondary"
variant="success"
class="gl-mr-1 js-no-auto-disable"
- >{{ __('Save and test payload') }}</gl-button
+ @click="onSubmitWithTestPayload"
+ >{{ s__('AlertSettings|Save and test payload') }}</gl-button
+ >
+ <gl-button
+ type="submit"
+ variant="success"
+ class="js-no-auto-disable"
+ data-testid="integration-form-submit"
+ >{{ s__('AlertSettings|Save integration') }}</gl-button
>
- <gl-button type="submit" variant="success" class="js-no-auto-disable">{{
- s__('AlertSettings|Save integration')
- }}</gl-button>
</div>
</gl-collapse>
</gl-form>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue
index ab6d5526154..7d5ea9aa8c4 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form_old.vue
@@ -56,7 +56,7 @@ export default {
data() {
return {
loading: false,
- selectedIntegration: integrationTypes[1].value,
+ selectedIntegration: integrationTypes[0].value,
options: integrationTypes,
active: false,
authKey: '',
@@ -88,34 +88,34 @@ export default {
];
},
isPrometheus() {
- return this.selectedIntegration === 'prometheus';
+ return this.selectedIntegration === 'PROMETHEUS';
},
isOpsgenie() {
- return this.selectedIntegration === 'opsgenie';
+ return this.selectedIntegration === 'OPSGENIE';
},
selectedIntegrationType() {
switch (this.selectedIntegration) {
- case 'generic': {
+ case 'HTTP': {
return {
url: this.generic.url,
- authKey: this.generic.authorizationKey,
- activated: this.generic.activated,
+ authKey: this.generic.authKey,
+ active: this.generic.active,
resetKey: this.resetKey.bind(this),
};
}
- case 'prometheus': {
+ case 'PROMETHEUS': {
return {
- url: this.prometheus.prometheusUrl,
- authKey: this.prometheus.authorizationKey,
- activated: this.prometheus.activated,
- resetKey: this.resetKey.bind(this, 'prometheus'),
+ url: this.prometheus.url,
+ authKey: this.prometheus.authKey,
+ active: this.prometheus.active,
+ resetKey: this.resetKey.bind(this, 'PROMETHEUS'),
targetUrl: this.prometheus.prometheusApiUrl,
};
}
- case 'opsgenie': {
+ case 'OPSGENIE': {
return {
targetUrl: this.opsgenie.opsgenieMvcTargetUrl,
- activated: this.opsgenie.activated,
+ active: this.opsgenie.active,
};
}
default: {
@@ -161,16 +161,12 @@ export default {
},
},
mounted() {
- if (
- this.prometheus.activated ||
- this.generic.activated ||
- !this.opsgenie.opsgenieMvcIsAvailable
- ) {
+ if (this.prometheus.active || this.generic.active || !this.opsgenie.opsgenieMvcIsAvailable) {
this.removeOpsGenieOption();
- } else if (this.opsgenie.activated) {
+ } else if (this.opsgenie.active) {
this.setOpsgenieAsDefault();
}
- this.active = this.selectedIntegrationType.activated;
+ this.active = this.selectedIntegrationType.active;
this.authKey = this.selectedIntegrationType.authKey ?? '';
},
methods: {
@@ -183,19 +179,19 @@ export default {
},
setOpsgenieAsDefault() {
this.options = this.options.map(el => {
- if (el.value !== 'opsgenie') {
+ if (el.value !== 'OPSGENIE') {
return { ...el, disabled: true };
}
return { ...el, disabled: false };
});
- this.selectedIntegration = this.options.find(({ value }) => value === 'opsgenie').value;
+ this.selectedIntegration = this.options.find(({ value }) => value === 'OPSGENIE').value;
if (this.targetUrl === null) {
this.targetUrl = this.selectedIntegrationType.targetUrl;
}
},
removeOpsGenieOption() {
this.options = this.options.map(el => {
- if (el.value !== 'opsgenie') {
+ if (el.value !== 'OPSGENIE') {
return { ...el, disabled: false };
}
return { ...el, disabled: true };
@@ -204,7 +200,7 @@ export default {
resetFormValues() {
this.testAlert.json = null;
this.targetUrl = this.selectedIntegrationType.targetUrl;
- this.active = this.selectedIntegrationType.activated;
+ this.active = this.selectedIntegrationType.active;
},
dismissFeedback() {
this.serverError = null;
@@ -212,7 +208,7 @@ export default {
this.isFeedbackDismissed = false;
},
resetKey(key) {
- const fn = key === 'prometheus' ? this.resetPrometheusKey() : this.resetGenericKey();
+ const fn = key === 'PROMETHEUS' ? this.resetPrometheusKey() : this.resetGenericKey();
return fn
.then(({ data: { token } }) => {
@@ -242,9 +238,10 @@ export default {
},
toggleActivated(value) {
this.loading = true;
+ const path = this.isOpsgenie ? this.opsgenie.formPath : this.generic.formPath;
return service
.updateGenericActive({
- endpoint: this[this.selectedIntegration].formPath,
+ endpoint: path,
params: this.isOpsgenie
? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
: { service: { active: value } },
@@ -345,7 +342,7 @@ export default {
if (this.canSaveForm) {
this.canSaveForm = false;
- this.active = this.selectedIntegrationType.activated;
+ this.active = this.selectedIntegrationType.active;
}
},
},
@@ -402,9 +399,9 @@ export default {
</gl-sprintf>
</span>
</gl-form-group>
- <gl-form-group :label="$options.i18n.activeLabel" label-for="activated">
+ <gl-form-group :label="$options.i18n.activeLabel" label-for="active">
<toggle-button
- id="activated"
+ id="active"
:disabled-input="loading"
:is-loading="loading"
:value="active"
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index 1576faf13a9..7fe0a4ad2cb 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,13 +1,24 @@
<script>
+import produce from 'immer';
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { fetchPolicies } from '~/lib/graphql';
+import createFlash, { FLASH_TYPES } from '~/flash';
import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
+import createHttpIntegrationMutation from '../graphql/mutations/create_http_integration.mutation.graphql';
+import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
import IntegrationsList from './alerts_integrations_list.vue';
import SettingsFormOld from './alerts_settings_form_old.vue';
import SettingsFormNew from './alerts_settings_form_new.vue';
+import { typeSet } from '../constants';
export default {
+ typeSet,
+ i18n: {
+ changesSaved: s__(
+ 'AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list.',
+ ),
+ },
components: {
IntegrationsList,
SettingsFormOld,
@@ -49,6 +60,7 @@ export default {
data() {
return {
errored: false,
+ isUpdating: false,
integrations: {},
};
},
@@ -61,16 +73,85 @@ export default {
{
name: s__('AlertSettings|HTTP endpoint'),
type: s__('AlertsIntegrations|HTTP endpoint'),
- active: this.generic.activated,
+ active: this.generic.active,
},
{
name: s__('AlertSettings|External Prometheus'),
type: s__('AlertsIntegrations|Prometheus'),
- active: this.prometheus.activated,
+ active: this.prometheus.active,
},
];
},
},
+ methods: {
+ onCreateNewIntegration({ type, variables }) {
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation:
+ type === this.$options.typeSet.http
+ ? createHttpIntegrationMutation
+ : createPrometheusIntegrationMutation,
+ variables: {
+ ...variables,
+ projectPath: this.projectPath,
+ },
+ update: this.updateIntegrations,
+ })
+ .then(({ data: { httpIntegrationCreate, prometheusIntegrationCreate } = {} } = {}) => {
+ const error = httpIntegrationCreate?.errors[0] || prometheusIntegrationCreate?.errors[0];
+ if (error) {
+ return createFlash({ message: error });
+ }
+ return createFlash({
+ message: this.$options.i18n.changesSaved,
+ type: FLASH_TYPES.SUCCESS,
+ });
+ })
+ .catch(err => {
+ this.errored = true;
+ createFlash({ message: err });
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ updateIntegrations(
+ store,
+ {
+ data: { httpIntegrationCreate, prometheusIntegrationCreate },
+ },
+ ) {
+ const integration =
+ httpIntegrationCreate?.integration || prometheusIntegrationCreate?.integration;
+ if (!integration) {
+ return;
+ }
+
+ const sourceData = store.readQuery({
+ query: getIntegrationsQuery,
+ variables: {
+ projectPath: this.projectPath,
+ },
+ });
+
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.alertManagementIntegrations.nodes = [
+ integration,
+ ...draftData.project.alertManagementIntegrations.nodes,
+ ];
+ });
+
+ store.writeQuery({
+ query: getIntegrationsQuery,
+ variables: {
+ projectPath: this.projectPath,
+ },
+ data,
+ });
+ },
+ },
};
</script>
@@ -80,7 +161,11 @@ export default {
:integrations="glFeatures.httpIntegrationsList ? integrations.list : intergrationsOptionsOld"
:loading="loading"
/>
- <settings-form-new v-if="glFeatures.httpIntegrationsList" />
+ <settings-form-new
+ v-if="glFeatures.httpIntegrationsList"
+ :loading="loading"
+ @on-create-new-integration="onCreateNewIntegration"
+ />
<settings-form-old v-else />
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index 74e39534eb5..7e0422c100d 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -1,5 +1,6 @@
import { s__ } from '~/locale';
+// TODO: Remove this as part of the form old removal
export const i18n = {
usageSection: s__(
'AlertSettings|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.',
@@ -39,13 +40,23 @@ export const i18n = {
integration: s__('AlertSettings|Integration'),
};
+// TODO: Delete as part of old form removal in 13.6
export const integrationTypes = [
+ { value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') },
+ { value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') },
+ { value: 'OPSGENIE', text: s__('AlertSettings|Opsgenie') },
+];
+
+export const integrationTypesNew = [
{ value: '', text: s__('AlertSettings|Select integration type') },
- { value: 'generic', text: s__('AlertSettings|HTTP Endpoint') },
- { value: 'prometheus', text: s__('AlertSettings|External Prometheus') },
- { value: 'opsgenie', text: s__('AlertSettings|Opsgenie') },
+ ...integrationTypes,
];
+export const typeSet = {
+ http: 'HTTP',
+ prometheus: 'PROMETHEUS',
+};
+
export const JSON_VALIDATE_DELAY = 250;
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
new file mode 100644
index 00000000000..d1dacbad40a
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) {
+ httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql
new file mode 100644
index 00000000000..bb22795ddd5
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql
@@ -0,0 +1,12 @@
+#import "../fragments/integration_item.fragment.graphql"
+
+mutation createPrometheusIntegration($projectPath: ID!, $apiUrl: String!, $active: Boolean!) {
+ prometheusIntegrationCreate(
+ input: { projectPath: $projectPath, apiUrl: $apiUrl, active: $active }
+ ) {
+ errors
+ integration {
+ ...IntegrationItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 8f22b8d1dcd..611148cd103 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -48,9 +48,9 @@ export default el => {
el,
provide: {
prometheus: {
- activated: parseBoolean(prometheusActivated),
- prometheusUrl,
- authorizationKey: prometheusAuthorizationKey,
+ active: parseBoolean(prometheusActivated),
+ url: prometheusUrl,
+ authKey: prometheusAuthorizationKey,
prometheusFormPath,
prometheusResetKeyPath,
prometheusApiUrl,
@@ -58,14 +58,14 @@ export default el => {
generic: {
alertsSetupUrl,
alertsUsageUrl,
- activated: parseBoolean(activatedStr),
+ active: parseBoolean(activatedStr),
formPath,
- authorizationKey,
+ authKey: authorizationKey,
url,
},
opsgenie: {
formPath: opsgenieMvcFormPath,
- activated: parseBoolean(opsgenieMvcEnabled),
+ active: parseBoolean(opsgenieMvcEnabled),
opsgenieMvcTargetUrl,
opsgenieMvcIsAvailable: parseBoolean(opsgenieMvcAvailable),
},