issuable_bulk_update_actions.js 4.84 KB
Newer Older
1
/* eslint-disable consistent-return, func-names, array-callback-return, prefer-arrow-callback, no-unused-vars */
2 3

import $ from 'jquery';
4
import _ from 'underscore';
5
import axios from './lib/utils/axios_utils';
Phil Hughes's avatar
Phil Hughes committed
6
import Flash from './flash';
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

export default {
  init({ container, form, issues, prefixId } = {}) {
    this.prefixId = prefixId || 'issue_';
    this.form = form || this.getElement('.bulk-update');
    this.$labelDropdown = this.form.find('.js-label-select');
    this.issues = issues || this.getElement('.issues-list .issue');
    this.willUpdateLabels = false;
    this.bindEvents();
  },

  bindEvents() {
    return this.form.off('submit').on('submit', this.onFormSubmit.bind(this));
  },

  onFormSubmit(e) {
    e.preventDefault();
    return this.submit();
  },

  submit() {
28 29 30
    axios[this.form.attr('method')](this.form.attr('action'), this.getFormDataAsObject())
      .then(() => window.location.reload())
      .catch(() => this.onFormSubmitFailure());
31 32 33 34
  },

  onFormSubmitFailure() {
    this.form.find('[type="submit"]').enable();
35
    return new Flash('Issue update failed');
36 37 38
  },

  getSelectedIssues() {
39
    return this.issues.has('.selected-issuable:checked');
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
  },

  getLabelsFromSelection() {
    const labels = [];
    this.getSelectedIssues().map(function() {
      const labelsData = $(this).data('labels');
      if (labelsData) {
        return labelsData.map(function(labelId) {
          if (labels.indexOf(labelId) === -1) {
            return labels.push(labelId);
          }
        });
      }
    });
    return labels;
  },

  /**
   * Will return only labels that were marked previously and the user has unmarked
   * @return {Array} Label IDs
   */

  getUnmarkedIndeterminedLabels() {
    const result = [];
    const labelsToKeep = this.$labelDropdown.data('indeterminate');

66
    this.getLabelsFromSelection().forEach(id => {
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
      if (labelsToKeep.indexOf(id) === -1) {
        result.push(id);
      }
    });

    return result;
  },

  /**
   * Simple form serialization, it will return just what we need
   * Returns key/value pairs from form data
   */

  getFormDataAsObject() {
    const formData = {
      update: {
        state_event: this.form.find('input[name="update[state_event]"]').val(),
        // For Merge Requests
        assignee_id: this.form.find('input[name="update[assignee_id]"]').val(),
        // For Issues
        assignee_ids: [this.form.find('input[name="update[assignee_ids][]"]').val()],
        milestone_id: this.form.find('input[name="update[milestone_id]"]').val(),
        issuable_ids: this.form.find('input[name="update[issuable_ids]"]').val(),
        subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
        add_label_ids: [],
92 93
        remove_label_ids: [],
      },
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    };
    if (this.willUpdateLabels) {
      formData.update.add_label_ids = this.$labelDropdown.data('marked');
      formData.update.remove_label_ids = this.$labelDropdown.data('unmarked');
    }
    return formData;
  },

  setOriginalDropdownData() {
    const $labelSelect = $('.bulk-update .js-label-select');
    $labelSelect.data('common', this.getOriginalCommonIds());
    $labelSelect.data('marked', this.getOriginalMarkedIds());
    $labelSelect.data('indeterminate', this.getOriginalIndeterminateIds());
  },

  // From issuable's initial bulk selection
  getOriginalCommonIds() {
    const labelIds = [];

113
    this.getElement('.selected-issuable:checked').each((i, el) => {
114 115 116 117 118 119 120 121
      labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels'));
    });
    return _.intersection.apply(this, labelIds);
  },

  // From issuable's initial bulk selection
  getOriginalMarkedIds() {
    const labelIds = [];
122
    this.getElement('.selected-issuable:checked').each((i, el) => {
123 124 125 126 127 128 129 130 131 132 133 134
      labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels'));
    });
    return _.intersection.apply(this, labelIds);
  },

  // From issuable's initial bulk selection
  getOriginalIndeterminateIds() {
    const uniqueIds = [];
    const labelIds = [];
    let issuableLabels = [];

    // Collect unique label IDs for all checked issues
135
    this.getElement('.selected-issuable:checked').each((i, el) => {
136
      issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels');
137
      issuableLabels.forEach(labelId => {
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
        // Store unique IDs
        if (uniqueIds.indexOf(labelId) === -1) {
          uniqueIds.push(labelId);
        }
      });
      // Store array of IDs per issuable
      labelIds.push(issuableLabels);
    });
    // Add uniqueIds to add it as argument for _.intersection
    labelIds.unshift(uniqueIds);
    // Return IDs that are present but not in all selected issueables
    return _.difference(uniqueIds, _.intersection.apply(this, labelIds));
  },

  getElement(selector) {
    this.scopeEl = this.scopeEl || $('.content');
    return this.scopeEl.find(selector);
  },
};