merge_request.js.coffee 5.19 KB
Newer Older
1
#= require jquery.waitforimages
2 3
#= require task_list

4
class @MergeRequest
5 6 7 8 9 10 11 12 13
  # Initialize MergeRequest behavior
  #
  # Options:
  #   action         - String, current controller action
  #   diffs_loaded   - Boolean, have diffs been pre-rendered server-side?
  #                    (default: true if `action` is 'diffs', otherwise false)
  #   commits_loaded - Boolean, have commits been pre-rendered server-side?
  #                    (default: false)
  #
14 15 16 17
  constructor: (@opts) ->
    @initContextWidget()
    this.$el = $('.merge-request')

18 19
    @diffs_loaded = @opts.diffs_loaded or @opts.action == 'diffs'
    @commits_loaded = @opts.commits_loaded or false
20 21

    this.bindEvents()
22
    this.activateTabFromPath()
23 24 25 26

    this.$('.show-all-commits').on 'click', =>
      this.showAllCommits()

27 28 29
    # Prevent duplicate event bindings
    @disableTaskList()

30
    if $("a.btn-close").length
31
      @initTaskList()
32

33 34 35
    $('.merge-request-details').waitForImages ->
      $('.issuable-affix').affix offset:
        top: ->
36
          @top = ($('.issuable-affix').offset().top - 70)
37 38
        bottom: ->
          @bottom = $('.footer').outerHeight(true)
39 40 41 42
      $('.issuable-affix').on 'affix.bs.affix', ->
        $(@).width($(@).outerWidth())
      .on 'affixed-top.bs.affix affixed-bottom.bs.affix', ->
        $(@).width('')
43

44 45 46 47 48 49
  # Local jQuery finder
  $: (selector) ->
    this.$el.find(selector)

  initContextWidget: ->
    $('.edit-merge_request.inline-update input[type="submit"]').hide()
50
    $(".context .inline-update").on "change", "select", ->
51
      $(this).submit()
52
    $(".context .inline-update").on "change", "#merge_request_assignee_id", ->
53 54 55 56
      $(this).submit()


  bindEvents: ->
57 58
    this.$('.merge-request-tabs a[data-toggle="tab"]').on 'shown.bs.tab', (e) =>
      $target = $(e.target)
59
      tab_action = $target.data('action')
60 61

      # Lazy-load diffs
62
      if tab_action == 'diffs'
63
        this.loadDiff() unless @diffs_loaded
64 65 66 67 68
        $('.diff-header').trigger('sticky_kit:recalc')

      # Skip tab-persisting behavior on MergeRequests#new
      unless @opts.action == 'new'
        @setCurrentAction(tab_action)
69

70
  # Activate a tab based on the current URL path
71
  #
72 73 74 75 76 77 78 79 80 81
  # If the current action is 'show' or 'new' (i.e., initial page load),
  # activates the first tab, otherwise activates the tab corresponding to the
  # current action (diffs, commits).
  activateTabFromPath: ->
    if @opts.action == 'show' || @opts.action == 'new'
      this.$('.merge-request-tabs a[data-toggle="tab"]:first').tab('show')
    else
      this.$(".merge-request-tabs a[data-action='#{@opts.action}']").tab('show')

  # Replaces the current Merge Request-specific action in the URL with a new one
82
  #
83 84
  # If the action is "notes", the URL is reset to the standard
  # `MergeRequests#show` route.
85
  #
86
  # Examples:
87
  #
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
  #   location.pathname # => "/namespace/project/merge_requests/1"
  #   setCurrentAction('diffs')
  #   location.pathname # => "/namespace/project/merge_requests/1/diffs"
  #
  #   location.pathname # => "/namespace/project/merge_requests/1/diffs"
  #   setCurrentAction('notes')
  #   location.pathname # => "/namespace/project/merge_requests/1"
  #
  #   location.pathname # => "/namespace/project/merge_requests/1/diffs"
  #   setCurrentAction('commits')
  #   location.pathname # => "/namespace/project/merge_requests/1/commits"
  setCurrentAction: (action) ->
    # Normalize action, just to be safe
    action = 'notes' if action == 'show'

    # Remove a trailing '/commits' or '/diffs'
    new_state = location.pathname.replace(/\/(commits|diffs)\/?$/, '')

    # Append the new action if we're on a tab other than 'notes'
    unless action == 'notes'
      new_state += "/#{action}"

110 111 112
    # Ensure parameters and hash come along for the ride
    new_state += location.search + location.hash

113 114 115 116 117
    # Replace the current history state with the new one without breaking
    # Turbolinks' history.
    #
    # See https://github.com/rails/turbolinks/issues/363
    history.replaceState {turbolinks: true, url: new_state}, '', new_state
118 119 120 121

  loadDiff: (event) ->
    $.ajax
      type: 'GET'
122
      url: this.$('.merge-request-tabs .diffs-tab a').attr('href') + ".json"
123
      beforeSend: =>
124
        this.$('.mr-loading-status .loading').show()
125 126
      complete: =>
        @diffs_loaded = true
127
        this.$('.mr-loading-status .loading').hide()
128 129 130 131 132 133 134 135
      success: (data) =>
        this.$(".diffs").html(data.html)
      dataType: 'json'

  showAllCommits: ->
    this.$('.first-commits').remove()
    this.$('.all-commits').removeClass 'hide'

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  initTaskList: ->
    $('.merge-request-details .js-task-list-container').taskList('enable')
    $(document).on 'tasklist:changed', '.merge-request-details .js-task-list-container', @updateTaskList

  disableTaskList: ->
    $('.merge-request-details .js-task-list-container').taskList('disable')
    $(document).off 'tasklist:changed', '.merge-request-details .js-task-list-container'

  # TODO (rspeicher): Make the merge request description inline-editable like a
  # note so that we can re-use its form here
  updateTaskList: ->
    patchData = {}
    patchData['merge_request'] = {'description': $('.js-task-list-field', this).val()}

    $.ajax
      type: 'PATCH'
      url: $('form.js-merge-request-update').attr('action')
      data: patchData