summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2018-07-16 18:18:52 +0200
committerBob Van Landuyt <bob@vanlanduyt.co>2018-07-30 15:01:26 +0200
commitf1d3ea63cf74d2791a9a863b29ab2d919ea61bd0 (patch)
treec36c2b272fba917af321a4f16c34a5047407f3b2 /app
parentb4c4b48a8c0258ff266c523488aa169a1b5ea0f3 (diff)
downloadgitlab-ce-f1d3ea63cf74d2791a9a863b29ab2d919ea61bd0.tar.gz
Show the status of a user in interactions
The status is shown for - The author of a commit when viewing a commit - Notes on a commit (regular/diff) - The user that triggered a pipeline when viewing a pipeline - The author of a merge request when viewing a merge request - The author of notes on a merge request (regular/diff) - The author of an issue when viewing an issue - The author of notes on an issue - The author of a snippet when viewing a snippet - The author of notes on a snippet - A user's profile page - The list of members of a group/user
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue3
-rw-r--r--app/controllers/concerns/members_presentation.rb8
-rw-r--r--app/controllers/concerns/membership_actions.rb2
-rw-r--r--app/controllers/concerns/notes_actions.rb4
-rw-r--r--app/controllers/concerns/renders_notes.rb5
-rw-r--r--app/controllers/groups/group_members_controller.rb2
-rw-r--r--app/controllers/projects/commit_controller.rb9
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb2
-rw-r--r--app/controllers/projects/notes_controller.rb3
-rw-r--r--app/controllers/projects/pipelines_controller.rb6
-rw-r--r--app/controllers/projects/snippets_controller.rb2
-rw-r--r--app/controllers/snippets/notes_controller.rb2
-rw-r--r--app/controllers/snippets_controller.rb2
-rw-r--r--app/helpers/issuables_helper.rb6
-rw-r--r--app/helpers/users_helper.rb18
-rw-r--r--app/models/note.rb2
-rw-r--r--app/models/snippet.rb1
-rw-r--r--app/models/user_status.rb4
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb19
-rw-r--r--app/serializers/user_entity.rb1
-rw-r--r--app/services/users/set_status_service.rb1
-rw-r--r--app/views/projects/commit/_commit_box.html.haml1
-rw-r--r--app/views/shared/members/_member.html.haml1
-rw-r--r--app/views/shared/notes/_note.html.haml4
-rw-r--r--app/views/shared/snippets/_header.html.haml1
-rw-r--r--app/views/users/show.html.haml5
28 files changed, 105 insertions, 14 deletions
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index ee3580895df..a621418cf72 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -74,6 +74,9 @@ export default {
</div>
<a :href="author.path">
<span class="note-header-author-name">{{ author.name }}</span>
+ <span
+ v-if="author.status_tooltip_html"
+ v-html="author.status_tooltip_html"></span>
<span class="note-headline-light">
@{{ author.username }}
</span>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 62d35f6547d..49fbce75110 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -113,6 +113,9 @@ export default {
{{ user.name }}
</a>
+ <span
+ v-if="user.status_tooltip_html"
+ v-html="user.status_tooltip_html"></span>
</template>
</section>
diff --git a/app/controllers/concerns/members_presentation.rb b/app/controllers/concerns/members_presentation.rb
index c0622516fd3..215e0bdf3cb 100644
--- a/app/controllers/concerns/members_presentation.rb
+++ b/app/controllers/concerns/members_presentation.rb
@@ -2,10 +2,18 @@ module MembersPresentation
extend ActiveSupport::Concern
def present_members(members)
+ preload_associations(members)
Gitlab::View::Presenter::Factory.new(
members,
current_user: current_user,
presenter_class: MembersPresenter
).fabricate!
end
+
+ def preload_associations(members)
+ ActiveRecord::Associations::Preloader.new.preload(members, :user)
+ ActiveRecord::Associations::Preloader.new.preload(members, :source)
+ ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :status)
+ ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :u2f_registrations)
+ end
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 7a6a00b8e13..409e6d4c4d2 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -1,4 +1,5 @@
module MembershipActions
+ include MembersPresentation
extend ActiveSupport::Concern
def create
@@ -20,6 +21,7 @@ module MembershipActions
.execute(member)
.present(current_user: current_user)
+ present_members([member])
respond_to do |format|
format.js { render 'shared/members/update', locals: { member: member } }
end
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index fe9a030cdf2..5127db3f5fb 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -41,7 +41,7 @@ module NotesActions
@note = Notes::CreateService.new(note_project, current_user, create_params).execute
if @note.is_a?(Note)
- Notes::RenderService.new(current_user).execute([@note])
+ prepare_notes_for_rendering([@note], noteable)
end
respond_to do |format|
@@ -56,7 +56,7 @@ module NotesActions
@note = Notes::UpdateService.new(project, current_user, note_params).execute(note)
if @note.is_a?(Note)
- Notes::RenderService.new(current_user).execute([@note])
+ prepare_notes_for_rendering([@note])
end
respond_to do |format|
diff --git a/app/controllers/concerns/renders_notes.rb b/app/controllers/concerns/renders_notes.rb
index 36e3d76ecfe..cf04023080a 100644
--- a/app/controllers/concerns/renders_notes.rb
+++ b/app/controllers/concerns/renders_notes.rb
@@ -4,6 +4,7 @@ module RendersNotes
preload_noteable_for_regular_notes(notes)
preload_max_access_for_authors(notes, @project)
preload_first_time_contribution_for_authors(noteable, notes)
+ preload_author_status(notes)
Notes::RenderService.new(current_user).execute(notes)
notes
@@ -28,4 +29,8 @@ module RendersNotes
notes.each {|n| n.specialize_for_first_contribution!(noteable)}
end
+
+ def preload_author_status(notes)
+ ActiveRecord::Associations::Preloader.new.preload(notes, { author: :status })
+ end
end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index ef5d5e5c742..7dc51f4c357 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -30,7 +30,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
end
@members = @members.page(params[:page]).per(50)
- @members = present_members(@members.includes(:user))
+ @members = present_members(@members)
@requesters = present_members(
AccessRequestsFinder.new(@group).execute(current_user))
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 1d1184d46d1..44b176d304e 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -22,7 +22,9 @@ class Projects::CommitController < Projects::ApplicationController
apply_diff_view_cookie!
respond_to do |format|
- format.html { render }
+ format.html do
+ render
+ end
format.diff do
send_git_diff(@project.repository, @commit.diff_refs)
end
@@ -124,7 +126,10 @@ class Projects::CommitController < Projects::ApplicationController
end
def commit
- @noteable = @commit ||= @project.commit_by(oid: params[:id])
+ @noteable = @commit ||= @project.commit_by(oid: params[:id]).tap do |commit|
+ # preload author and their status for rendering
+ commit&.author&.status
+ end
end
def define_commit_vars
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 7c897b2d86c..ef8159aa553 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -165,7 +165,7 @@ class Projects::IssuesController < Projects::ApplicationController
return @issue if defined?(@issue)
# The Sortable default scope causes performance issues when used with find_by
- @issuable = @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
+ @issuable = @noteable = @issue ||= @project.issues.includes(author: :status).where(iid: params[:id]).reorder(nil).take!
@note = @project.notes.new(noteable: @issuable)
return render_404 unless can?(current_user, :read_issue, @issue)
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index 8e4aeec16dc..fead81dd472 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -6,7 +6,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
private
def merge_request
- @issuable = @merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
+ @issuable = @merge_request ||= @project.merge_requests.includes(author: :status).find_by!(iid: params[:id])
end
def merge_request_params
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 4d4c2af2415..21e2145b73b 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -1,4 +1,5 @@
class Projects::NotesController < Projects::ApplicationController
+ include RendersNotes
include NotesActions
include NotesHelper
include ToggleAwardEmoji
@@ -53,7 +54,7 @@ class Projects::NotesController < Projects::ApplicationController
private
def render_json_with_notes_serializer
- Notes::RenderService.new(current_user).execute([note])
+ prepare_notes_for_rendering([note])
render json: note_serializer.represent(note)
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 45cef123c34..1d5d1ee5d5a 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -161,7 +161,11 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def pipeline
- @pipeline ||= project.pipelines.find_by!(id: params[:id]).present(current_user: current_user)
+ @pipeline ||= project
+ .pipelines
+ .includes(user: :status)
+ .find_by!(id: params[:id])
+ .present(current_user: current_user)
end
def commit
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index f742d7edf83..7c03d8ce827 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -88,7 +88,7 @@ class Projects::SnippetsController < Projects::ApplicationController
protected
def snippet
- @snippet ||= @project.snippets.find(params[:id])
+ @snippet ||= @project.snippets.inc_relations_for_view.find(params[:id])
end
alias_method :awardable, :snippet
alias_method :spammable, :snippet
diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb
index c8b4682e6dc..217da89a1fd 100644
--- a/app/controllers/snippets/notes_controller.rb
+++ b/app/controllers/snippets/notes_controller.rb
@@ -9,7 +9,7 @@ class Snippets::NotesController < ApplicationController
private
def note
- @note ||= snippet.notes.find(params[:id])
+ @note ||= snippet.notes.inc_relations_for_view.find(params[:id])
end
alias_method :awardable, :note
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 1d6d0943674..dcf18c1f751 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -95,7 +95,7 @@ class SnippetsController < ApplicationController
protected
def snippet
- @snippet ||= PersonalSnippet.find_by(id: params[:id])
+ @snippet ||= PersonalSnippet.inc_relations_for_view.find_by(id: params[:id])
end
alias_method :awardable, :snippet
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 8766bb43cac..678fed9c414 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -159,6 +159,12 @@ module IssuablesHelper
output << content_tag(:strong) do
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline", tooltip: true)
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-block d-sm-none")
+
+ if status = user_status(issuable.author)
+ author_output << "&ensp; #{status}".html_safe
+ end
+
+ author_output
end
output << "&ensp;".html_safe
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 8ee4203b6f5..ceea4384f91 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -39,6 +39,24 @@ module UsersHelper
"access:#{max_project_member_access(project)}"
end
+ def user_status(user)
+ return unless user
+
+ unless user.association(:status).loaded?
+ exception = RuntimeError.new("Status was not preloaded")
+ Gitlab::Sentry.track_exception(exception, extra: { user: user.inspect })
+ end
+
+ return unless user.status
+
+ content_tag :span,
+ class: 'user-status-emoji has-tooltip',
+ title: user.status.message_html,
+ data: { html: true, placement: 'top' } do
+ emoji_icon user.status.emoji
+ end
+ end
+
private
def get_profile_tabs
diff --git a/app/models/note.rb b/app/models/note.rb
index fe3507adcb3..87cf7c7b2fa 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -101,7 +101,7 @@ class Note < ActiveRecord::Base
scope :inc_author_project, -> { includes(:project, :author) }
scope :inc_author, -> { includes(:author) }
scope :inc_relations_for_view, -> do
- includes(:project, :author, :updated_by, :resolved_by, :award_emoji,
+ includes(:project, { author: :status }, :updated_by, :resolved_by, :award_emoji,
:system_note_metadata, :note_diff_file)
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 644120453cf..390bdbf838a 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -49,6 +49,7 @@ class Snippet < ActiveRecord::Base
scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) }
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
scope :fresh, -> { order("created_at DESC") }
+ scope :inc_relations_for_view, -> { includes(author: :status) }
participant :author
participant :notes_with_associations
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 72938cfbca0..2bbb0c59ac1 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -3,6 +3,10 @@
class UserStatus < ActiveRecord::Base
include CacheMarkdownField
+ self.primary_key = :user_id
+
+ DEFAULT_EMOJI = 'speech_balloon'.freeze
+
belongs_to :user
validates :user, presence: true
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
new file mode 100644
index 00000000000..aa6e67e3351
--- /dev/null
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module UserStatusTooltip
+ extend ActiveSupport::Concern
+ include ActionView::Helpers::TagHelper
+ include ActionView::Context
+ include EmojiHelper
+ include UsersHelper
+
+ included do
+ expose :user_status_if_loaded, as: :status_tooltip_html
+
+ def user_status_if_loaded
+ return nil unless object.association(:status).loaded?
+
+ user_status(object)
+ end
+ end
+end
diff --git a/app/serializers/user_entity.rb b/app/serializers/user_entity.rb
index 6236d66ff4a..656900bb8af 100644
--- a/app/serializers/user_entity.rb
+++ b/app/serializers/user_entity.rb
@@ -2,6 +2,7 @@
class UserEntity < API::Entities::UserBasic
include RequestAwareEntity
+ include UserStatusTooltip
expose :path do |user|
user_path(user)
diff --git a/app/services/users/set_status_service.rb b/app/services/users/set_status_service.rb
index 275e13faf59..89008368d5f 100644
--- a/app/services/users/set_status_service.rb
+++ b/app/services/users/set_status_service.rb
@@ -24,6 +24,7 @@ module Users
private
def set_status
+ params[:emoji] = UserStatus::DEFAULT_EMOJI if params[:emoji].blank?
user_status.update(params)
end
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 78522393d4b..8afbbaf378f 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -13,6 +13,7 @@
= author_avatar(@commit, size: 24, has_tooltip: false)
%strong
= commit_author_link(@commit, avatar: true, size: 24)
+ = user_status(@commit.author)
- if @commit.different_committer?
%span.light= _('Committed by')
%strong
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 46debe1f2b9..af29c0fe59e 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -11,6 +11,7 @@
= image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
.user-info
= link_to user.name, user_path(user), class: 'member'
+ = user_status(user)
%span.cgray= user.to_reference
- if user == current_user
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index f5464058bc0..84adbd444c5 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -31,7 +31,9 @@
.note-header
.note-header-info
%a{ href: user_path(note.author) }
- %span.note-header-author-name= sanitize(note.author.name)
+ %span.note-header-author-name
+ = sanitize(note.author.name)
+ = user_status(note.author)
%span.note-headline-light
= note.author.to_reference
%span.note-headline-light
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index 828ec870dc0..10bfc30492a 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -8,6 +8,7 @@
Authored
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title", avatar_class: "d-none d-sm-inline")}
+ = user_status(@snippet.author)
.detail-page-header-actions
- if @snippet.project_id?
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 8d9e86d02c4..7a38d290915 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -40,6 +40,11 @@
.cover-title
= @user.name
+ - if @user.status
+ .cover-status
+ = emoji_icon(@user.status.emoji)
+ = markdown_field(@user.status, :message)
+
.cover-desc.member-date
%p
%span.middle-dot-divider