summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/todos.js
blob: caaf6484a34ba2d171bef26b3ab5fab08dfedf9a (plain)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* eslint-disable class-methods-use-this, no-unneeded-ternary, quote-props */
/* global UsersSelect */

class Todos {
  constructor() {
    this.initFilters();
    this.bindEvents();

    this.cleanupWrapper = this.cleanup.bind(this);
    document.addEventListener('beforeunload', this.cleanupWrapper);
  }

  cleanup() {
    this.unbindEvents();
    document.removeEventListener('beforeunload', this.cleanupWrapper);
  }

  unbindEvents() {
    $('.js-done-todo, .js-undo-todo, .js-add-todo').off('click', this.updateRowStateClickedWrapper);
    $('.js-todos-mark-all').off('click', this.allDoneClickedWrapper);
    $('.todo').off('click', this.goToTodoUrl);
  }

  bindEvents() {
    this.updateRowStateClickedWrapper = this.updateRowStateClicked.bind(this);
    this.allDoneClickedWrapper = this.allDoneClicked.bind(this);

    $('.js-done-todo, .js-undo-todo, .js-add-todo').on('click', this.updateRowStateClickedWrapper);
    $('.js-todos-mark-all').on('click', this.allDoneClickedWrapper);
    $('.todo').on('click', this.goToTodoUrl);
  }

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

    $('form.filter-form').on('submit', function applyFilters(event) {
      event.preventDefault();
      gl.utils.visitUrl(`${this.action}&${$(this).serialize()}`);
    });
    return new UsersSelect();
  }

  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(),
    });
  }

  updateRowStateClicked(e) {
    e.preventDefault();

    const target = e.target;
    target.setAttribute('disabled', '');
    target.classList.add('disabled');
    $.ajax({
      type: 'POST',
      url: target.getAttribute('href'),
      dataType: 'json',
      data: {
        '_method': target.getAttribute('data-method'),
      },
      success: (data) => {
        this.updateRowState(target);
        return this.updateBadges(data);
      },
    });
  }

  allDoneClicked(e) {
    e.preventDefault();
    const $target = $(e.currentTarget);
    $target.disable();
    $.ajax({
      type: 'POST',
      url: $target.attr('href'),
      dataType: 'json',
      data: {
        '_method': 'delete',
      },
      success: (data) => {
        $target.remove();
        $('.js-todos-all').html('<div class="nothing-here-block">You\'re all done!</div>');
        this.updateBadges(data);
      },
    });
  }

  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);
    }
  }

  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;
  }

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

    if (!todoLink) {
      return;
    }

    if (gl.utils.isMetaClick(e)) {
      const windowTarget = '_blank';
      const selected = e.target;
      e.preventDefault();

      if (selected.tagName === 'IMG') {
        const avatarUrl = selected.parentElement.getAttribute('href');
        window.open(avatarUrl, windowTarget);
      } else {
        window.open(todoLink, windowTarget);
      }
    } else {
      gl.utils.visitUrl(todoLink);
    }
  }
}

window.gl = window.gl || {};
gl.Todos = Todos;