BigW Consortium Gitlab

user_tabs.js.coffee 4.33 KB
Newer Older
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
# UserTabs
#
# Handles persisting and restoring the current tab selection and lazily-loading
# content on the Users#show page.
#
# ### Example Markup
#
#   <ul class="nav-links">
#     <li class="activity-tab active">
#       <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
#         Activity
#       </a>
#     </li>
#     <li class="groups-tab">
#       <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
#         Groups
#       </a>
#     </li>
#     <li class="contributed-tab">
#       <a data-action="contributed" data-target="#contributed" data-toggle="tab" href="/u/username/contributed">
#         Contributed projects
#       </a>
#     </li>
#     <li class="projects-tab">
#       <a data-action="projects" data-target="#projects" data-toggle="tab" href="/u/username/projects">
#         Personal projects
#       </a>
#     </li>
29 30 31 32
#    <li class="snippets-tab">
#       <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
#       </a>
#     </li>
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#   </ul>
#
#   <div class="tab-content">
#     <div class="tab-pane" id="activity">
#       Activity Content
#     </div>
#     <div class="tab-pane" id="groups">
#       Groups Content
#     </div>
#     <div class="tab-pane" id="contributed">
#       Contributed projects content
#     </div>
#     <div class="tab-pane" id="projects">
#       Projects content
#     </div>
48 49 50
#     <div class="tab-pane" id="snippets">
#       Snippets content
#     </div>
51 52 53 54 55 56 57 58
#   </div>
#
#   <div class="loading-status">
#     <div class="loading">
#       Loading Animation
#     </div>
#   </div>
#
59
class @UserTabs
60 61 62
  constructor: (opts) ->
    {
      @action = 'activity'
63
      @defaultAction = 'activity'
64 65 66 67 68
      @parentEl = $(document)
    } = opts

    # Make jQuery object if selector is provided
    @parentEl = $(@parentEl) if typeof @parentEl is 'string'
69 70 71

    # Store the `location` object, allowing for easier stubbing in tests
    @_location = location
72 73

    # Set tab states
Alfredo Sumaran committed
74
    @loaded = {}
75 76
    for item in @parentEl.find('.nav-links a')
      @loaded[$(item).attr 'data-action'] = false
77

78 79
    # Actions
    @actions = Object.keys @loaded
Alfredo Sumaran committed
80

81
    @bindEvents()
82 83

    # Set active tab
84 85
    @action = @defaultAction if @action is 'show'
    @activateTab(@action)
86 87

  bindEvents: ->
Alfredo Sumaran committed
88 89 90 91
    # Toggle event listeners
    @parentEl
      .off 'shown.bs.tab', '.nav-links a[data-toggle="tab"]'
      .on 'shown.bs.tab', '.nav-links a[data-toggle="tab"]', @tabShown
Alfredo Sumaran committed
92

93 94 95 96 97
  tabShown: (event) =>
    $target = $(event.target)
    action = $target.data('action')
    source = $target.attr('href')

Alfredo Sumaran committed
98
    @setTab(source, action)
99 100
    @setCurrentAction(action)

101
  activateTab: (action) ->
102
    @parentEl.find(".nav-links .js-#{action}-tab a").tab('show')
103

Alfredo Sumaran committed
104 105 106 107 108 109
  setTab: (source, action) ->
    return if @loaded[action] is true

    if action is 'activity'
      @loadActivities(source)

110
    if action in ['groups', 'contributed', 'projects', 'snippets']
Alfredo Sumaran committed
111 112
      @loadTab(source, action)

113
  loadTab: (source, action) ->
Alfredo Sumaran committed
114 115 116 117 118
    $.ajax
      beforeSend: => @toggleLoading(true)
      complete:   => @toggleLoading(false)
      dataType: 'json'
      type: 'GET'
119 120 121
      url: "#{source}.json"
      success: (data) =>
        tabSelector = 'div#' + action
122
        @parentEl.find(tabSelector).html(data.html)
Alfredo Sumaran committed
123
        @loaded[action] = true
124

125 126 127
        # Fix tooltips
        gl.utils.localTimeAgo($('.js-timeago', tabSelector))

Alfredo Sumaran committed
128 129
  loadActivities: (source) ->
    return if @loaded['activity'] is true
130

131
    $calendarWrap = @parentEl.find('.user-calendar')
132
    $calendarWrap.load($calendarWrap.data('href'))
133

Alfredo Sumaran committed
134 135
    new Activities()
    @loaded['activity'] = true
136

Alfredo Sumaran committed
137
  toggleLoading: (status) ->
138
    @parentEl.find('.loading-status .loading').toggle(status)
139 140 141 142

  setCurrentAction: (action) ->
    # Remove possible actions from URL
    regExp = new RegExp('\/(' + @actions.join('|') + ')(\.html)?\/?$')
143 144 145
    new_state = @_location.pathname
    new_state = new_state.replace(/\/+$/, "") # remove trailing slashes
    new_state = new_state.replace(regExp, '')
146 147 148 149 150 151 152 153 154 155 156

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

    # Ensure parameters and hash come along for the ride
    new_state += @_location.search + @_location.hash

    history.replaceState {turbolinks: true, url: new_state}, document.title, new_state

    new_state