labels_select.js.coffee 9.83 KB
Newer Older
1 2 3
class @LabelsSelect
  constructor: ->
    $('.js-label-select').each (i, dropdown) ->
Phil Hughes's avatar
Phil Hughes committed
4 5 6
      $dropdown = $(dropdown)
      projectId = $dropdown.data('project-id')
      labelUrl = $dropdown.data('labels')
7
      issueUpdateURL = $dropdown.data('issueUpdate')
Phil Hughes's avatar
Phil Hughes committed
8
      selectedLabel = $dropdown.data('selected')
9
      if selectedLabel? and not $dropdown.hasClass 'js-multiselect'
10
        selectedLabel = selectedLabel.split(',')
11 12
      newLabelField = $('#new_label_name')
      newColorField = $('#new_label_color')
Phil Hughes's avatar
Phil Hughes committed
13 14
      showNo = $dropdown.data('show-no')
      showAny = $dropdown.data('show-any')
15
      defaultLabel = $dropdown.data('default-label')
16
      abilityName = $dropdown.data('ability-name')
17 18
      $selectbox = $dropdown.closest('.selectbox')
      $block = $selectbox.closest('.block')
19
      $form = $dropdown.closest('form')
20
      $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span')
21 22
      $value = $block.find('.value')
      $loading = $block.find('.block-loading').fadeOut()
23 24

      if newLabelField.length
25 26
        $newLabelCreateButton = $('.js-new-label-btn')
        $colorPreview = $('.js-dropdown-label-color-preview')
27 28 29
        $newLabelError = $dropdown.parent().find('.js-label-error')
        $newLabelError.hide()

30
        # Suggested colors in the dropdown to chose from pre-chosen colors
Phil Hughes's avatar
Phil Hughes committed
31
        $('.suggest-colors-dropdown a').on 'click', (e) ->
32

33 34
      issueURLSplit = issueUpdateURL.split('/') if issueUpdateURL?
      if issueUpdateURL
35
        labelHTMLTemplate = _.template(
36
            '<% _.each(labels, function(label){ %>
37 38 39
            <a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= _.escape(label.title) %>">
            <span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>;">
            <%= _.escape(label.title) %>
40 41 42
            </span>
            </a>
            <% }); %>'
43
        )
Jacob Schatz's avatar
Jacob Schatz committed
44
        labelNoneHTMLTemplate = _.template('<div class="light">None</div>')
45 46 47

      if newLabelField.length and $dropdown.hasClass 'js-extra-options'
        $('.suggest-colors-dropdown a').on "click", (e) ->
48 49
          e.preventDefault()
          e.stopPropagation()
50 51 52 53
          newColorField
            .val($(this).data('color'))
            .trigger('change')
          $colorPreview
Phil Hughes's avatar
Phil Hughes committed
54
            .css 'background-color', $(this).data('color')
55
            .parent()
56 57
            .addClass 'is-active'

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
        # Cancel button takes back to first page
        resetForm = ->
          newLabelField
            .val ''
            .trigger 'change'
          newColorField
            .val ''
            .trigger 'change'
          $colorPreview
            .css 'background-color', ''
            .parent()
            .removeClass 'is-active'

        $('.dropdown-menu-back').on 'click', ->
          resetForm()

74 75 76
        $('.js-cancel-label-btn').on 'click', (e) ->
          e.preventDefault()
          e.stopPropagation()
77
          resetForm()
78 79
          $('.dropdown-menu-back', $dropdown.parent()).trigger 'click'

80 81 82
        # Listen for change and keyup events on label and color field
        # This allows us to enable the button when ready
        enableLabelCreateButton = ->
