# MergeRequestTabs # # Handles persisting and restoring the current tab selection and lazily-loading # content on the MergeRequests#show page. # # ### Example Markup # # # #
#
# Notes Content #
#
# Commits Content #
#
# Diffs Content #
#
# #
#
# Loading Animation #
#
# class @MergeRequestTabs diffsLoaded: false buildsLoaded: false commitsLoaded: false constructor: (@opts = {}) -> # Store the `location` object, allowing for easier stubbing in tests @_location = location @bindEvents() @activateTab(@opts.action) bindEvents: -> $(document).on 'shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', @tabShown $(document).on 'click', '.js-show-tab', @showTab showTab: (event) => event.preventDefault() @activateTab $(event.target).data('action') tabShown: (event) => $target = $(event.target) action = $target.data('action') if action == 'commits' @loadCommits($target.attr('href')) else if action == 'diffs' @loadDiff($target.attr('href')) else if action == 'builds' @loadBuilds($target.attr('href')) @setCurrentAction(action) scrollToElement: (container) -> if window.location.hash $el = $("div#{container} #{window.location.hash}") $('body').scrollTo($el.offset().top) if $el.length # 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|builds)(\.html)?\/?$/, '') # 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.querySelector("div#commits").innerHTML = data.html $('.js-timeago').timeago() @commitsLoaded = true @scrollToElement("#commits") loadDiff: (source) -> return if @diffsLoaded @_get url: "#{source}.json" + @_location.search success: (data) => document.querySelector("div#diffs").innerHTML = data.html $('div#diffs .js-syntax-highlight').syntaxHighlight() @diffsLoaded = true @scrollToElement("#diffs") loadBuilds: (source) -> return if @buildsLoaded @_get url: "#{source}.json" success: (data) => document.querySelector("div#builds").innerHTML = data.html $('.js-timeago').timeago() @buildsLoaded = true @scrollToElement("#builds") # Show or hide the loading spinner # # status - Boolean, true to show, false to hide toggleLoading: (status) -> $('.mr-loading-status .loading').toggle(status) _get: (options) -> defaults = { beforeSend: => @toggleLoading(true) complete: => @toggleLoading(false) dataType: 'json' type: 'GET' } options = $.extend({}, defaults, options) $.ajax(options)