todos.js 4.65 KB
Newer Older
1
/* eslint-disable class-methods-use-this, no-unneeded-ternary */
2 3

import $ from 'jquery';
4 5 6
import { visitUrl } from '~/lib/utils/url_utility';
import UsersSelect from '~/users_select';
import { isMetaClick } from '~/lib/utils/common_utils';
7 8 9
import { __ } from '~/locale';
import flash from '~/flash';
import axios from '~/lib/utils/axios_utils';
10

11
export default class Todos {
12 13 14
  constructor() {
    this.initFilters();
    this.bindEvents();
15
    this.todo_ids = [];
16

17 18 19
    this.cleanupWrapper = this.cleanup.bind(this);
    document.addEventListener('beforeunload', this.cleanupWrapper);
  }
Fatih Acet's avatar
Fatih Acet committed
20

21 22 23 24
  cleanup() {
    this.unbindEvents();
    document.removeEventListener('beforeunload', this.cleanupWrapper);
  }
Fatih Acet's avatar
Fatih Acet committed
25

26 27
  unbindEvents() {
    $('.js-done-todo, .js-undo-todo, .js-add-todo').off('click', this.updateRowStateClickedWrapper);
28
    $('.js-todos-mark-all', '.js-todos-undo-all').off('click', this.updateallStateClickedWrapper);
29 30
    $('.todo').off('click', this.goToTodoUrl);
  }
31

32 33
  bindEvents() {
    this.updateRowStateClickedWrapper = this.updateRowStateClicked.bind(this);
34
    this.updateAllStateClickedWrapper = this.updateAllStateClicked.bind(this);
35

36
    $('.js-done-todo, .js-undo-todo, .js-add-todo').on('click', this.updateRowStateClickedWrapper);
37
    $('.js-todos-mark-all, .js-todos-undo-all').on('click', this.updateAllStateClickedWrapper);
38 39
    $('.todo').on('click', this.goToTodoUrl);
  }
Fatih Acet's avatar
Fatih Acet committed
40

41 42 43 44
  initFilters() {
    this.initFilterDropdown($('.js-project-search'), 'project_id', ['text']);
    this.initFilterDropdown($('.js-type-search'), 'type');
    this.initFilterDropdown($('.js-action-search'), 'action_id');
45

46 47
    return new UsersSelect();
  }
48

49 50 51 52 53 54 55 56 57 58
  initFilterDropdown($dropdown, fieldName, searchFields) {
    $dropdown.glDropdown({
      fieldName,
      selectable: true,
      filterable: searchFields ? true : false,
      search: { fields: searchFields },
      data: $dropdown.data('data'),
      clicked: () => $dropdown.closest('form.filter-form').submit(),
    });
  }
59

60
  updateRowStateClicked(e) {
61
    e.stopPropagation();
62 63 64
    e.preventDefault();

    const target = e.target;
65
    target.setAttribute('disabled', true);
66
    target.classList.add('disabled');
Phil Hughes's avatar
Phil Hughes committed
67 68 69

    axios[target.dataset.method](target.dataset.href)
      .then(({ data }) => {
70
        this.updateRowState(target);
Phil Hughes's avatar
Phil Hughes committed
71 72
        this.updateBadges(data);
      }).catch(() => flash(__('Error updating todo status.')));
73
  }
Fatih Acet's avatar
Fatih Acet committed
74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  updateRowState(target) {
    const row = target.closest('li');
    const restoreBtn = row.querySelector('.js-undo-todo');
    const doneBtn = row.querySelector('.js-done-todo');

    target.classList.add('hidden');
    target.removeAttribute('disabled');
    target.classList.remove('disabled');

    if (target === doneBtn) {
      row.classList.add('done-reversible');
      restoreBtn.classList.remove('hidden');
    } else if (target === restoreBtn) {
      row.classList.remove('done-reversible');
      doneBtn.classList.remove('hidden');
    } else {
      row.parentNode.removeChild(row);
Bryce Johnson's avatar
Bryce Johnson committed
92
    }
93
  }
Fatih Acet's avatar
Fatih Acet committed
94

95
  updateAllStateClicked(e) {
96
    e.stopPropagation();
97 98 99 100 101
    e.preventDefault();

    const target = e.currentTarget;
    target.setAttribute('disabled', true);
    target.classList.add('disabled');
Phil Hughes's avatar
Phil Hughes committed
102 103 104 105 106 107 108

    axios[target.dataset.method](target.dataset.href, {
      ids: this.todo_ids,
    }).then(({ data }) => {
      this.updateAllState(target, data);
      this.updateBadges(data);
    }).catch(() => flash(__('Error updating status for all todos.')));
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
  }

  updateAllState(target, data) {
    const markAllDoneBtn = document.querySelector('.js-todos-mark-all');
    const undoAllBtn = document.querySelector('.js-todos-undo-all');
    const todoListContainer = document.querySelector('.js-todos-list-container');
    const nothingHereContainer = document.querySelector('.js-nothing-here-container');

    target.removeAttribute('disabled');
    target.classList.remove('disabled');

    this.todo_ids = (target === markAllDoneBtn) ? data.updated_ids : [];
    undoAllBtn.classList.toggle('hidden');
    markAllDoneBtn.classList.toggle('hidden');
    todoListContainer.classList.toggle('hidden');
    nothingHereContainer.classList.toggle('hidden');
  }

127 128 129 130 131
  updateBadges(data) {
    $(document).trigger('todo:toggle', data.count);
    document.querySelector('.todos-pending .badge').innerHTML = data.count;
    document.querySelector('.todos-done .badge').innerHTML = data.done_count;
  }
132

133 134
  goToTodoUrl(e) {
    const todoLink = this.dataset.url;
135

Phil Hughes's avatar
Phil Hughes committed
136
    if (!todoLink || e.target.tagName === 'A' || e.target.tagName === 'IMG') {
137
      return;
Bryce Johnson's avatar
Bryce Johnson committed
138
    }
Fatih Acet's avatar
Fatih Acet committed
139

Phil Hughes's avatar
Phil Hughes committed
140 141 142
    e.stopPropagation();
    e.preventDefault();

143
    if (isMetaClick(e)) {
144
      const windowTarget = '_blank';
Phil Hughes's avatar
Phil Hughes committed
145 146

      window.open(todoLink, windowTarget);
147
    } else {
Phil Hughes's avatar
Phil Hughes committed
148
      visitUrl(todoLink);
Bryce Johnson's avatar
Bryce Johnson committed
149 150
    }
  }
151
}