import { delay } from 'lodash'; import toast from '~/vue_shared/plugins/global_toast'; import axios from '../lib/utils/axios_utils'; import initForm from './edit'; import eventHub from './edit/event_hub'; import { TEST_INTEGRATION_EVENT, SAVE_INTEGRATION_EVENT, GET_JIRA_ISSUE_TYPES_EVENT, TOGGLE_INTEGRATION_EVENT, VALIDATE_INTEGRATION_FORM_EVENT, I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE, I18N_DEFAULT_ERROR_MESSAGE, I18N_SUCCESSFUL_CONNECTION_MESSAGE, } from './constants'; export default class IntegrationSettingsForm { constructor(formSelector) { this.$form = document.querySelector(formSelector); this.formActive = false; this.vue = null; // Form Metadata this.testEndPoint = this.$form.dataset.testUrl; } init() { // Init Vue component this.vue = initForm( document.querySelector('.js-vue-integration-settings'), document.querySelector('.js-vue-default-integration-settings'), ); eventHub.$on(TOGGLE_INTEGRATION_EVENT, (active) => { this.formActive = active; this.toggleServiceState(); }); eventHub.$on(TEST_INTEGRATION_EVENT, () => { this.testIntegration(); }); eventHub.$on(SAVE_INTEGRATION_EVENT, () => { this.saveIntegration(); }); eventHub.$on(GET_JIRA_ISSUE_TYPES_EVENT, () => { this.getJiraIssueTypes(new FormData(this.$form)); }); } saveIntegration() { // Save Service if not active and check the following if active; // 1) If form contents are valid // 2) If this service can be saved // If both conditions are true, we override form submission // and save the service using provided configuration. const formValid = this.$form.checkValidity() || this.formActive === false; if (formValid) { delay(() => { this.$form.submit(); }, 100); } else { eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT); this.vue.$store.dispatch('setIsSaving', false); } } testIntegration() { // Service was marked active so now we check; // 1) If form contents are valid // 2) If this service can be tested // If both conditions are true, we override form submission // and test the service using provided configuration. if (this.$form.checkValidity()) { this.testSettings(new FormData(this.$form)); } else { eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT); this.vue.$store.dispatch('setIsTesting', false); } } /** * Change Form's validation enforcement based on service status (active/inactive) */ toggleServiceState() { if (this.formActive) { this.$form.removeAttribute('novalidate'); } else if (!this.$form.getAttribute('novalidate')) { this.$form.setAttribute('novalidate', 'novalidate'); } } /** * Get a list of Jira issue types for the currently configured project * * @param {string} formData - URL encoded string containing the form data * * @return {Promise} */ getJiraIssueTypes(formData) { const { $store: { dispatch }, } = this.vue; dispatch('requestJiraIssueTypes'); return this.fetchTestSettings(formData) .then( ({ data: { issuetypes, error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE }, }) => { if (error || !issuetypes?.length) { eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT); throw new Error(message); } dispatch('receiveJiraIssueTypesSuccess', issuetypes); }, ) .catch(({ message = I18N_DEFAULT_ERROR_MESSAGE }) => { dispatch('receiveJiraIssueTypesError', message); }); } /** * Send request to the test endpoint which checks if the current config is valid */ fetchTestSettings(formData) { return axios.put(this.testEndPoint, formData); } /** * Test Integration config */ testSettings(formData) { return this.fetchTestSettings(formData) .then(({ data }) => { if (data.error) { toast(`${data.message} ${data.service_response}`); } else { this.vue.$store.dispatch('receiveJiraIssueTypesSuccess', data.issuetypes); toast(I18N_SUCCESSFUL_CONNECTION_MESSAGE); } }) .catch(() => { toast(I18N_DEFAULT_ERROR_MESSAGE); }) .finally(() => { this.vue.$store.dispatch('setIsTesting', false); }); } }