Commit 1ece0011 authored by David O'Regan's avatar David O'Regan

Merge branch '280851-prettify-mapping-builder' into 'master'

Prettify mapping builder form

See merge request gitlab-org/gitlab!47512
parents 27b3aaa9 c6819c43
...@@ -124,14 +124,14 @@ export default { ...@@ -124,14 +124,14 @@ export default {
<template> <template>
<div class="gl-display-table gl-w-full gl-mt-5"> <div class="gl-display-table gl-w-full gl-mt-5">
<div class="gl-display-table-row"> <div class="gl-display-table-row">
<h5 class="gl-display-table-cell gl-py-3 gl-pr-3"> <h5 id="gitlabFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
{{ $options.i18n.columns.gitlabKeyTitle }} {{ $options.i18n.columns.gitlabKeyTitle }}
</h5> </h5>
<h5 class="gl-display-table-cell gl-py-3 gl-pr-3">&nbsp;</h5> <h5 class="gl-display-table-cell gl-py-3 gl-pr-3">&nbsp;</h5>
<h5 class="gl-display-table-cell gl-py-3 gl-pr-3"> <h5 id="parsedFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
{{ $options.i18n.columns.payloadKeyTitle }} {{ $options.i18n.columns.payloadKeyTitle }}
</h5> </h5>
<h5 class="gl-display-table-cell gl-py-3 gl-pr-3"> <h5 id="fallbackFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
{{ $options.i18n.columns.fallbackKeyTitle }} {{ $options.i18n.columns.fallbackKeyTitle }}
<gl-icon <gl-icon
v-gl-tooltip v-gl-tooltip
...@@ -144,22 +144,24 @@ export default { ...@@ -144,22 +144,24 @@ export default {
<div v-for="gitlabField in mappingData" :key="gitlabField.name" class="gl-display-table-row"> <div v-for="gitlabField in mappingData" :key="gitlabField.name" class="gl-display-table-row">
<div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p"> <div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p">
<gl-form-input <gl-form-input
aria-labelledby="gitlabFieldsHeader"
disabled disabled
:value="getFieldValue(gitlabField)" :value="getFieldValue(gitlabField)"
class="gl-bg-transparent! gl-text-gray-900!"
/> />
</div> </div>
<div class="gl-display-table-cell gl-py-3 gl-pr-3"> <div class="gl-display-table-cell gl-py-3 gl-pr-3">
<div class="right-arrow"> <div class="right-arrow gl-vertical-align-middle gl-mt-n1">
<i class="right-arrow-head"></i> <i class="right-arrow-head"></i>
</div> </div>
</div> </div>
<div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p"> <div class="gl-display-table-cell gl-py-3 gl-pr-3 w-30p">
<gl-dropdown <gl-dropdown
:disabled="!gitlabField.mappingFields.length"
aria-labelledby="parsedFieldsHeader"
:text="selectedValue(gitlabField.mapping)" :text="selectedValue(gitlabField.mapping)"
class="gl-w-full" class="gl-w-full gl-vertical-align-baseline!"
:header-text="$options.i18n.selectMappingKey" :header-text="$options.i18n.selectMappingKey"
> >
<gl-search-box-by-type @input="setSearchTerm($event, 'searchTerm', gitlabField.name)" /> <gl-search-box-by-type @input="setSearchTerm($event, 'searchTerm', gitlabField.name)" />
...@@ -181,8 +183,10 @@ export default { ...@@ -181,8 +183,10 @@ export default {
<div class="gl-display-table-cell gl-py-3 w-30p"> <div class="gl-display-table-cell gl-py-3 w-30p">
<gl-dropdown <gl-dropdown
v-if="Boolean(gitlabField.numberOfFallbacks)" v-if="Boolean(gitlabField.numberOfFallbacks)"
:disabled="!gitlabField.mappingFields.length"
aria-labelledby="fallbackFieldsHeader"
:text="selectedValue(gitlabField.fallback)" :text="selectedValue(gitlabField.fallback)"
class="gl-w-full" class="gl-w-full gl-vertical-align-baseline!"
:header-text="$options.i18n.selectMappingKey" :header-text="$options.i18n.selectMappingKey"
> >
<gl-search-box-by-type <gl-search-box-by-type
......
...@@ -73,11 +73,14 @@ export default { ...@@ -73,11 +73,14 @@ export default {
resetOk: s__('AlertSettings|Proceed with editing'), resetOk: s__('AlertSettings|Proceed with editing'),
editPayload: s__('AlertSettings|Edit payload'), editPayload: s__('AlertSettings|Edit payload'),
submitPayload: s__('AlertSettings|Submit payload'), submitPayload: s__('AlertSettings|Submit payload'),
payloadParsedSucessMsg: s__(
'AlertSettings|Sample payload has been parsed. You can now map the fields.',
),
}, },
step5: { step5: {
label: s__('AlertSettings|5. Map fields (optional)'), label: s__('AlertSettings|5. Map fields (optional)'),
intro: s__( 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.', "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key.",
), ),
}, },
prometheusFormUrl: { prometheusFormUrl: {
...@@ -211,10 +214,10 @@ export default { ...@@ -211,10 +214,10 @@ export default {
); );
}, },
mappingBuilderFields() { mappingBuilderFields() {
return this.customMapping?.samplePayload?.payloadAlerFields?.nodes || []; return this.customMapping?.samplePayload?.payloadAlerFields?.nodes;
}, },
mappingBuilderMapping() { mappingBuilderMapping() {
return this.customMapping?.storedMapping?.nodes || []; return this.customMapping?.storedMapping?.nodes;
}, },
hasSamplePayload() { hasSamplePayload() {
return Boolean(this.customMapping?.samplePayload); return Boolean(this.customMapping?.samplePayload);
...@@ -352,6 +355,8 @@ export default { ...@@ -352,6 +355,8 @@ export default {
this.customMapping = res; this.customMapping = res;
this.integrationTestPayload.json = res?.samplePayload.body; this.integrationTestPayload.json = res?.samplePayload.body;
this.resetSamplePayloadConfirmed = false; this.resetSamplePayloadConfirmed = false;
this.$toast.show(this.$options.i18n.integrationFormSteps.step4.payloadParsedSucessMsg);
}) })
.finally(() => { .finally(() => {
this.parsingPayload = false; this.parsingPayload = false;
...@@ -528,6 +533,7 @@ export default { ...@@ -528,6 +533,7 @@ export default {
id="test-integration" id="test-integration"
:label="$options.i18n.integrationFormSteps.step4.label" :label="$options.i18n.integrationFormSteps.step4.label"
label-for="test-integration" label-for="test-integration"
:class="{ 'gl-mb-0!': showMappingBuilder }"
:invalid-feedback="integrationTestPayload.error" :invalid-feedback="integrationTestPayload.error"
> >
<alert-settings-form-help-block <alert-settings-form-help-block
...@@ -547,11 +553,13 @@ export default { ...@@ -547,11 +553,13 @@ export default {
max-rows="10" max-rows="10"
@input="validateJson" @input="validateJson"
/> />
</gl-form-group>
<template v-if="showMappingBuilder"> <template v-if="showMappingBuilder">
<gl-button <gl-button
v-if="canEditPayload" v-if="canEditPayload"
v-gl-modal.resetPayloadModal v-gl-modal.resetPayloadModal
data-testid="payload-action-btn"
:disabled="!active" :disabled="!active"
class="gl-mt-3" class="gl-mt-3"
> >
...@@ -560,9 +568,10 @@ export default { ...@@ -560,9 +568,10 @@ export default {
<gl-button <gl-button
v-else v-else
data-testid="payload-action-btn"
:class="{ 'gl-mt-3': integrationTestPayload.error }"
:disabled="!active" :disabled="!active"
:loading="parsingPayload" :loading="parsingPayload"
class="gl-mt-3"
@click="parseMapping" @click="parseMapping"
> >
{{ $options.i18n.integrationFormSteps.step4.submitPayload }} {{ $options.i18n.integrationFormSteps.step4.submitPayload }}
...@@ -577,11 +586,11 @@ export default { ...@@ -577,11 +586,11 @@ export default {
{{ $options.i18n.integrationFormSteps.step4.resetBody }} {{ $options.i18n.integrationFormSteps.step4.resetBody }}
</gl-modal> </gl-modal>
</template> </template>
</gl-form-group>
<gl-form-group <gl-form-group
v-if="showMappingBuilder" v-if="showMappingBuilder"
id="mapping-builder" id="mapping-builder"
class="gl-mt-5"
:label="$options.i18n.integrationFormSteps.step5.label" :label="$options.i18n.integrationFormSteps.step5.label"
label-for="mapping-builder" label-for="mapping-builder"
> >
......
import Vue from 'vue'; import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue'; import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
...@@ -8,6 +9,7 @@ apolloProvider.clients.defaultClient.cache.writeData({ ...@@ -8,6 +9,7 @@ apolloProvider.clients.defaultClient.cache.writeData({
currentIntegration: null, currentIntegration: null,
}, },
}); });
Vue.use(GlToast);
export default el => { export default el => {
if (!el) { if (!el) {
......
...@@ -2574,6 +2574,9 @@ msgstr "" ...@@ -2574,6 +2574,9 @@ msgstr ""
msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields." msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
msgstr "" msgstr ""
msgid "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key."
msgstr ""
msgid "AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations." msgid "AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations."
msgstr "" msgstr ""
...@@ -2613,6 +2616,9 @@ msgstr "" ...@@ -2613,6 +2616,9 @@ msgstr ""
msgid "AlertSettings|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." msgid "AlertSettings|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 "" msgstr ""
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
msgid "AlertSettings|Save and test payload" msgid "AlertSettings|Save and test payload"
msgstr "" msgstr ""
...@@ -2634,9 +2640,6 @@ msgstr "" ...@@ -2634,9 +2640,6 @@ msgstr ""
msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?" msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?"
msgstr "" msgstr ""
msgid "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."
msgstr ""
msgid "AlertSettings|There was an error updating the alert settings." msgid "AlertSettings|There was an error updating the alert settings."
msgstr "" msgstr ""
......
...@@ -80,10 +80,10 @@ exports[`AlertsSettingsFormNew with default values renders the initial template ...@@ -80,10 +80,10 @@ exports[`AlertsSettingsFormNew with default values renders the initial template
<!----> <!---->
<!----> <!---->
<!----> <!---->
<!---->
</div> </div>
</div> </div>
<!----> <!---->
<!---->
</div> </div>
<div class=\\"gl-display-flex gl-justify-content-end\\"><button type=\\"reset\\" class=\\"btn gl-mr-3 js-no-auto-disable btn-default btn-md gl-button\\"> <div class=\\"gl-display-flex gl-justify-content-end\\"><button type=\\"reset\\" class=\\"btn gl-mr-3 js-no-auto-disable btn-default btn-md gl-button\\">
<!----> <!---->
......
...@@ -6,14 +6,15 @@ import { ...@@ -6,14 +6,15 @@ import {
GlFormInput, GlFormInput,
GlToggle, GlToggle,
GlFormTextarea, GlFormTextarea,
GlButton,
} from '@gitlab/ui'; } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue'; import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
import { defaultAlertSettingsConfig } from './util'; import { defaultAlertSettingsConfig } from './util';
import { typeSet } from '~/alerts_settings/constants'; import { typeSet } from '~/alerts_settings/constants';
describe('AlertsSettingsFormNew', () => { describe('AlertsSettingsFormNew', () => {
let wrapper; let wrapper;
const mockToastShow = jest.fn();
const createComponent = ({ const createComponent = ({
data = {}, data = {},
...@@ -34,6 +35,11 @@ describe('AlertsSettingsFormNew', () => { ...@@ -34,6 +35,11 @@ describe('AlertsSettingsFormNew', () => {
glFeatures: { multipleHttpIntegrationsCustomMapping }, glFeatures: { multipleHttpIntegrationsCustomMapping },
...defaultAlertSettingsConfig, ...defaultAlertSettingsConfig,
}, },
mocks: {
$toast: {
show: mockToastShow,
},
},
}); });
}; };
...@@ -49,6 +55,7 @@ describe('AlertsSettingsFormNew', () => { ...@@ -49,6 +55,7 @@ describe('AlertsSettingsFormNew', () => {
wrapper.find(`[data-testid="multi-integrations-not-supported"]`); wrapper.find(`[data-testid="multi-integrations-not-supported"]`);
const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`); const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`);
const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`); const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`);
const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`);
afterEach(() => { afterEach(() => {
if (wrapper) { if (wrapper) {
...@@ -307,14 +314,30 @@ describe('AlertsSettingsFormNew', () => { ...@@ -307,14 +314,30 @@ describe('AlertsSettingsFormNew', () => {
resetSamplePayloadConfirmed, resetSamplePayloadConfirmed,
}); });
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect( expect(findActionBtn().text()).toBe(caption);
findTestPayloadSection()
.find(GlButton)
.text(),
).toBe(caption);
}); });
}); });
}); });
describe('Parsing payload', () => {
it('displays a toast message on successful parse', async () => {
jest.useFakeTimers();
wrapper.setData({
selectedIntegration: typeSet.http,
customMapping: { samplePayload: false },
});
await wrapper.vm.$nextTick();
findActionBtn().vm.$emit('click');
jest.advanceTimersByTime(1000);
await waitForPromises();
expect(mockToastShow).toHaveBeenCalledWith(
'Sample payload has been parsed. You can now map the fields.',
);
});
});
}); });
describe('Mapping builder section', () => { describe('Mapping builder section', () => {
......
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