All files / app/assets/javascripts task_list.js

90.9% Statements 40/44
66.66% Branches 14/21
87.5% Functions 14/16
90.9% Lines 40/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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                  81x 81x 81x 81x 81x 81x 81x 81x 81x                           81x       81x   81x       81x   4x     81x       439x               87x               175x           88x 88x       87x 87x 87x       82x 82x       81x 81x       8x 8x 8x   8x 8x                     8x 8x   8x     6x 6x   6x     2x   2x        
import $ from 'jquery';
import 'deckar01-task_list';
import { __ } from '~/locale';
import { createAlert } from '~/alert';
import { TYPE_INCIDENT, TYPE_ISSUE } from '~/issues/constants';
import axios from './lib/utils/axios_utils';
 
export default class TaskList {
  constructor(options = {}) {
    this.selector = options.selector;
    this.dataType = options.dataType;
    this.fieldName = options.fieldName;
    this.lockVersion = options.lockVersion;
    this.taskListContainerSelector = `${this.selector} .js-task-list-container`;
    this.updateHandler = this.update.bind(this);
    this.onUpdate = options.onUpdate || (() => {});
    this.onSuccess = options.onSuccess || (() => {});
    this.onError =
      options.onError ||
      function showFlash(e) {
        let errorMessages = '';
 
        if (e.response.data && typeof e.response.data === 'object') {
          errorMessages = e.response.data.errors.join(' ');
        }
 
        return createAlert({
          message: errorMessages || __('Update failed'),
        });
      };
 
    this.init();
  }
 
  init() {
    this.disable(); // Prevent duplicate event bindings
 
    const taskListFields = document.querySelectorAll(
      `${this.taskListContainerSelector} .js-task-list-field[data-value]`,
    );
 
    taskListFields.forEach((taskListField) => {
      // eslint-disable-next-line no-param-reassign
      taskListField.value = taskListField.dataset.value;
    });
 
    this.enable();
  }
 
  getTaskListTarget(e) {
    return e && e.currentTarget ? $(e.currentTarget) : $(this.taskListContainerSelector);
  }
 
  // Disable any task items that don't have a data-sourcepos attribute, on the
  // assumption that if it doesn't then it wasn't generated from our markdown parser.
  // This covers the case of markdown not being able to handle task lists inside
  // markdown tables. It also includes hand coded HTML lists.
  disableNonMarkdownTaskListItems(e) {
    this.getTaskListTarget(e)
      .find('.task-list-item')
      .not('[data-sourcepos]')
      .find('.task-list-item-checkbox')
      .prop('disabled', true);
  }
 
  updateInapplicableTaskListItems(e) {
    this.getTaskListTarget(e)
      .find('.task-list-item-checkbox[data-inapplicable]')
      .prop('disabled', true);
  }
 
  disableTaskListItems(e) {
    this.getTaskListTarget(e).taskList('disable');
    this.updateInapplicableTaskListItems();
  }
 
  enableTaskListItems(e) {
    this.getTaskListTarget(e).taskList('enable');
    this.disableNonMarkdownTaskListItems(e);
    this.updateInapplicableTaskListItems(e);
  }
 
  enable() {
    this.enableTaskListItems();
    $(document).on('tasklist:changed', this.taskListContainerSelector, this.updateHandler);
  }
 
  disable() {
    this.disableTaskListItems();
    $(document).off('tasklist:changed', this.taskListContainerSelector);
  }
 
  update(e) {
    const $target = $(e.target);
    const { index, checked, lineNumber, lineSource } = e.detail;
    const patchData = {};
 
    const dataType = this.dataType === TYPE_INCIDENT ? TYPE_ISSUE : this.dataType;
    patchData[dataType] = {
      [this.fieldName]: $target.val(),
      lock_version: this.lockVersion,
      update_task: {
        index,
        checked,
        line_number: lineNumber,
        line_source: lineSource,
      },
    };
 
    this.onUpdate();
    this.disableTaskListItems(e);
 
    return axios
      .patch($target.data('updateUrl') || $('form.js-issuable-update').attr('action'), patchData)
      .then(({ data }) => {
        this.lockVersion = data.lock_version;
        this.enableTaskListItems(e);
 
        return this.onSuccess(data);
      })
      .catch(({ response }) => {
        this.enableTaskListItems(e);
 
        return this.onError(response.data);
      });
  }
}