debian-mirror-gitlab/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue

734 lines
22 KiB
Vue
Raw Normal View History

2021-01-29 00:20:46 +05:30
<script>
import {
GlButton,
GlForm,
GlFormGroup,
GlFormSelect,
GlFormInput,
GlFormInputGroup,
GlFormTextarea,
GlModal,
GlModalDirective,
GlToggle,
2021-04-17 20:07:23 +05:30
GlTabs,
GlTab,
2021-01-29 00:20:46 +05:30
} from '@gitlab/ui';
2021-04-17 20:07:23 +05:30
import * as Sentry from '@sentry/browser';
2021-04-29 21:17:54 +05:30
import { isEqual, isEmpty, omit } from 'lodash';
2021-01-29 00:20:46 +05:30
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
2021-12-11 22:18:48 +05:30
import { PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
2021-01-29 00:20:46 +05:30
import {
2021-03-08 18:12:59 +05:30
integrationTypes,
2021-04-17 20:07:23 +05:30
integrationSteps,
createStepNumbers,
editStepNumbers,
2021-01-29 00:20:46 +05:30
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
typeSet,
2021-04-17 20:07:23 +05:30
i18n,
2021-04-29 21:17:54 +05:30
tabIndices,
testAlertModalId,
2021-01-29 00:20:46 +05:30
} from '../constants';
2021-03-11 19:13:27 +05:30
import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
2021-04-17 20:07:23 +05:30
import parseSamplePayloadQuery from '../graphql/queries/parse_sample_payload.query.graphql';
2021-03-11 19:13:27 +05:30
import MappingBuilder from './alert_mapping_builder.vue';
import AlertSettingsFormHelpBlock from './alert_settings_form_help_block.vue';
2021-02-22 17:27:13 +05:30
2021-01-29 00:20:46 +05:30
export default {
placeholders: {
prometheus: targetPrometheusUrlPlaceholder,
},
JSON_VALIDATE_DELAY,
typeSet,
2021-04-17 20:07:23 +05:30
integrationSteps,
2021-02-22 17:27:13 +05:30
i18n,
2021-04-29 21:17:54 +05:30
primaryProps: { text: i18n.integrationFormSteps.testPayload.savedAndTest },
secondaryProps: { text: i18n.integrationFormSteps.testPayload.proceedWithoutSave },
cancelProps: { text: i18n.integrationFormSteps.testPayload.cancel },
testAlertModalId,
2021-01-29 00:20:46 +05:30
components: {
ClipboardButton,
GlButton,
GlForm,
GlFormGroup,
GlFormInput,
GlFormInputGroup,
GlFormTextarea,
GlFormSelect,
GlModal,
GlToggle,
2021-04-17 20:07:23 +05:30
GlTabs,
GlTab,
2021-01-29 00:20:46 +05:30
AlertSettingsFormHelpBlock,
MappingBuilder,
},
directives: {
GlModal: GlModalDirective,
},
inject: {
2021-04-29 21:17:54 +05:30
alertsUsageUrl: {
default: '#',
2021-01-29 00:20:46 +05:30
},
2021-03-11 19:13:27 +05:30
multiIntegrations: {
default: false,
},
2021-04-17 20:07:23 +05:30
projectPath: {
default: '',
},
2021-01-29 00:20:46 +05:30
},
props: {
loading: {
type: Boolean,
required: true,
},
canAddIntegration: {
type: Boolean,
required: true,
},
2021-03-11 19:13:27 +05:30
alertFields: {
type: Array,
required: false,
default: null,
},
2021-04-29 21:17:54 +05:30
tabIndex: {
type: Number,
required: false,
default: tabIndices.configureDetails,
},
2021-01-29 00:20:46 +05:30
},
apollo: {
currentIntegration: {
query: getCurrentIntegrationQuery,
},
},
data() {
return {
2021-04-17 20:07:23 +05:30
integrationTypesOptions: Object.values(integrationTypes),
samplePayload: {
2021-01-29 00:20:46 +05:30
json: null,
error: null,
2021-04-29 21:17:54 +05:30
loading: false,
2021-01-29 00:20:46 +05:30
},
2021-04-17 20:07:23 +05:30
testPayload: {
json: null,
error: null,
},
resetPayloadAndMappingConfirmed: false,
2021-03-11 19:13:27 +05:30
mapping: [],
2021-04-29 21:17:54 +05:30
integrationForm: {
active: false,
type: integrationTypes.none.value,
name: '',
token: '',
url: '',
apiUrl: '',
},
activeTabIndex: this.tabIndex,
2021-01-29 00:20:46 +05:30
currentIntegration: null,
2021-04-17 20:07:23 +05:30
parsedPayload: [],
2021-04-29 21:17:54 +05:30
validationState: {
name: true,
apiUrl: true,
},
2021-12-11 22:18:48 +05:30
pricingLink: `${PROMO_URL}/pricing`,
2021-01-29 00:20:46 +05:30
};
},
computed: {
isPrometheus() {
2021-04-29 21:17:54 +05:30
return this.integrationForm.type === typeSet.prometheus;
2021-01-29 00:20:46 +05:30
},
2021-04-17 20:07:23 +05:30
isHttp() {
2021-04-29 21:17:54 +05:30
return this.integrationForm.type === typeSet.http;
},
isNone() {
return !this.isHttp && !this.isPrometheus;
2021-04-17 20:07:23 +05:30
},
isCreating() {
return !this.currentIntegration;
},
isSampePayloadValid() {
return this.samplePayload.error === null;
},
isTestPayloadValid() {
return this.testPayload.error === null;
2021-01-29 00:20:46 +05:30
},
testAlertPayload() {
return {
2021-04-17 20:07:23 +05:30
data: this.testPayload.json,
2021-01-29 00:20:46 +05:30
endpoint: this.integrationForm.url,
token: this.integrationForm.token,
};
},
showMappingBuilder() {
2021-04-17 20:07:23 +05:30
return this.multiIntegrations && this.isHttp && this.alertFields?.length;
2021-01-29 00:20:46 +05:30
},
hasSamplePayload() {
2021-04-17 20:07:23 +05:30
return this.isValidNonEmptyJSON(this.currentIntegration?.payloadExample);
2021-01-29 00:20:46 +05:30
},
canEditPayload() {
2021-04-17 20:07:23 +05:30
return this.hasSamplePayload && !this.resetPayloadAndMappingConfirmed;
},
canParseSamplePayload() {
2021-04-29 21:17:54 +05:30
return this.isSampePayloadValid && this.samplePayload.json;
2021-02-22 17:27:13 +05:30
},
isSelectDisabled() {
return this.currentIntegration !== null || !this.canAddIntegration;
2021-01-29 00:20:46 +05:30
},
2021-04-17 20:07:23 +05:30
viewCredentialsHelpMsg() {
return this.isPrometheus
? i18n.integrationFormSteps.setupCredentials.prometheusHelp
: i18n.integrationFormSteps.setupCredentials.help;
},
2021-04-29 21:17:54 +05:30
isFormValid() {
return (
Object.values(this.validationState).every(Boolean) &&
!this.isNone &&
this.isSampePayloadValid
);
},
isFormDirty() {
const { type, active, name, apiUrl, payloadAlertFields = [], payloadAttributeMappings = [] } =
this.currentIntegration || {};
const {
name: formName,
apiUrl: formApiUrl,
active: formActive,
type: formType,
} = this.integrationForm;
const isDirty =
type !== formType ||
active !== formActive ||
name !== formName ||
apiUrl !== formApiUrl ||
!isEqual(this.parsedPayload, payloadAlertFields) ||
!isEqual(this.mapping, this.getCleanMapping(payloadAttributeMappings));
return isDirty;
},
canSubmitForm() {
return this.isFormValid && this.isFormDirty;
},
dataForSave() {
const { name, apiUrl, active } = this.integrationForm;
const customMappingVariables = {
payloadAttributeMappings: this.mapping,
payloadExample: this.samplePayload.json || '{}',
};
const variables = this.isHttp
? { name, active, ...customMappingVariables }
: { apiUrl, active };
return { type: this.integrationForm.type, variables };
},
testAlertModal() {
return this.isFormDirty ? testAlertModalId : null;
},
prometheusUrlInvalidFeedback() {
const { blankUrlError, invalidUrlError } = i18n.integrationFormSteps.prometheusFormUrl;
return this.integrationForm.apiUrl?.length ? invalidUrlError : blankUrlError;
},
2021-01-29 00:20:46 +05:30
},
watch: {
2021-04-29 21:17:54 +05:30
tabIndex(val) {
this.activeTabIndex = val;
},
2021-01-29 00:20:46 +05:30
currentIntegration(val) {
if (val === null) {
2021-04-17 20:07:23 +05:30
this.reset();
return;
}
2021-04-29 21:17:54 +05:30
this.resetPayloadAndMapping();
const {
name,
type,
active,
url,
apiUrl,
token,
payloadExample,
payloadAlertFields,
payloadAttributeMappings,
} = val;
this.integrationForm = { type, name, active, url, apiUrl, token };
if (this.showMappingBuilder) {
this.resetPayloadAndMappingConfirmed = false;
2021-04-17 20:07:23 +05:30
this.parsedPayload = payloadAlertFields;
2021-04-29 21:17:54 +05:30
this.samplePayload.json = this.getPrettifiedPayload(payloadExample);
this.updateMapping(this.getCleanMapping(payloadAttributeMappings));
2021-01-29 00:20:46 +05:30
}
2021-04-17 20:07:23 +05:30
this.$el.scrollIntoView({ block: 'center' });
2021-01-29 00:20:46 +05:30
},
},
methods: {
2021-04-29 21:17:54 +05:30
getCleanMapping(mapping) {
return mapping.map((mappingItem) => omit(mappingItem, '__typename'));
},
validateName() {
this.validationState.name = Boolean(this.integrationForm.name?.length);
},
validateApiUrl() {
try {
const parsedUrl = new URL(this.integrationForm.apiUrl);
this.validationState.apiUrl = ['http:', 'https:'].includes(parsedUrl.protocol);
} catch (e) {
this.validationState.apiUrl = false;
}
},
2021-04-17 20:07:23 +05:30
isValidNonEmptyJSON(JSONString) {
if (JSONString) {
let parsed;
try {
parsed = JSON.parse(JSONString);
} catch (error) {
Sentry.captureException(error);
}
if (parsed) return !isEmpty(parsed);
2021-01-29 00:20:46 +05:30
}
2021-04-17 20:07:23 +05:30
return false;
2021-01-29 00:20:46 +05:30
},
2021-04-29 21:17:54 +05:30
getPrettifiedPayload(payload) {
return this.isValidNonEmptyJSON(payload)
? JSON.stringify(JSON.parse(payload), null, '\t')
: null;
},
triggerValidation() {
if (this.isHttp) {
this.validationState.apiUrl = true;
this.validateName();
if (!this.validationState.name) {
this.$refs.integrationName.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
} else if (this.isPrometheus) {
this.validationState.name = true;
this.validateApiUrl();
}
},
2021-04-17 20:07:23 +05:30
sendTestAlert() {
this.$emit('test-alert-payload', this.testAlertPayload);
2021-01-29 00:20:46 +05:30
},
2021-04-29 21:17:54 +05:30
saveAndSendTestAlert() {
this.$emit('save-and-test-alert-payload', this.dataForSave, this.testAlertPayload);
},
submit(testAfterSubmit = false) {
this.triggerValidation();
2021-01-29 00:20:46 +05:30
2021-04-29 21:17:54 +05:30
if (!this.isFormValid) {
return;
2021-01-29 00:20:46 +05:30
}
2021-04-29 21:17:54 +05:30
const event = this.currentIntegration ? 'update-integration' : 'create-new-integration';
this.$emit(event, this.dataForSave, testAfterSubmit);
2021-01-29 00:20:46 +05:30
},
reset() {
2021-04-17 20:07:23 +05:30
this.resetFormValues();
this.resetPayloadAndMapping();
this.$emit('clear-current-integration', { type: this.currentIntegration?.type });
2021-01-29 00:20:46 +05:30
},
resetFormValues() {
2021-04-29 21:17:54 +05:30
this.integrationForm.type = integrationTypes.none.value;
2021-01-29 00:20:46 +05:30
this.integrationForm.name = '';
2021-04-29 21:17:54 +05:30
this.integrationForm.active = false;
2021-01-29 00:20:46 +05:30
this.integrationForm.apiUrl = '';
2021-04-17 20:07:23 +05:30
this.samplePayload = {
2021-01-29 00:20:46 +05:30
json: null,
error: null,
};
},
resetAuthKey() {
if (!this.currentIntegration) {
return;
}
this.$emit('reset-token', {
2021-04-29 21:17:54 +05:30
type: this.integrationForm.type,
2021-01-29 00:20:46 +05:30
variables: { id: this.currentIntegration.id },
});
},
2021-04-17 20:07:23 +05:30
validateJson(isSamplePayload = true) {
const payload = isSamplePayload ? this.samplePayload : this.testPayload;
payload.error = null;
if (payload.json === '') {
2021-01-29 00:20:46 +05:30
return;
}
try {
2021-04-17 20:07:23 +05:30
JSON.parse(payload.json);
2021-01-29 00:20:46 +05:30
} catch (e) {
2021-04-17 20:07:23 +05:30
payload.error = JSON.stringify(e.message);
2021-01-29 00:20:46 +05:30
}
},
2021-04-29 21:17:54 +05:30
parseSamplePayload() {
this.samplePayload.loading = true;
2021-01-29 00:20:46 +05:30
2021-04-17 20:07:23 +05:30
return this.$apollo
.query({
query: parseSamplePayloadQuery,
variables: { projectPath: this.projectPath, payload: this.samplePayload.json },
})
.then(
({
data: {
project: { alertManagementPayloadFields },
},
}) => {
this.parsedPayload = alertManagementPayloadFields;
this.resetPayloadAndMappingConfirmed = false;
this.$toast.show(
2021-04-29 21:17:54 +05:30
this.$options.i18n.integrationFormSteps.mapFields.payloadParsedSucessMsg,
2021-04-17 20:07:23 +05:30
);
},
)
.catch(({ message }) => {
this.samplePayload.error = message;
2021-01-29 00:20:46 +05:30
})
.finally(() => {
2021-04-29 21:17:54 +05:30
this.samplePayload.loading = false;
2021-01-29 00:20:46 +05:30
});
},
2021-03-11 19:13:27 +05:30
updateMapping(mapping) {
this.mapping = mapping;
},
2021-04-17 20:07:23 +05:30
resetPayloadAndMapping() {
this.resetPayloadAndMappingConfirmed = true;
this.parsedPayload = [];
this.updateMapping([]);
},
getLabelWithStepNumber(step, label) {
let stepNumber = editStepNumbers[step];
if (this.isCreating) {
stepNumber = createStepNumbers[step];
}
return stepNumber ? `${stepNumber}.${label}` : label;
},
2021-01-29 00:20:46 +05:30
},
};
</script>
<template>
<gl-form class="gl-mt-6" @submit.prevent="submit" @reset.prevent="reset">
2021-04-17 20:07:23 +05:30
<gl-tabs v-model="activeTabIndex">
2021-04-29 21:17:54 +05:30
<gl-tab :title="$options.i18n.integrationTabs.configureDetails" class="gl-mt-3">
2021-01-29 00:20:46 +05:30
<gl-form-group
2021-04-17 20:07:23 +05:30
v-if="isCreating"
id="integration-type"
:label="
getLabelWithStepNumber(
$options.integrationSteps.selectType,
$options.i18n.integrationFormSteps.selectType.label,
)
"
label-for="integration-type"
2021-01-29 00:20:46 +05:30
>
2021-04-17 20:07:23 +05:30
<gl-form-select
2021-04-29 21:17:54 +05:30
v-model="integrationForm.type"
2021-04-17 20:07:23 +05:30
:disabled="isSelectDisabled"
class="gl-max-w-full"
:options="integrationTypesOptions"
2021-01-29 00:20:46 +05:30
/>
2021-04-17 20:07:23 +05:30
2021-01-29 00:20:46 +05:30
<alert-settings-form-help-block
2021-04-17 20:07:23 +05:30
v-if="!canAddIntegration"
disabled="true"
class="gl-display-inline-block gl-my-4"
:message="$options.i18n.integrationFormSteps.selectType.enterprise"
2021-12-11 22:18:48 +05:30
:link="pricingLink"
2021-04-17 20:07:23 +05:30
data-testid="multi-integrations-not-supported"
2021-01-29 00:20:46 +05:30
/>
2021-04-17 20:07:23 +05:30
</gl-form-group>
<div class="gl-mt-3">
<gl-form-group
v-if="isHttp"
:label="
getLabelWithStepNumber(
$options.integrationSteps.nameIntegration,
$options.i18n.integrationFormSteps.nameIntegration.label,
)
"
label-for="name-integration"
2021-04-29 21:17:54 +05:30
:invalid-feedback="$options.i18n.integrationFormSteps.nameIntegration.error"
:state="validationState.name"
2021-04-17 20:07:23 +05:30
>
<gl-form-input
2021-04-29 21:17:54 +05:30
id="name-integration"
ref="integrationName"
2021-04-17 20:07:23 +05:30
v-model="integrationForm.name"
type="text"
:placeholder="$options.i18n.integrationFormSteps.nameIntegration.placeholder"
2021-04-29 21:17:54 +05:30
@input="validateName"
2021-04-17 20:07:23 +05:30
/>
</gl-form-group>
2021-01-29 00:20:46 +05:30
2021-04-29 21:17:54 +05:30
<gl-form-group
v-if="!isNone"
:label="
getLabelWithStepNumber(
isHttp
? $options.integrationSteps.enableHttpIntegration
: $options.integrationSteps.enablePrometheusIntegration,
$options.i18n.integrationFormSteps.enableIntegration.label,
)
"
>
<span>{{ $options.i18n.integrationFormSteps.enableIntegration.help }}</span>
<gl-toggle
id="enable-integration"
v-model="integrationForm.active"
:is-loading="loading"
:label="$options.i18n.integrationFormSteps.nameIntegration.activeToggle"
class="gl-mt-4 gl-font-weight-normal"
/>
</gl-form-group>
2021-01-29 00:20:46 +05:30
2021-04-29 21:17:54 +05:30
<gl-form-group
v-if="isPrometheus"
class="gl-my-4"
:label="$options.i18n.integrationFormSteps.prometheusFormUrl.label"
label-for="api-url"
:invalid-feedback="prometheusUrlInvalidFeedback"
:state="validationState.apiUrl"
>
2021-01-29 00:20:46 +05:30
<gl-form-input
2021-04-29 21:17:54 +05:30
id="api-url"
2021-01-29 00:20:46 +05:30
v-model="integrationForm.apiUrl"
type="text"
:placeholder="$options.placeholders.prometheus"
2021-04-29 21:17:54 +05:30
@input="validateApiUrl"
2021-01-29 00:20:46 +05:30
/>
<span class="gl-text-gray-400">
{{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
</span>
2021-04-29 21:17:54 +05:30
</gl-form-group>
2021-01-29 00:20:46 +05:30
2021-04-17 20:07:23 +05:30
<template v-if="showMappingBuilder">
<gl-form-group
data-testid="sample-payload-section"
:label="
getLabelWithStepNumber(
2021-04-29 21:17:54 +05:30
$options.integrationSteps.customizeMapping,
$options.i18n.integrationFormSteps.mapFields.label,
2021-04-17 20:07:23 +05:30
)
"
label-for="sample-payload"
class="gl-mb-0!"
:invalid-feedback="samplePayload.error"
>
2021-04-29 21:17:54 +05:30
<span>{{ $options.i18n.integrationFormSteps.mapFields.help }}</span>
2021-04-17 20:07:23 +05:30
<gl-form-textarea
id="sample-payload"
2021-04-29 21:17:54 +05:30
v-model="samplePayload.json"
:disabled="canEditPayload"
2021-04-17 20:07:23 +05:30
:state="isSampePayloadValid"
2021-04-29 21:17:54 +05:30
:placeholder="$options.i18n.integrationFormSteps.mapFields.placeholder"
2021-04-17 20:07:23 +05:30
class="gl-my-3"
:debounce="$options.JSON_VALIDATE_DELAY"
rows="6"
max-rows="10"
@input="validateJson"
/>
</gl-form-group>
<gl-button
v-if="canEditPayload"
v-gl-modal.resetPayloadModal
data-testid="payload-action-btn"
2021-04-29 21:17:54 +05:30
:disabled="!integrationForm.active"
2021-04-17 20:07:23 +05:30
class="gl-mt-3"
>
2021-04-29 21:17:54 +05:30
{{ $options.i18n.integrationFormSteps.mapFields.editPayload }}
2021-04-17 20:07:23 +05:30
</gl-button>
<gl-button
v-else
data-testid="payload-action-btn"
:class="{ 'gl-mt-3': samplePayload.error }"
2021-04-29 21:17:54 +05:30
:disabled="!canParseSamplePayload"
:loading="samplePayload.loading"
@click="parseSamplePayload"
2021-04-17 20:07:23 +05:30
>
2021-04-29 21:17:54 +05:30
{{ $options.i18n.integrationFormSteps.mapFields.parsePayload }}
2021-04-17 20:07:23 +05:30
</gl-button>
<gl-modal
modal-id="resetPayloadModal"
2021-04-29 21:17:54 +05:30
:title="$options.i18n.integrationFormSteps.mapFields.resetHeader"
:ok-title="$options.i18n.integrationFormSteps.mapFields.resetOk"
2021-04-17 20:07:23 +05:30
ok-variant="danger"
2021-04-29 21:17:54 +05:30
@ok="resetPayloadAndMappingConfirmed = true"
2021-04-17 20:07:23 +05:30
>
2021-04-29 21:17:54 +05:30
{{ $options.i18n.integrationFormSteps.mapFields.resetBody }}
2021-04-17 20:07:23 +05:30
</gl-modal>
2021-04-29 21:17:54 +05:30
<div class="gl-mt-5">
<span>{{ $options.i18n.integrationFormSteps.mapFields.mapIntro }}</span>
2021-04-17 20:07:23 +05:30
<mapping-builder
:parsed-payload="parsedPayload"
:saved-mapping="mapping"
:alert-fields="alertFields"
@onMappingUpdate="updateMapping"
/>
2021-04-29 21:17:54 +05:30
</div>
2021-04-17 20:07:23 +05:30
</template>
</div>
<div class="gl-display-flex gl-justify-content-start gl-py-3">
<gl-button
2021-04-29 21:17:54 +05:30
:disabled="!canSubmitForm"
2021-04-17 20:07:23 +05:30
variant="confirm"
class="js-no-auto-disable"
data-testid="integration-form-submit"
2021-04-29 21:17:54 +05:30
@click="submit(false)"
2021-04-17 20:07:23 +05:30
>
{{ $options.i18n.saveIntegration }}
</gl-button>
2021-04-29 21:17:54 +05:30
<gl-button
:disabled="!canSubmitForm"
variant="confirm"
category="secondary"
class="gl-ml-3 js-no-auto-disable"
data-testid="integration-form-test-and-submit"
@click="submit(true)"
>
{{ $options.i18n.saveAndTestIntegration }}
</gl-button>
2021-04-17 20:07:23 +05:30
<gl-button type="reset" class="gl-ml-3 js-no-auto-disable">{{
$options.i18n.cancelAndClose
}}</gl-button>
</div>
</gl-tab>
2021-04-29 21:17:54 +05:30
<gl-tab
:title="$options.i18n.integrationTabs.viewCredentials"
:disabled="isCreating"
class="gl-mt-3"
>
2021-04-17 20:07:23 +05:30
<alert-settings-form-help-block
:message="viewCredentialsHelpMsg"
link="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
/>
<gl-form-group id="integration-webhook">
2021-01-29 00:20:46 +05:30
<div class="gl-my-4">
<span class="gl-font-weight-bold">
2021-04-17 20:07:23 +05:30
{{ $options.i18n.integrationFormSteps.setupCredentials.webhookUrl }}
2021-01-29 00:20:46 +05:30
</span>
<gl-form-input-group id="url" readonly :value="integrationForm.url">
<template #append>
<clipboard-button
:text="integrationForm.url || ''"
2021-04-17 20:07:23 +05:30
:title="$options.i18n.copy"
2021-01-29 00:20:46 +05:30
class="gl-m-0!"
/>
</template>
</gl-form-input-group>
</div>
<div class="gl-my-4">
<span class="gl-font-weight-bold">
2021-04-17 20:07:23 +05:30
{{ $options.i18n.integrationFormSteps.setupCredentials.authorizationKey }}
2021-01-29 00:20:46 +05:30
</span>
<gl-form-input-group
id="authorization-key"
class="gl-mb-3"
readonly
:value="integrationForm.token"
>
<template #append>
<clipboard-button
:text="integrationForm.token || ''"
2021-04-17 20:07:23 +05:30
:title="$options.i18n.copy"
2021-01-29 00:20:46 +05:30
class="gl-m-0!"
/>
</template>
</gl-form-input-group>
</div>
</gl-form-group>
2021-04-29 21:17:54 +05:30
<div class="gl-display-flex gl-justify-content-start gl-py-3">
<gl-button v-gl-modal.authKeyModal variant="danger">
{{ $options.i18n.integrationFormSteps.setupCredentials.reset }}
</gl-button>
2021-04-17 20:07:23 +05:30
2021-04-29 21:17:54 +05:30
<gl-button type="reset" class="gl-ml-3 js-no-auto-disable">
{{ $options.i18n.cancelAndClose }}
</gl-button>
</div>
2021-04-17 20:07:23 +05:30
<gl-modal
modal-id="authKeyModal"
:title="$options.i18n.integrationFormSteps.setupCredentials.reset"
:ok-title="$options.i18n.integrationFormSteps.setupCredentials.reset"
ok-variant="danger"
@ok="resetAuthKey"
2021-01-29 00:20:46 +05:30
>
2021-04-17 20:07:23 +05:30
{{ $options.i18n.integrationFormSteps.restKeyInfo.label }}
</gl-modal>
</gl-tab>
2021-04-29 21:17:54 +05:30
<gl-tab
:title="$options.i18n.integrationTabs.sendTestAlert"
:disabled="isCreating"
class="gl-mt-3"
>
2021-04-17 20:07:23 +05:30
<gl-form-group id="test-integration" :invalid-feedback="testPayload.error">
2021-01-29 00:20:46 +05:30
<alert-settings-form-help-block
2021-04-29 21:17:54 +05:30
:message="$options.i18n.integrationFormSteps.testPayload.help"
:link="alertsUsageUrl"
2021-01-29 00:20:46 +05:30
/>
<gl-form-textarea
id="test-payload"
2021-04-29 21:17:54 +05:30
v-model="testPayload.json"
2021-04-17 20:07:23 +05:30
:state="isTestPayloadValid"
2021-04-29 21:17:54 +05:30
:placeholder="$options.i18n.integrationFormSteps.testPayload.placeholder"
2021-01-29 00:20:46 +05:30
class="gl-my-3"
:debounce="$options.JSON_VALIDATE_DELAY"
rows="6"
max-rows="10"
2021-04-17 20:07:23 +05:30
@input="validateJson(false)"
2021-01-29 00:20:46 +05:30
/>
</gl-form-group>
2021-04-29 21:17:54 +05:30
<div class="gl-display-flex gl-justify-content-start gl-py-3">
<gl-button
v-gl-modal="testAlertModal"
:disabled="!isTestPayloadValid"
:loading="loading"
data-testid="send-test-alert"
variant="confirm"
class="js-no-auto-disable"
@click="isFormDirty ? null : sendTestAlert()"
>
{{ $options.i18n.send }}
</gl-button>
2021-01-29 00:20:46 +05:30
2021-04-29 21:17:54 +05:30
<gl-button type="reset" class="gl-ml-3 js-no-auto-disable">
{{ $options.i18n.cancelAndClose }}
</gl-button>
</div>
2021-04-17 20:07:23 +05:30
2021-04-29 21:17:54 +05:30
<gl-modal
:modal-id="$options.testAlertModalId"
:title="$options.i18n.integrationFormSteps.testPayload.modalTitle"
:action-primary="$options.primaryProps"
:action-secondary="$options.secondaryProps"
:action-cancel="$options.cancelProps"
@primary="saveAndSendTestAlert"
@secondary="sendTestAlert"
>
{{ $options.i18n.integrationFormSteps.testPayload.modalBody }}
</gl-modal>
2021-04-17 20:07:23 +05:30
</gl-tab>
</gl-tabs>
2021-01-29 00:20:46 +05:30
</gl-form>
</template>