summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js')
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js126
1 files changed, 126 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js
new file mode 100644
index 00000000000..14824820c0d
--- /dev/null
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js
@@ -0,0 +1,126 @@
+import $ from 'jquery';
+import { difference, intersection, union } from 'lodash';
+import createFlash 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 createFlash({
+ 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);
+ },
+};