summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bennett <lukeeeebennettplus@gmail.com>2016-10-19 04:06:45 +0100
committerLuke Bennett <lukeeeebennettplus@gmail.com>2016-10-19 04:22:23 +0100
commit7633e36930dfbd07a6376e57a13168d660fc2c2a (patch)
treea90c5d472883c84f1ae0377810969aa7bcbaa8b6
parentea9aee35a334fae2cc55e67a52c01e30fe337263 (diff)
downloadgitlab-ce-23206-load-issuable-participants-asynchronously.tar.gz
Created new participants actions and added clientside templating driven by ajax request23206-load-issuable-participants-asynchronously
-rw-r--r--app/assets/javascripts/issuable_context.js69
-rw-r--r--app/assets/javascripts/issuable_context.js.es6104
-rw-r--r--app/assets/stylesheets/pages/issuable.scss4
-rw-r--r--app/controllers/projects/issues_controller.rb13
-rw-r--r--app/controllers/projects/merge_requests_controller.rb13
-rw-r--r--app/views/shared/issuable/_participants.html.haml37
-rw-r--r--config/routes/project.rb2
7 files changed, 155 insertions, 87 deletions
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
deleted file mode 100644
index 8147e83ffe8..00000000000
--- a/app/assets/javascripts/issuable_context.js
+++ /dev/null
@@ -1,69 +0,0 @@
-(function() {
- this.IssuableContext = (function() {
- function IssuableContext(currentUser) {
- this.initParticipants();
- new UsersSelect(currentUser);
- $('select.select2').select2({
- width: 'resolve',
- dropdownAutoWidth: true
- });
- $(".issuable-sidebar .inline-update").on("change", "select", function() {
- return $(this).submit();
- });
- $(".issuable-sidebar .inline-update").on("change", ".js-assignee", function() {
- return $(this).submit();
- });
- $(document).off('click', '.issuable-sidebar .dropdown-content a').on('click', '.issuable-sidebar .dropdown-content a', function(e) {
- return e.preventDefault();
- });
- $(document).off('click', '.edit-link').on('click', '.edit-link', function(e) {
- var $block, $selectbox;
- e.preventDefault();
- $block = $(this).parents('.block');
- $selectbox = $block.find('.selectbox');
- if ($selectbox.is(':visible')) {
- $selectbox.hide();
- $block.find('.value').show();
- } else {
- $selectbox.show();
- $block.find('.value').hide();
- }
- if ($selectbox.is(':visible')) {
- return setTimeout(function() {
- return $block.find('.dropdown-menu-toggle').trigger('click');
- }, 0);
- }
- });
- $(".right-sidebar").niceScroll();
- }
-
- IssuableContext.prototype.initParticipants = function() {
- var _this;
- _this = this;
- $(document).on("click", ".js-participants-more", this.toggleHiddenParticipants);
- return $(".js-participants-author").each(function(i) {
- if (i >= _this.PARTICIPANTS_ROW_COUNT) {
- return $(this).addClass("js-participants-hidden").hide();
- }
- });
- };
-
- IssuableContext.prototype.toggleHiddenParticipants = function(e) {
- var currentText, lessText, originalText;
- e.preventDefault();
- currentText = $(this).text().trim();
- lessText = $(this).data("less-text");
- originalText = $(this).data("original-text");
- if (currentText === originalText) {
- $(this).text(lessText);
- } else {
- $(this).text(originalText);
- }
- return $(".js-participants-hidden").toggle();
- };
-
- return IssuableContext;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/issuable_context.js.es6 b/app/assets/javascripts/issuable_context.js.es6
new file mode 100644
index 00000000000..802e1f9763e
--- /dev/null
+++ b/app/assets/javascripts/issuable_context.js.es6
@@ -0,0 +1,104 @@
+(function() {
+ this.IssuableContext = (function() {
+ function IssuableContext(currentUser) {
+ this.initParticipants();
+ new UsersSelect(currentUser);
+ $('select.select2').select2({
+ width: 'resolve',
+ dropdownAutoWidth: true
+ });
+ $(".issuable-sidebar .inline-update").on("change", "select", function() {
+ return $(this).submit();
+ });
+ $(".issuable-sidebar .inline-update").on("change", ".js-assignee", function() {
+ return $(this).submit();
+ });
+ $(document).off('click', '.issuable-sidebar .dropdown-content a').on('click', '.issuable-sidebar .dropdown-content a', function(e) {
+ return e.preventDefault();
+ });
+ $(document).off('click', '.edit-link').on('click', '.edit-link', function(e) {
+ var $block, $selectbox;
+ e.preventDefault();
+ $block = $(this).parents('.block');
+ $selectbox = $block.find('.selectbox');
+ if ($selectbox.is(':visible')) {
+ $selectbox.hide();
+ $block.find('.value').show();
+ } else {
+ $selectbox.show();
+ $block.find('.value').hide();
+ }
+ if ($selectbox.is(':visible')) {
+ return setTimeout(function() {
+ return $block.find('.dropdown-menu-toggle').trigger('click');
+ }, 0);
+ }
+ });
+ $(".right-sidebar").niceScroll();
+ }
+
+ IssuableContext.prototype.initParticipants = function() {
+ const participantsBlock = document.querySelector('.js-participants-block');
+ this.participantsCount = participantsBlock.querySelector('.count');
+ this.participantsTitle = participantsBlock.querySelector('.title');
+ this.participantsList = participantsBlock.querySelector('.participants-list');
+
+ this.participantsOptions = participantsBlock.querySelector('#js-participants-options').dataset;
+ this.participantTemplate = _.template(_.unescape(participantsBlock.querySelector('#participant-template').innerHTML));
+ this.moreParticipantsTemplate = _.template(_.unescape(participantsBlock.querySelector('#more-participants-template').innerHTML));
+ this.PARTICIPANTS_ROW_COUNT = parseInt(this.participantsOptions.participantsRow);
+
+ this.participantsOptions.participantsEndpoint ? this.loadParticipants() : this.bindParticipants();
+ };
+
+ IssuableContext.prototype.loadParticipants = function() {
+ $.get(this.participantsOptions.participantsEndpoint)
+ .then((participants) => {
+ this.renderParticipants(participants);
+ this.bindParticipants();
+ });
+ };
+
+ IssuableContext.prototype.renderParticipants = function(participants) {
+ this.participantsCount.textContent = participants.length;
+ this.participantsTitle.textContent = `${participants.length} participant${participants.length > 1 ? 's' : ''}`;
+ let participantsListInnerHTML = '';
+ for (participant of participants) {
+ participantsListInnerHTML += this.participantTemplate(participant);
+ }
+ if (participants.length > this.PARTICIPANTS_ROW_COUNT) {
+ participantsListInnerHTML += this.moreParticipantsTemplate({
+ moreCount: `${participants.length - this.PARTICIPANTS_ROW_COUNT}`
+ });
+ }
+ this.participantsList.innerHTML = participantsListInnerHTML;
+ };
+
+ IssuableContext.prototype.bindParticipants = function() {
+ $(document).on("click", ".js-participants-more", this.toggleHiddenParticipants);
+ return $(".js-participants-author").each((i, author) => {
+ if (i >= this.PARTICIPANTS_ROW_COUNT) {
+ return $(author).addClass("js-participants-hidden").hide();
+ }
+ });
+ };
+
+ IssuableContext.prototype.toggleHiddenParticipants = function(e) {
+ var currentText, lessText, originalText;
+ e.preventDefault();
+ currentText = $(this).text().trim();
+ lessText = $(this).data("less-text");
+ originalText = $(this).data("original-text");
+ if (currentText === originalText) {
+ $(this).text(lessText);
+ } else {
+ $(this).text(originalText);
+ }
+ return $(".js-participants-hidden").toggle();
+ };
+
+ return IssuableContext;
+
+ })();
+
+}).call(this);
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 230b927a17d..a7a37b24bf3 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -320,6 +320,10 @@
.participants-list {
margin: -5px;
+
+ .spinner {
+ margin-left: 5px;
+ }
}
.participants-author {
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 96041b07647..67981d91678 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -5,11 +5,12 @@ class Projects::IssuesController < Projects::ApplicationController
include ToggleAwardEmoji
include IssuableCollections
include SpammableActions
+ include ApplicationHelper
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
before_action :module_enabled
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
- :related_branches, :can_create_branch]
+ :related_branches, :can_create_branch, :participants]
# Allow read any issue
before_action :authorize_read_issue!, only: [:show]
@@ -156,6 +157,16 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
+ def participants
+ participants = ::Projects::ParticipantsService.new(@project, current_user).execute(@noteable)
+ participants.map do |participant|
+ user = User.find_by_username(participant[:username])
+ participant[:link] = user_path(participant)
+ participant[:avatar] = avatar_icon(user)
+ end
+ render json: participants
+ end
+
protected
def issue
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index a39b47b6d95..8a945f2fc4c 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -6,11 +6,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
include NotesHelper
include ToggleAwardEmoji
include IssuableCollections
+ include ApplicationHelper
before_action :module_enabled
before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check,
- :ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
+ :ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues, :participants
]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines]
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
@@ -437,6 +438,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render json: environments
end
+ def participants
+ participants = ::Projects::ParticipantsService.new(@project, current_user).execute(@issuable)
+ participants.map do |participant|
+ user = User.find_by_username(participant[:username])
+ participant[:link] = user_path(participant)
+ participant[:avatar] = avatar_icon(user)
+ end
+ render json: participants
+ end
+
protected
def selected_target_project
diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml
index 33a9a494857..dd149378150 100644
--- a/app/views/shared/issuable/_participants.html.haml
+++ b/app/views/shared/issuable/_participants.html.haml
@@ -1,20 +1,25 @@
-- participants_row = 7
-- participants_size = participants.size
-- participants_extra = participants_size - participants_row
-.block.participants
+- if current_controller?(:issues)
+ - participants_endpoint = participants_namespace_project_issue_path(@project.namespace, @project, @issue)
+- else
+ - participants_endpoint = participants_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
+
+.block.participants.js-participants-block
+ #js-participants-options{ data: { 'participants-endpoint': participants_endpoint, 'participants-row': 7 } }
.sidebar-collapsed-icon
= icon('users')
- %span
- = participants.count
+ %span.count
+ = icon('spinner spin')
.title.hide-collapsed
- = pluralize participants.count, "participant"
+ Participants
.hide-collapsed.participants-list
- - participants.each do |participant|
- .participants-author.js-participants-author
- = link_to_member(@project, participant, name: false, size: 24)
- - if participants_extra > 0
- %div.participants-more
- %a.js-participants-more{href: "#", data: {original_text: "+ #{participants_size - 7} more", less_text: "- show less"}}
- + #{participants_extra} more
-:javascript
- IssuableContext.prototype.PARTICIPANTS_ROW_COUNT = #{participants_row};
+ = icon('spinner spin', class: 'spinner')
+
+ %script#participant-template{ type: 'text/template' }
+ .participants-author.js-participants-author
+ %a.author_link.has_tooltip{ href: '<%- link %>', data: { 'original-title': '<%- name %>' } }
+ %img.avatar.avatar-inline.s24{ width: '24', src: '<%- avatar %>' }
+
+ %script#more-participants-template{ type: 'text/template' }
+ .participants-more
+ %a.js-participants-more{ href: '#', data: { 'original-text': '+ <%- moreCount %> more', 'less-text': '- show less' } }
+ + <%- moreCount %> more
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 711a59df744..d87d4da64e4 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -280,6 +280,7 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only:
get :diff_for_path
post :resolve_conflicts
post :assign_related_issues
+ get :participants
end
collection do
@@ -388,6 +389,7 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only:
get :referenced_merge_requests
get :related_branches
get :can_create_branch
+ get :participants
end
collection do
post :bulk_update