summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/integrations/integration_settings_form.js
blob: 1c9b94ade8ac902183db67f08aecfcb2579ac9a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import $ from 'jquery';
import axios from '../lib/utils/axios_utils';
import flash from '../flash';
import { __ } from '~/locale';

export default class IntegrationSettingsForm {
  constructor(formSelector) {
    this.$form = $(formSelector);

    // Form Metadata
    this.canTestService = this.$form.data('canTest');
    this.testEndPoint = this.$form.data('testUrl');

    // Form Child Elements
    this.$serviceToggle = this.$form.find('#service_active');
    this.$submitBtn = this.$form.find('button[type="submit"]');
    this.$submitBtnLoader = this.$submitBtn.find('.js-btn-spinner');
    this.$submitBtnLabel = this.$submitBtn.find('.js-btn-label');
  }

  init() {
    // Initialize View
    this.toggleServiceState(this.$serviceToggle.is(':checked'));

    // Bind Event Listeners
    this.$serviceToggle.on('change', e => this.handleServiceToggle(e));
    this.$submitBtn.on('click', e => this.handleSettingsSave(e));
  }

  handleSettingsSave(e) {
    // Check if Service is marked active, as if not marked active,
    // We can skip testing it and directly go ahead to allow form to
    // be submitted
    if (!this.$serviceToggle.is(':checked')) {
      return;
    }

    // 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.get(0).checkValidity() && this.canTestService) {
      e.preventDefault();
      // eslint-disable-next-line no-jquery/no-serialize
      this.testSettings(this.$form.serialize());
    }
  }

  handleServiceToggle(e) {
    this.toggleServiceState($(e.currentTarget).is(':checked'));
  }

  /**
   * Change Form's validation enforcement based on service status (active/inactive)
   */
  toggleServiceState(serviceActive) {
    this.toggleSubmitBtnLabel(serviceActive);
    if (serviceActive) {
      this.$form.removeAttr('novalidate');
    } else if (!this.$form.attr('novalidate')) {
      this.$form.attr('novalidate', 'novalidate');
    }
  }

  /**
   * Toggle Submit button label based on Integration status and ability to test service
   */
  toggleSubmitBtnLabel(serviceActive) {
    let btnLabel = __('Save changes');

    if (serviceActive && this.canTestService) {
      btnLabel = __('Test settings and save changes');
    }

    this.$submitBtnLabel.text(btnLabel);
  }

  /**
   * Toggle Submit button state based on provided boolean value of `saveTestActive`
   * When enabled, it does two things, and reverts back when disabled
   *
   * 1. It shows load spinner on submit button
   * 2. Makes submit button disabled
   */
  toggleSubmitBtnState(saveTestActive) {
    if (saveTestActive) {
      this.$submitBtn.disable();
      this.$submitBtnLoader.removeClass('hidden');
    } else {
      this.$submitBtn.enable();
      this.$submitBtnLoader.addClass('hidden');
    }
  }

  /**
   * Test Integration config
   */
  testSettings(formData) {
    this.toggleSubmitBtnState(true);

    return axios
      .put(this.testEndPoint, formData)
      .then(({ data }) => {
        if (data.error) {
          let flashActions;

          if (data.test_failed) {
            flashActions = {
              title: __('Save anyway'),
              clickHandler: e => {
                e.preventDefault();
                this.$form.submit();
              },
            };
          }

          flash(`${data.message} ${data.service_response}`, 'alert', document, flashActions);
        } else {
          this.$form.submit();
        }

        this.toggleSubmitBtnState(false);
      })
      .catch(() => {
        flash(__('Something went wrong on our end.'));
        this.toggleSubmitBtnState(false);
      });
  }
}