BigW Consortium Gitlab

user_tabs.js 5.07 KB
Newer Older
1
/* eslint-disable max-len, space-before-function-paren, no-underscore-dangle, consistent-return, comma-dangle, no-unused-vars, dot-notation, no-new, no-return-assign, camelcase, no-param-reassign, class-methods-use-this */
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
/*
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>
    <li class="snippets-tab">
       <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
       </a>
     </li>
   </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>
     <div class="tab-pane" id="snippets">
       Snippets content
     </div>
  </div>

   <div class="loading-status">
     <div class="loading">
      Loading Animation
     </div>
   </div>
*/
62
((global) => {
63
  class UserTabs {
64
    constructor ({ defaultAction, action, parentEl }) {
65
      this.loaded = {};
66 67
      this.defaultAction = defaultAction || 'activity';
      this.action = action || this.defaultAction;
68
      this.$parentEl = $(parentEl) || $(document);
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
      this._location = window.location;
      this.$parentEl.find('.nav-links a')
        .each((i, navLink) => {
          this.loaded[$(navLink).attr('data-action')] = false;
        });
      this.actions = Object.keys(this.loaded);
      this.bindEvents();

      if (this.action === 'show') {
        this.action = this.defaultAction;
      }

      this.activateTab(this.action);
    }

    bindEvents() {
85 86 87
      this.changeProjectsPageWrapper = this.changeProjectsPage.bind(this);

      this.$parentEl.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
88
        .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event));
89 90 91 92 93 94 95 96

      this.$parentEl.on('click', '.gl-pagination a', this.changeProjectsPageWrapper);
    }

    changeProjectsPage(e) {
      e.preventDefault();

      $('.tab-pane.active').empty();
97 98
      const endpoint = $(e.target).attr('href');
      this.loadTab(this.getCurrentAction(), endpoint);
99 100 101 102 103 104
    }

    tabShown(event) {
      const $target = $(event.target);
      const action = $target.data('action');
      const source = $target.attr('href');
105 106 107
      const endpoint = $target.data('endpoint');
      this.setTab(action, endpoint);
      return this.setCurrentAction(source);
108 109 110
    }

    activateTab(action) {
111
      return this.$parentEl.find(`.nav-links .js-${action}-tab a`)
112 113 114
        .tab('show');
    }

115
    setTab(action, endpoint) {
116 117 118 119
      if (this.loaded[action]) {
        return;
      }
      if (action === 'activity') {
120
        this.loadActivities();
121
      }
122

123
      const loadableActions = ['groups', 'contributed', 'projects', 'snippets'];
124
      if (loadableActions.indexOf(action) > -1) {
125
        return this.loadTab(action, endpoint);
126 127 128
      }
    }

129
    loadTab(action, endpoint) {
130 131 132 133 134
      return $.ajax({
        beforeSend: () => this.toggleLoading(true),
        complete: () => this.toggleLoading(false),
        dataType: 'json',
        type: 'GET',
135
        url: endpoint,
136
        success: (data) => {
137
          const tabSelector = `div#${action}`;
138 139 140 141 142 143 144
          this.$parentEl.find(tabSelector).html(data.html);
          this.loaded[action] = true;
          return gl.utils.localTimeAgo($('.js-timeago', tabSelector));
        }
      });
    }

145
    loadActivities() {
146 147 148 149 150
      if (this.loaded['activity']) {
        return;
      }
      const $calendarWrap = this.$parentEl.find('.user-calendar');
      $calendarWrap.load($calendarWrap.data('href'));
151
      new gl.Activities();
152 153 154 155 156 157 158 159
      return this.loaded['activity'] = true;
    }

    toggleLoading(status) {
      return this.$parentEl.find('.loading-status .loading')
        .toggle(status);
    }

160
    setCurrentAction(source) {
161
      let new_state = source;
162
      new_state = new_state.replace(/\/+$/, '');
163 164 165 166 167
      new_state += this._location.search + this._location.hash;
      history.replaceState({
        url: new_state
      }, document.title, new_state);
      return new_state;
168
    }
169 170 171 172

    getCurrentAction() {
      return this.$parentEl.find('.nav-links .active a').data('action');
    }
173 174 175
  }
  global.UserTabs = UserTabs;
})(window.gl || (window.gl = {}));