summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/merge_request_tabs.js.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/merge_request_tabs.js.coffee')
-rw-r--r--app/assets/javascripts/merge_request_tabs.js.coffee153
1 files changed, 153 insertions, 0 deletions
diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee
new file mode 100644
index 00000000000..de9a4c2cc2f
--- /dev/null
+++ b/app/assets/javascripts/merge_request_tabs.js.coffee
@@ -0,0 +1,153 @@
+# MergeRequestTabs
+#
+# Handles persisting and restoring the current tab selection and lazily-loading
+# content on the MergeRequests#show page.
+#
+# ### Example Markup
+#
+# <ul class="nav nav-tabs merge-request-tabs">
+# <li class="notes-tab active">
+# <a data-action="notes" data-target="#notes" data-toggle="tab" href="/foo/bar/merge_requests/1">
+# Discussion
+# </a>
+# </li>
+# <li class="commits-tab">
+# <a data-action="commits" data-target="#commits" data-toggle="tab" href="/foo/bar/merge_requests/1/commits">
+# Commits
+# </a>
+# </li>
+# <li class="diffs-tab">
+# <a data-action="diffs" data-target="#diffs" data-toggle="tab" href="/foo/bar/merge_requests/1/diffs">
+# Diffs
+# </a>
+# </li>
+# </ul>
+#
+# <div class="tab-content">
+# <div class="notes tab-pane active" id="notes">
+# Notes Content
+# </div>
+# <div class="commits tab-pane" id="commits">
+# Commits Content
+# </div>
+# <div class="diffs tab-pane" id="diffs">
+# Diffs Content
+# </div>
+# </div>
+#
+# <div class="mr-loading-status">
+# <div class="loading">
+# Loading Animation
+# </div>
+# </div>
+#
+class @MergeRequestTabs
+ diffsLoaded: false
+ commitsLoaded: false
+
+ constructor: (@opts = {}) ->
+ # Store the `location` object, allowing for easier stubbing in tests
+ @_location = location
+
+ @bindEvents()
+ @activateTab(@opts.action)
+
+ switch @opts.action
+ when 'commits' then @commitsLoaded = true
+ when 'diffs' then @diffsLoaded = true
+
+ bindEvents: ->
+ $(document).on 'shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', @tabShown
+
+ tabShown: (event) =>
+ $target = $(event.target)
+ action = $target.data('action')
+
+ if action == 'commits'
+ @loadCommits($target.attr('href'))
+ else if action == 'diffs'
+ @loadDiff($target.attr('href'))
+
+ @setCurrentAction(action)
+
+ # Activate a tab based on the current action
+ activateTab: (action) ->
+ action = 'notes' if action == 'show'
+ $(".merge-request-tabs a[data-action='#{action}']").tab('show')
+
+ # Replaces the current Merge Request-specific action in the URL with a new one
+ #
+ # If the action is "notes", the URL is reset to the standard
+ # `MergeRequests#show` route.
+ #
+ # Examples:
+ #
+ # 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"
+ #
+ # Returns the new URL String
+ 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}"
+
+ # Ensure parameters and hash come along for the ride
+ new_state += @_location.search + @_location.hash
+
+ # 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}, document.title, new_state
+
+ new_state
+
+ loadCommits: (source) ->
+ return if @commitsLoaded
+
+ @_get
+ url: "#{source}.json"
+ success: (data) =>
+ document.getElementById('commits').innerHTML = data.html
+ $('.js-timeago').timeago()
+ @commitsLoaded = true
+
+ loadDiff: (source) ->
+ return if @diffsLoaded
+
+ @_get
+ url: "#{source}.json"
+ success: (data) =>
+ document.getElementById('diffs').innerHTML = data.html
+ $('.diff-header').trigger('sticky_kit:recalc')
+ @diffsLoaded = true
+
+ toggleLoading: ->
+ $('.mr-loading-status .loading').toggle()
+
+ _get: (options) ->
+ defaults = {
+ beforeSend: @toggleLoading
+ complete: @toggleLoading
+ dataType: 'json'
+ type: 'GET'
+ }
+
+ options = $.extend({}, defaults, options)
+
+ $.ajax(options)