diff options
author | Jacob Schatz <jschatz@gitlab.com> | 2016-08-18 20:04:18 +0000 |
---|---|---|
committer | Jacob Schatz <jschatz@gitlab.com> | 2016-08-18 20:04:18 +0000 |
commit | 2b487edc98186e7f46c93ef7e6d029902aa82ebe (patch) | |
tree | e1626b042819065c871be10117a6d155553a8599 | |
parent | 4659a64b53d63841cb042ceee1d4d2b29c3336b8 (diff) | |
parent | d548f3ee27fd12b4bafd36b0d6f2b9890ac383b4 (diff) | |
download | gitlab-ce-2b487edc98186e7f46c93ef7e6d029902aa82ebe.tar.gz |
Merge branch '18334-truncate-award-emoji-users' into 'master'
Truncated long user lists in award emoji tooltips
## What does this MR do?
Truncates award emoji tooltips so that they only show 10 users maximum.
Further users are indicated by appending "and X more."
## Are there points in the code the reviewer needs to double check?
Is 10 too little, should it be raised?
My test cases rely on join() to build the expected output.
This feels a little iffy is it alright?
## Why was this MR needed?
Some issues have a large number of thumbs causing tooltips to be very large.
## What are the relevant issue numbers?
closes #18334, closes #19542
## Screenshots (if relevant)
##### Before
![Screenshot_from_2016-06-20_19-49-12](/uploads/d7a14dd87bb3da2acd7c0818de99852b/Screenshot_from_2016-06-20_19-49-12.png)
##### After
![Screenshot_from_2016-06-20_19-50-58](/uploads/f7f05c44594bfe8cec7dfd48802753a6/Screenshot_from_2016-06-20_19-50-58.png)
Truncation point modified for purposes of screenshot
## Does this MR meet the acceptance criteria?
- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [x] API support added
- [x] Tests
- [x] Added for this feature/bug
- [x] All builds are passing
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
See merge request !4780
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | app/assets/javascripts/awards_handler.js | 54 | ||||
-rw-r--r-- | app/helpers/issues_helper.rb | 14 | ||||
-rw-r--r-- | features/steps/project/issues/award_emoji.rb | 2 | ||||
-rw-r--r-- | spec/helpers/issues_helper_spec.rb | 26 | ||||
-rw-r--r-- | spec/javascripts/awards_handler_spec.js | 46 |
6 files changed, 116 insertions, 28 deletions
diff --git a/CHANGELOG b/CHANGELOG index 164c4184feb..dc530c3481b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -87,6 +87,8 @@ v 8.11.0 (unreleased) - Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le) - Load project invited groups and members eagerly in `ProjectTeam#fetch_members` - Add pipeline events hook + - Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison) + - Fix duplicate "me" in award emoji tooltip !5218 (jlogandavison) - Bump gitlab_git to speedup DiffCollection iterations - Rewrite description of a blocked user in admin settings. (Elias Werberich) - Make branches sortable without push permission !5462 (winniehell) diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 2c5b83e4f1e..aee1c29eee3 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -1,5 +1,6 @@ (function() { this.AwardsHandler = (function() { + const FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence function AwardsHandler() { this.aliases = gl.emojiAliases(); $(document).off('click', '.js-add-award').on('click', '.js-add-award', (function(_this) { @@ -130,7 +131,7 @@ counter = $emojiButton.find('.js-counter'); counter.text(parseInt(counter.text()) + 1); $emojiButton.addClass('active'); - this.addMeToUserList(votesBlock, emoji); + this.addYouToUserList(votesBlock, emoji); return this.animateEmoji($emojiButton); } } else { @@ -176,11 +177,11 @@ counterNumber = parseInt(counter.text(), 10); if (counterNumber > 1) { counter.text(counterNumber - 1); - this.removeMeFromUserList($emojiButton, emoji); + this.removeYouFromUserList($emojiButton, emoji); } else if (emoji === 'thumbsup' || emoji === 'thumbsdown') { $emojiButton.tooltip('destroy'); counter.text('0'); - this.removeMeFromUserList($emojiButton, emoji); + this.removeYouFromUserList($emojiButton, emoji); if ($emojiButton.parents('.note').length) { this.removeEmoji($emojiButton); } @@ -204,43 +205,48 @@ return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || ''; }; - AwardsHandler.prototype.removeMeFromUserList = function($emojiButton, emoji) { + AwardsHandler.prototype.toSentence = function(list) { + if(list.length <= 2){ + return list.join(' and '); + } + else{ + return list.slice(0, -1).join(', ') + ', and ' + list[list.length - 1]; + } + }; + + AwardsHandler.prototype.removeYouFromUserList = function($emojiButton, emoji) { var authors, awardBlock, newAuthors, originalTitle; awardBlock = $emojiButton; originalTitle = this.getAwardTooltip(awardBlock); - authors = originalTitle.split(', '); - authors.splice(authors.indexOf('me'), 1); - newAuthors = authors.join(', '); - awardBlock.closest('.js-emoji-btn').removeData('original-title').attr('data-original-title', newAuthors); - return this.resetTooltip(awardBlock); + authors = originalTitle.split(FROM_SENTENCE_REGEX); + authors.splice(authors.indexOf('You'), 1); + return awardBlock + .closest('.js-emoji-btn') + .removeData('title') + .removeAttr('data-title') + .removeAttr('data-original-title') + .attr('title', this.toSentence(authors)) + .tooltip('fixTitle'); }; - AwardsHandler.prototype.addMeToUserList = function(votesBlock, emoji) { + AwardsHandler.prototype.addYouToUserList = function(votesBlock, emoji) { var awardBlock, origTitle, users; awardBlock = this.findEmojiIcon(votesBlock, emoji).parent(); origTitle = this.getAwardTooltip(awardBlock); users = []; if (origTitle) { - users = origTitle.trim().split(', '); + users = origTitle.trim().split(FROM_SENTENCE_REGEX); } - users.push('me'); - awardBlock.attr('title', users.join(', ')); - return this.resetTooltip(awardBlock); - }; - - AwardsHandler.prototype.resetTooltip = function(award) { - var cb; - award.tooltip('destroy'); - cb = function() { - return award.tooltip(); - }; - return setTimeout(cb, 200); + users.unshift('You'); + return awardBlock + .attr('title', this.toSentence(users)) + .tooltip('fixTitle'); }; AwardsHandler.prototype.createEmoji_ = function(votesBlock, emoji) { var $emojiButton, buttonHtml, emojiCssClass; emojiCssClass = this.resolveNameToCssClass(emoji); - buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='me' data-placement='bottom'> <div class='icon emoji-icon " + emojiCssClass + "' data-emoji='" + emoji + "'></div> <span class='award-control-text js-counter'>1</span> </button>"; + buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='You' data-placement='bottom'> <div class='icon emoji-icon " + emojiCssClass + "' data-emoji='" + emoji + "'></div> <span class='award-control-text js-counter'>1</span> </button>"; $emojiButton = $(buttonHtml); $emojiButton.insertBefore(votesBlock.find('.js-award-holder')).find('.emoji-icon').data('emoji', emoji); this.animateEmoji($emojiButton); diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 2e82b44437b..8b212b0327a 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -114,9 +114,17 @@ module IssuesHelper end def award_user_list(awards, current_user) - awards.map do |award| - award.user == current_user ? 'me' : award.user.name - end.join(', ') + names = awards.map do |award| + award.user == current_user ? 'You' : award.user.name + end + + # Take first 9 OR current user + first 9 + current_user_name = names.delete('You') + names = names.first(9).insert(0, current_user_name).compact + + names << "#{awards.size - names.size} more." if awards.size > names.size + + names.to_sentence end def award_active_class(awards, current_user) diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index 1498f899cf5..cbe5738e7e4 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -48,7 +48,7 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps page.within '.awards' do expect(page).to have_selector '.js-emoji-btn' expect(page.find('.js-emoji-btn.active .js-counter')).to have_content '1' - expect(page).to have_css(".js-emoji-btn.active[data-original-title='me']") + expect(page).to have_css(".js-emoji-btn.active[data-original-title='You']") end end diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 5e4655dfc95..67bac782591 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -62,6 +62,32 @@ describe IssuesHelper do it { is_expected.to eq("!1, !2, or !3") } end + describe '#award_user_list' do + let!(:awards) { build_list(:award_emoji, 15) } + + it "returns a comma seperated list of 1-9 users" do + expect(award_user_list(awards.first(9), nil)).to eq(awards.first(9).map { |a| a.user.name }.to_sentence) + end + + it "displays the current user's name as 'You'" do + expect(award_user_list(awards.first(1), awards[0].user)).to eq('You') + end + + it "truncates lists of larger than 9 users" do + expect(award_user_list(awards, nil)).to eq(awards.first(9).map { |a| a.user.name }.join(', ') + ", and 6 more.") + end + + it "displays the current user in front of 0-9 other users" do + expect(award_user_list(awards, awards[0].user)). + to eq("You, " + awards[1..9].map { |a| a.user.name }.join(', ') + ", and 5 more.") + end + + it "displays the current user in front regardless of position in the list" do + expect(award_user_list(awards, awards[12].user)). + to eq("You, " + awards[0..8].map { |a| a.user.name }.join(', ') + ", and 5 more.") + end + end + describe '#award_active_class' do let!(:upvote) { create(:award_emoji) } diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js index 3ddc163033e..fa32d0d7da5 100644 --- a/spec/javascripts/awards_handler_spec.js +++ b/spec/javascripts/awards_handler_spec.js @@ -143,6 +143,52 @@ return expect($votesBlock.find('[data-emoji=fire]').length).toBe(0); }); }); + describe('::addYouToUserList', function() { + it('should prepend "You" to the award tooltip', function() { + var $thumbsUpEmoji, $votesBlock, awardUrl; + awardUrl = awardsHandler.getAwardUrl(); + $votesBlock = $('.js-awards-block').eq(0); + $thumbsUpEmoji = $votesBlock.find('[data-emoji=thumbsup]').parent(); + $thumbsUpEmoji.attr('data-title', 'sam, jerry, max, and andy'); + awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); + $thumbsUpEmoji.tooltip(); + return expect($thumbsUpEmoji.data("original-title")).toBe('You, sam, jerry, max, and andy'); + }); + return it('handles the special case where "You" is not cleanly comma seperated', function() { + var $thumbsUpEmoji, $votesBlock, awardUrl; + awardUrl = awardsHandler.getAwardUrl(); + $votesBlock = $('.js-awards-block').eq(0); + $thumbsUpEmoji = $votesBlock.find('[data-emoji=thumbsup]').parent(); + $thumbsUpEmoji.attr('data-title', 'sam'); + awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); + $thumbsUpEmoji.tooltip(); + return expect($thumbsUpEmoji.data("original-title")).toBe('You and sam'); + }); + }); + describe('::removeYouToUserList', function() { + it('removes "You" from the front of the tooltip', function() { + var $thumbsUpEmoji, $votesBlock, awardUrl; + awardUrl = awardsHandler.getAwardUrl(); + $votesBlock = $('.js-awards-block').eq(0); + $thumbsUpEmoji = $votesBlock.find('[data-emoji=thumbsup]').parent(); + $thumbsUpEmoji.attr('data-title', 'You, sam, jerry, max, and andy'); + $thumbsUpEmoji.addClass('active'); + awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); + $thumbsUpEmoji.tooltip(); + return expect($thumbsUpEmoji.data("original-title")).toBe('sam, jerry, max, and andy'); + }); + return it('handles the special case where "You" is not cleanly comma seperated', function() { + var $thumbsUpEmoji, $votesBlock, awardUrl; + awardUrl = awardsHandler.getAwardUrl(); + $votesBlock = $('.js-awards-block').eq(0); + $thumbsUpEmoji = $votesBlock.find('[data-emoji=thumbsup]').parent(); + $thumbsUpEmoji.attr('data-title', 'You and sam'); + $thumbsUpEmoji.addClass('active'); + awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false); + $thumbsUpEmoji.tooltip(); + return expect($thumbsUpEmoji.data("original-title")).toBe('sam'); + }); + }); describe('search', function() { return it('should filter the emoji', function() { $('.js-add-award').eq(0).click(); |