diff options
Diffstat (limited to 'app/assets/javascripts/issuable/issuable_bulk_update_actions.js')
-rw-r--r-- | app/assets/javascripts/issuable/issuable_bulk_update_actions.js | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable/issuable_bulk_update_actions.js new file mode 100644 index 00000000000..c386267501a --- /dev/null +++ b/app/assets/javascripts/issuable/issuable_bulk_update_actions.js @@ -0,0 +1,126 @@ +import $ from 'jquery'; +import { difference, intersection, union } from 'lodash'; +import { createAlert } from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import { __ } from '~/locale'; + +export default { + init({ 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() { + // eslint-disable-next-line @gitlab/no-global-event-off + return this.form.off('submit').on('submit', this.onFormSubmit.bind(this)); + }, + + onFormSubmit(e) { + e.preventDefault(); + return this.submit(); + }, + + submit() { + axios[this.form.attr('method')](this.form.attr('action'), this.getFormDataAsObject()) + .then(() => window.location.reload()) + .catch(() => this.onFormSubmitFailure()); + }, + + onFormSubmitFailure() { + this.form.find('[type="submit"]').enable(); + return createAlert({ + message: __('Issue update failed'), + }); + }, + + /** + * 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(), + 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(), + health_status: this.form.find('input[name="update[health_status]"]').val(), + epic_id: this.form.find('input[name="update[epic_id]"]').val(), + sprint_id: this.form.find('input[name="update[iteration_id]"]').val(), + add_label_ids: [], + remove_label_ids: [], + }, + }; + if (this.willUpdateLabels) { + formData.update.add_label_ids = this.$labelDropdown.data('user-checked'); + formData.update.remove_label_ids = this.$labelDropdown.data('user-unchecked'); + } + return formData; + }, + + setOriginalDropdownData() { + const $labelSelect = $('.bulk-update .js-label-select'); + const userCheckedIds = $labelSelect.data('user-checked') || []; + const userUncheckedIds = $labelSelect.data('user-unchecked') || []; + + // Common labels plus user checked labels minus user unchecked labels + const checkedIdsToShow = difference( + union(this.getOriginalCommonIds(), userCheckedIds), + userUncheckedIds, + ); + + // Indeterminate labels minus user checked labels minus user unchecked labels + const indeterminateIdsToShow = difference( + this.getOriginalIndeterminateIds(), + userCheckedIds, + userUncheckedIds, + ); + + $labelSelect.data('marked', checkedIdsToShow); + $labelSelect.data('indeterminate', indeterminateIdsToShow); + }, + + // From issuable's initial bulk selection + getOriginalCommonIds() { + const labelIds = []; + this.getElement('.issuable-list input[type="checkbox"]:checked').each((i, el) => { + 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 + this.getElement('.issuable-list input[type="checkbox"]:checked').each((i, el) => { + issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels'); + issuableLabels.forEach((labelId) => { + // 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 issuables + return uniqueIds.filter((x) => !intersection.apply(this, labelIds).includes(x)); + }, + + getElement(selector) { + this.scopeEl = this.scopeEl || $('.content'); + return this.scopeEl.find(selector); + }, +}; |