Phil Hughes's avatar
Phil Hughes committed
83
          if newLabelField.val() isnt '' and newColorField.val() isnt ''
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
            $newLabelError.hide()
            $('.js-new-label-btn').disable()

            # Create new label with API
            Api.newLabel projectId, {
              name: newLabelField.val()
              color: newColorField.val()
            }, (label) ->
              $('.js-new-label-btn').enable()

              if label.message?
                $newLabelError
                  .text label.message
                  .show()
              else
                $('.dropdown-menu-back', $dropdown.parent()).trigger 'click'

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
            $newLabelCreateButton.enable()
          else
            $newLabelCreateButton.disable()

        newLabelField.on 'keyup change', enableLabelCreateButton

        newColorField.on 'keyup change', enableLabelCreateButton

        # Send the API call to create the label
        $newLabelCreateButton
          .disable()
          .on 'click', (e) ->
            e.preventDefault()
            e.stopPropagation()

            if newLabelField.val() isnt '' and newColorField.val() isnt ''
              $newLabelError.hide()
              $('.js-new-label-btn').disable()

              # Create new label with API
              Api.newLabel projectId, {
                name: newLabelField.val()
                color: newColorField.val()
              }, (label) ->
                $('.js-new-label-btn').enable()

                if label.message?
                  $newLabelError
                    .text label.message
                    .show()
                else
                  $('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
133

134 135 136 137 138 139 140 141 142 143 144 145 146
      saveLabelData = ->
        selected = $dropdown
          .closest('.selectbox')
          .find("input[name='#{$dropdown.data('field-name')}']")
          .map(->
            @value
          ).get()
        data = {}
        data[abilityName] = {}
        data[abilityName].label_ids = selected
        if not selected.length
          data[abilityName].label_ids = ['']
        $loading.fadeIn()
147
        $dropdown.trigger('loading.gl.dropdown')
148 149
        $.ajax(
          type: 'PUT'
150
          url: issueUpdateURL
Alfredo Sumaran's avatar
Alfredo Sumaran committed
151
          dataType: 'JSON'
152 153 154
          data: data
        ).done (data) ->
          $loading.fadeOut()
155
          $dropdown.trigger('loaded.gl.dropdown')
156
          $selectbox.hide()
Jacob Schatz's avatar
Jacob Schatz committed
157
          data.issueURLSplit = issueURLSplit
158 159
          labelCount = 0
          if data.labels.length
160
            template = labelHTMLTemplate(data)
161 162 163 164 165 166 167 168
            labelCount = data.labels.length
          else
            template = labelNoneHTMLTemplate()
          $value
            .removeAttr('style')
            .html(template)
          $sidebarCollapsedValue.text(labelCount)

169 170
          $('.has-tooltip', $value).tooltip(container: 'body')

171 172 173 174
          $value
            .find('a')
            .each((i) ->
              setTimeout(=>
175
                gl.animate.animate($(@), 'pulse')
176 177 178 179
              ,200 * i
              )
            )

180

Phil Hughes's avatar
Phil Hughes committed
181
      $dropdown.glDropdown(
Phil Hughes's avatar
Phil Hughes committed
182
        data: (term, callback) ->
183 184 185
          $.ajax(
            url: labelUrl
          ).done (data) ->
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
            if $dropdown.hasClass 'js-extra-options'
              if showNo
                data.unshift(
                  id: 0
                  title: 'No Label'
                )

              if showAny
                data.unshift(
                  isAny: true
                  title: 'Any Label'
                )

              if data.length > 2
                data.splice 2, 0, 'divider'
201
            callback data
202

203
        renderRow: (label) ->
204
          removesAll = label.id is 0 or not label.id?
205 206

          selectedClass = []
207
          if $form.find("input[type='hidden']\
208
            [name='#{$dropdown.data('fieldName')}']\
209
            [value='#{this.id(label)}']").length
210 211 212 213
            selectedClass.push 'is-active'

          if $dropdown.hasClass('js-multiselect') and removesAll
            selectedClass.push 'dropdown-clear-active'
Phil Hughes's avatar
Phil Hughes committed
214

215 216
          color = if label.color? then "<span class='dropdown-label-box' style='background-color: #{label.color}'></span>" else ""

217
          "<li>
218
            <a href='#' class='#{selectedClass.join(' ')}'>
219
              #{color}
220
              #{_.escape(label.title)}
221 222 223 224
            </a>
          </li>"
        filterable: true
        search:
225
          fields: ['title']
226
        selectable: true
227

228 229 230
        toggleLabel: (selected, el) ->
          selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active')

231
          if selected and selected.title?
Arinde Eniola's avatar
Arinde Eniola committed
232
            if selected_labels.length > 1
233 234 235 236 237 238 239 240
              "#{selected.title} +#{selected_labels.length - 1} more"
            else
              selected.title
          else if not selected and selected_labels.length isnt 0
            if selected_labels.length > 1
              "#{$(selected_labels[0]).text()} +#{selected_labels.length - 1} more"
            else if selected_labels.length is 1
              $(selected_labels).text()
241 242
          else
            defaultLabel
Phil Hughes's avatar
Phil Hughes committed
243
        fieldName: $dropdown.data('field-name')
244
        id: (label) ->
245
          if $dropdown.hasClass("js-filter-submit") and not label.isAny?
246
            label.title
247 248 249 250
          else
            label.id

        hidden: ->
Jacob Schatz's avatar
Jacob Schatz committed
251 252
          page = $('body').data 'page'
          isIssueIndex = page is 'projects:issues:index'
Arinde Eniola's avatar
Arinde Eniola committed
253
          isMRIndex = page is 'projects:merge_requests:index'
254

255
          $selectbox.hide()
256 257
          # display:block overrides the hide-collapse rule
          $value.removeAttr('style')
258
          if $dropdown.hasClass 'js-multiselect'
Jacob Schatz's avatar
Jacob Schatz committed
259
            if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
260 261
              selectedLabels = $dropdown
                .closest('form')
Arinde Eniola's avatar
Arinde Eniola committed
262
                .find("input:hidden[name='#{$dropdown.data('fieldName')}']")
263
              Issuable.filterResults $dropdown.closest('form')
Jacob Schatz's avatar
Jacob Schatz committed
264 265 266 267
            else if $dropdown.hasClass('js-filter-submit')
              $dropdown.closest('form').submit()
            else
              saveLabelData()
268

Jacob Schatz's avatar
Jacob Schatz committed
269
        multiSelect: $dropdown.hasClass 'js-multiselect'
Phil Hughes's avatar
Phil Hughes committed
270
        clicked: (label) ->
Phil Hughes's avatar
Phil Hughes committed
271 272
          page = $('body').data 'page'
          isIssueIndex = page is 'projects:issues:index'
Arinde Eniola's avatar
Arinde Eniola committed
273
          isMRIndex = page is 'projects:merge_requests:index'
Phil Hughes's avatar
Phil Hughes committed
274
          if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
275 276
            if not $dropdown.hasClass 'js-multiselect'
              selectedLabel = label.title
277
              Issuable.filterResults $dropdown.closest('form')
Phil Hughes's avatar
Phil Hughes committed
278 279
          else if $dropdown.hasClass 'js-filter-submit'
            $dropdown.closest('form').submit()
280
          else
281 282 283 284
            if $dropdown.hasClass 'js-multiselect'
              return
            else
              saveLabelData()
285
      )