-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#55581] popover for user information on hover #17255
Draft
EinLama
wants to merge
67
commits into
dev
Choose a base branch
from
feature/55581-popover-for-user-information-on-hover
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+729
−70
Draft
Changes from all commits
Commits
Show all changes
67 commits
Select commit
Hold shift + click to select a range
44ac6fc
[#55581] enforce hover card in project member list for now
EinLama 937fa1e
[#55581] unwrap quotes for angular components
EinLama 8f324fa
[#55581] return early
EinLama b743a60
[#55581] Users::HoverCardComponent
EinLama 2528268
[#55581] prefer flex layout
EinLama 530d722
WIP
EinLama 867d204
[#55581] offer hover card trigger switch in avatar helper
EinLama 8c798a8
[#55581] first draft for triangle pointing at hover source
EinLama 5ee7c09
[#55581] construct project membership string, link to profile
EinLama 3629b10
avatar details
EinLama 44ced5b
[#55581] show email if allowed to do so
EinLama ed8f9e2
[#55581] link project names to projects
EinLama 6199acd
[#55581] attach hover card attributes to avatar image
EinLama 3a0e2f8
[#55581] copyright notices
EinLama ad59277
[#55581] clear timeout for closing hover card
EinLama 1082109
return as soon as possible
EinLama d5f0b38
[#55581] set position & close delay of card by data-attr
EinLama 375c870
[#55581] do not show the same modal twice
EinLama 1450c90
[#55581] link to groups instead of projects
EinLama 0e91b52
[#55581] link the end of the sentence to users#show
EinLama 0360982
[#55581] allow hovercards in auto completer and share dialog
EinLama 12f7a7d
[#55581] only show hovercard if set active
EinLama aeb29e9
[#55581] do not attempt to show hover cards for groups
EinLama 3abcc0b
[#55581] ensure hover card is rendered in front of modals
EinLama 537126d
[#55581] show hover card in member list
EinLama 5f9fbb8
WIP
EinLama 7e976d4
[#55581] make portal target customizable
EinLama 1c3ef02
default should be default
EinLama 1dcc011
[#55581] provide hover card in news module
EinLama 5bacf83
[#55581] hover card on boards
EinLama 75197e8
[#55581] hover card in wp activities
EinLama ed817a7
[#55581] hover card in meetings
EinLama f3be0fd
[#55581] hover card on project overview page (members widget)
EinLama 1fa7ed1
[#55581] fix z-index on top of auto completers
EinLama c8f132d
[#55581] small polishing fixes
EinLama 4715127
[#55581] do not set top alignment by default
EinLama b1c97b4
[#55581] add necessary translation for hover card permission
EinLama 33a7126
[#55581] remove redundant comments, provide 404 locale
EinLama f7a10fa
frozen_string_literal
EinLama 8e6fc05
[#55581] explain missing urls in some cases
EinLama fd5d811
[#55581] remove unneeded permission
EinLama dfe0f5a
mv project group
EinLama 997fe53
[#55581] do not show hover card for placeholder users
EinLama 6355a2b
[#55581] reduce ABC in avatar helper
EinLama 36d5a84
[#55581] spec for user hover cards on member page
EinLama cb906e3
[#55581] reduce email font size
EinLama d3ecb66
[#55581] do not let very long names/mails overflow
EinLama 8385f02
[#55581] wait for one second before displaying a hover card
EinLama 1e40f90
[#55581] remove superfluous styling
EinLama 2461c0d
[#55581] link to edit profile, localize button string
EinLama a465d59
[#55581] use text-shortener mixin
EinLama fb61671
[#55581] remove alignment and close delay options
EinLama 5db32b7
[#55581] make user hover card opt-out
EinLama 1fb00f3
fix indentation
EinLama 49aec8b
[#55581] allow disabling the hover card
EinLama 0f0ff98
[#55581] disable hover card on hover card
EinLama 945e505
[#55581] only show visible groups within the hover card
EinLama 6e25f7d
[#55581] hover cards only in project share, not wp share
EinLama eee22e3
[#55581] fix bug where hover cards are sometimes directly dismissed
EinLama 4843e8a
[#55581] do not try to show a modal twice at the same time
EinLama 3a95189
[#55581] use test selectors in spec
EinLama fdc2b1b
[#55581] specs for Users::HoverCardComponent
EinLama 6a6a0a6
[#55581] fix avatar_helper specs
EinLama 62d92bb
[#55581] do not show the hover card within the log time dialog
EinLama 56ed83a
[#55581] ensure the URL is a string
EinLama 7679081
[#55581] disable hover cards in global search
EinLama 9c47122
[#55581] lookbook proposal
EinLama File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<%#-- copyright | ||
OpenProject is an open source project management software. | ||
Copyright (C) the OpenProject GmbH | ||
|
||
This program is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU General Public License version 3. | ||
|
||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: | ||
Copyright (C) 2006-2013 Jean-Philippe Lang | ||
Copyright (C) 2010-2013 the ChiliProject Team | ||
|
||
This program is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU General Public License | ||
as published by the Free Software Foundation; either version 2 | ||
of the License, or (at your option) any later version. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with this program; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
|
||
See COPYRIGHT and LICENSE files for more details. | ||
|
||
++#%> | ||
|
||
<%= | ||
if @user.present? | ||
flex_layout(classes: 'op-user-hover-card', data: { test_selector: "user-hover-card-#{@user.id}" }) do |flex| | ||
flex.with_row do | ||
render(Users::AvatarComponent.new(user: @user, show_name: false, link: false, hover_card: { active: false })) | ||
end | ||
|
||
flex.with_row do | ||
flex_layout(classes: 'op-user-hover-card--info') do |f| | ||
f.with_column(classes: 'op-user-hover-card--name') do | ||
render(Primer::Beta::Text.new(font_weight: :semibold, data: { test_selector: 'user-hover-card-name' })) do | ||
@user.name | ||
end | ||
end | ||
|
||
if show_email? | ||
f.with_column(classes: 'op-user-hover-card--email') do | ||
render(Primer::Beta::Text.new(font_size: :small, | ||
color: :muted, | ||
data: { test_selector: 'user-hover-card-email' })) do | ||
@user.mail | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
flex.with_row do | ||
flex_layout(classes: 'op-user-hover-card--group-list') do |f| | ||
f.with_column do | ||
render(Primer::Beta::Octicon.new(icon: :people)) | ||
end | ||
|
||
f.with_column do | ||
render(Primer::Beta::Text.new(color: :muted, data: { test_selector: 'user-hover-card-groups' })) do | ||
group_membership_summary | ||
end | ||
end | ||
end | ||
end | ||
|
||
flex.with_row do | ||
render(Primer::Beta::Button.new(tag: :a, | ||
href: helpers.allowed_management_user_profile_path(@user), | ||
data: { test_selector: 'user-hover-card-profile-btn' })) do | ||
I18n.t("users.open_profile") | ||
end | ||
end | ||
end | ||
else | ||
render Primer::Beta::Blankslate.new(border: false, narrow: true) do |component| | ||
component.with_visual_icon(icon: "x-circle") | ||
component.with_heading(tag: :h3).with_content(I18n.t("api_v3.errors.not_found.user")) | ||
end | ||
end | ||
%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# frozen_string_literal: true | ||
|
||
#-- copyright | ||
# OpenProject is an open source project management software. | ||
# Copyright (C) the OpenProject GmbH | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License version 3. | ||
# | ||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: | ||
# Copyright (C) 2006-2013 Jean-Philippe Lang | ||
# Copyright (C) 2010-2013 the ChiliProject Team | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# as published by the Free Software Foundation; either version 2 | ||
# of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
# | ||
# See COPYRIGHT and LICENSE files for more details. | ||
#++ | ||
|
||
class Users::HoverCardComponent < ApplicationComponent | ||
include OpPrimer::ComponentHelpers | ||
|
||
def initialize(id:) | ||
super | ||
|
||
@id = id | ||
@user = User.find(@id) | ||
end | ||
|
||
def show_email? | ||
(@user == User.current) || User.current.allowed_globally?(:view_user_email) | ||
end | ||
|
||
# Constructs a string in the form of: | ||
# "Member of group4, group5" | ||
# or | ||
# "Member of group1, group2 and 3 more" | ||
# The latter string is cut off since the complete list of group names would exceed the allowed `max_length`. | ||
def group_membership_summary(max_length = 40) | ||
groups = @user.groups.visible | ||
return no_group_text if groups.empty? | ||
|
||
group_links = linked_group_names(groups) | ||
|
||
cutoff_index = calculate_cutoff_index(groups.map(&:name), max_length) | ||
build_summary(group_links, cutoff_index) | ||
end | ||
|
||
private | ||
|
||
def linked_group_names(groups) | ||
groups.map { |group| link_to(h(group.name), show_group_path(group)) } | ||
end | ||
|
||
def no_group_text | ||
t("users.groups.no_results_title_text") | ||
end | ||
|
||
# Calculate the index at which to cut off the group names, based on plain text length | ||
def calculate_cutoff_index(names, max_length) | ||
current_length = 0 | ||
|
||
names.each_with_index do |name, index| | ||
new_length = current_length + name.length + (index > 0 ? 2 : 0) # 2 for ", " separator | ||
return index if new_length > max_length | ||
|
||
current_length = new_length | ||
end | ||
|
||
names.size # No cutoff needed -> return the total size | ||
end | ||
|
||
def build_summary(links, cutoff_index) | ||
summary_links = safe_join(links[0...cutoff_index], ", ") | ||
remaining_count = links.size - cutoff_index | ||
remaining_count_link = link_to(t("users.groups.more", count: remaining_count), user_path(@user)) | ||
|
||
if remaining_count > 0 | ||
t("users.groups.summary_with_more", names: summary_links, count_link: remaining_count_link).html_safe | ||
else | ||
t("users.groups.summary", names: summary_links).html_safe | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Correct the z-index of the regular hover card container so that it is above the dropdown of user auto completers | ||
.spot-modal-overlay:has(.op-user-hover-card) | ||
z-index: 9600 | ||
|
||
.op-user-hover-card | ||
gap: 1rem | ||
overflow: hidden | ||
|
||
.op-user-hover-card--info | ||
gap: 0.5rem | ||
|
||
.op-user-hover-card--name, .op-user-hover-card--email | ||
@include text-shortener() | ||
|
||
.op-user-hover-card--group-list | ||
gap: 0.5rem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
#-- copyright | ||
# OpenProject is an open source project management software. | ||
# Copyright (C) the OpenProject GmbH | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License version 3. | ||
# | ||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: | ||
# Copyright (C) 2006-2013 Jean-Philippe Lang | ||
# Copyright (C) 2010-2013 the ChiliProject Team | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# as published by the Free Software Foundation; either version 2 | ||
# of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
# | ||
# See COPYRIGHT and LICENSE files for more details. | ||
#++ | ||
class Users::HoverCardController < ApplicationController | ||
no_authorization_required! :show | ||
|
||
def show | ||
@id = params[:id] | ||
render layout: nil | ||
end | ||
end |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the value 40 coming from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A true magic number 🔮🧙🏻♂️ found by, uh... guessing and trying it out! 🪄
Seemed sensible when used with the English translation and should look okay with most other languages. The caveat is that only the group names are considered when deciding where to shorten the list. To make it perfect, we'd have to load the translation first, factor it's length into the calculation and THEN decide where to cut off the group list. I figured the value
40
is good enough in most cases and strikes a balance between pleasant looks and code complexity :)