From 05b85eb37f0cece7add4007614dee869885e214f Mon Sep 17 00:00:00 2001 From: Lisa P Date: Thu, 14 Jan 2016 18:03:34 +0100 Subject: [PATCH 1/4] make a user-avatar component delete some, add some, fix some tests --- app/components/user-avatar.js | 40 ++++++++++ app/controllers/top.js | 6 -- app/styles/app/layouts/profile.sass | 8 +- app/styles/app/modules/avatar.sass | 95 +++++++++++++---------- app/styles/app/modules/build-header.sass | 5 -- app/styles/app/modules/navigation.sass | 7 +- app/templates/components/branch-row.hbs | 2 +- app/templates/components/build-header.hbs | 6 +- app/templates/components/builds-item.hbs | 2 +- app/templates/components/org-item.hbs | 8 +- app/templates/components/user-avatar.hbs | 2 + app/templates/top.hbs | 5 +- app/utils/urls.js | 4 +- tests/unit/components/builds-item-test.js | 2 +- tests/unit/components/user-avatar-test.js | 61 +++++++++++++++ tests/unit/models/commit-test.js | 4 +- 16 files changed, 176 insertions(+), 81 deletions(-) create mode 100644 app/components/user-avatar.js create mode 100644 app/templates/components/user-avatar.hbs create mode 100644 tests/unit/components/user-avatar-test.js diff --git a/app/components/user-avatar.js b/app/components/user-avatar.js new file mode 100644 index 00000000..4013db9f --- /dev/null +++ b/app/components/user-avatar.js @@ -0,0 +1,40 @@ +import Ember from 'ember'; +import config from 'travis/config/environment'; +import {gravatarImage} from '../utils/urls'; + +export default Ember.Component.extend({ + + tagName: 'span', + classNames: ['avatar'], + + gravatarUrl: function() { + if (!this.get('isAuthor') && !this.get('isComitter')) { + if (this.get('user.type') === 'organization') { + return this.get('user.avatarUrl'); + } else { + return gravatarImage(this.get('user.email'), 36); + } + } else { + if (this.get('isAuthor')) { + return this.user.get('authorAvatarUrlOrGravatar'); + } else if (this.get('isCommitter')) { + return this.user.get('committerAvatarUrlorGravatar'); + } + } + }.property('gravatarUrl'), + + userInitials: function() { + var name = this.get('user.name') || this.get('user.login') || + this.get('user.authorName') || this.get('user.committerName'); + var arr = name.split(' '); + var initials; + + if (arr.length >= 2) { + initials = arr[0].split('')[0] + arr[1].split('')[0]; + } else { + initials = arr[0].split('')[0]; + } + return initials.toUpperCase(); + }.property('userInitials') + +}); diff --git a/app/controllers/top.js b/app/controllers/top.js index de6962d5..2fca30cf 100644 --- a/app/controllers/top.js +++ b/app/controllers/top.js @@ -11,12 +11,6 @@ export default Ember.Controller.extend({ return this.get('user.name') || this.get('user.login'); }.property('user.login', 'user.name'), - gravatarUrl: function() { - if (this.get('user.gravatarId')) { - return location.protocol + "//www.gravatar.com/avatar/" + (this.get('user.gravatarId')) + "?s=36&d=mm"; - } - }.property('user.gravatarId'), - defineTowerColor(broadcastArray) { if (!broadcastArray) { return ''; diff --git a/app/styles/app/layouts/profile.sass b/app/styles/app/layouts/profile.sass index e3e84e36..6c95e01a 100644 --- a/app/styles/app/layouts/profile.sass +++ b/app/styles/app/layouts/profile.sass @@ -87,14 +87,10 @@ .media-elem width: 14% - img - width: 2.6rem - height: 2.6rem - border-radius: 50% .media-body width: 86% p - margin: 0 + margin: .1em 0 ul @include resetul li @@ -261,4 +257,4 @@ p.profile-user-last #unadministerable-hooks p - margin-top: 2em \ No newline at end of file + margin-top: 2em diff --git a/app/styles/app/modules/avatar.sass b/app/styles/app/modules/avatar.sass index bf2af64d..71933ce0 100644 --- a/app/styles/app/modules/avatar.sass +++ b/app/styles/app/modules/avatar.sass @@ -1,43 +1,58 @@ -%avatar - position: relative - background-color: #a0a0a0 - border-radius: 50% - overflow: hidden - &:before - content: "" - display: block - width: 40% - height: 40% - border-radius: 50% - background: $cream-light - position: absolute - top: 20% - margin: auto - left: 0 - right: 0 +=absoluteCenter + position: absolute + top: 0 + right: 0 + bottom: 0 + left: 0 + margin: auto - &:after - content: "" - display: block - width: 66% - height: 70% - border-radius: 50% - background: $cream-light - position: absolute - top: 55% - margin: auto - left: 0 - right: 0 - -.default-avatar--profile - @extend %avatar - width: 2.6rem - height: 2.6rem - -.default-avatar--topbar - @extend %avatar - width: 2.7rem - height: 2.7rem +.avatar display: inline-block + width: 2.3em + height: 2.3em + position: relative vertical-align: middle - margin-left: 0.3em + border-radius: 50% + background-color: white + overflow: hidden + + .pseudo-avatar + +absoluteCenter + border: 1px solid $grey + border-radius: 50% + background: white + z-index: 1 + &:after + content: attr(data-initials) + +absoluteCenter + color: $grey + font-weight: 600 + text-align: center + font-size: 1.4em + line-height: 1.6 + + .real-avatar + +absoluteCenter + z-index: 2 + border-radius: 50% + +.profile + .avatar + margin-left: 1em + top: -3px + +.commit-author + .avatar + width: 20px + height: 20px + .pseudo-avatar:after + font-size: .7em + line-height: 1.7 + +.row-committer + .avatar + width: 18px + height: 18px + .pseudo-avatar:after + font-size: .7em + line-height: 1.6 diff --git a/app/styles/app/modules/build-header.sass b/app/styles/app/modules/build-header.sass index e9a31e37..b84ef377 100644 --- a/app/styles/app/modules/build-header.sass +++ b/app/styles/app/modules/build-header.sass @@ -75,11 +75,6 @@ .commit-author margin: 1rem 0 .7rem - img - width: 20px - height: 20px - margin-right: .5em - border-radius: 50% .commit-description margin: 1rem 0 diff --git a/app/styles/app/modules/navigation.sass b/app/styles/app/modules/navigation.sass index 71e00214..a588770f 100644 --- a/app/styles/app/modules/navigation.sass +++ b/app/styles/app/modules/navigation.sass @@ -32,14 +32,9 @@ $nav-line-height: 35px text-align: right line-height: $top-height float: right - img - border-radius: 50% - width: 2.7rem - height: 2.7rem - margin-left: 1rem @media #{$medium-up} margin-right: 0 - + .navigation-anchor display: block diff --git a/app/templates/components/branch-row.hbs b/app/templates/components/branch-row.hbs index e2c07287..d6cd40b4 100644 --- a/app/templates/components/branch-row.hbs +++ b/app/templates/components/branch-row.hbs @@ -1,5 +1,5 @@
-
+

{{status-icon status=build.last_build.state}} {{build.name}}

diff --git a/app/templates/components/build-header.hbs b/app/templates/components/build-header.hbs index 2d35e48c..d03f3f99 100644 --- a/app/templates/components/build-header.hbs +++ b/app/templates/components/build-header.hbs @@ -38,11 +38,13 @@

{{#if commit.authorName}} - {{commit.authorName}} authored{{#if commit.authorIsCommitter}} and committed{{/if}} + {{user-avatar user=commit isAuthor=true}} + {{commit.authorName}} authored{{#if commit.authorIsCommitter}} and committed{{/if}} {{/if}} {{#unless commit.authorIsCommitter}} {{#if commit.committerName}} - {{commit.committerName}} committed + {{user-avatar user=commit isComitter=true}} + {{commit.committerName}} committed {{/if}} {{/unless}}

diff --git a/app/templates/components/builds-item.hbs b/app/templates/components/builds-item.hbs index 46b11b3e..7e38b4d5 100644 --- a/app/templates/components/builds-item.hbs +++ b/app/templates/components/builds-item.hbs @@ -20,7 +20,7 @@ {{/unless}}
- {{build.commit.authorName}} avatar + {{user-avatar user=build.commit isAuthor=true}} {{build.commit.authorName}}
diff --git a/app/templates/components/org-item.hbs b/app/templates/components/org-item.hbs index 830ce530..4aba50c0 100644 --- a/app/templates/components/org-item.hbs +++ b/app/templates/components/org-item.hbs @@ -1,9 +1,5 @@
- {{#if avatarUrl}} - {{name}} avatar - {{else}} -
- {{/if}} + {{user-avatar user=account}}
{{#link-to "account" account.login}} @@ -12,7 +8,7 @@ {{/link-to}} {{#if isUser}} -

Token: +

Token: {{#if tokenIsVisible}} {{auth.currentUser.token}} {{/if}} diff --git a/app/templates/components/user-avatar.hbs b/app/templates/components/user-avatar.hbs new file mode 100644 index 00000000..77a3a0f9 --- /dev/null +++ b/app/templates/components/user-avatar.hbs @@ -0,0 +1,2 @@ + +avatar diff --git a/app/templates/top.hbs b/app/templates/top.hbs index f3e14815..87a6e78f 100644 --- a/app/templates/top.hbs +++ b/app/templates/top.hbs @@ -56,8 +56,9 @@ {{/if}} {{#if auth.signedIn}} - {{#link-to "profile" class="navigation-anchor signed-in"}}{{userName}} - {{#if gravatarUrl }}{{else}}

{{/if}} + {{#link-to "profile" class="navigation-anchor signed-in"}} + {{userName}} + {{user-avatar user=user}} {{/link-to}} {{/if}} {{#if auth.signingIn}} diff --git a/app/utils/urls.js b/app/utils/urls.js index cea2839b..425b3107 100644 --- a/app/utils/urls.js +++ b/app/utils/urls.js @@ -59,9 +59,7 @@ email = function(email) { }; gravatarImage = function(email, size) { - var avatarDefaultUrl; - avatarDefaultUrl = 'https://travis-ci.org/images/ui/default-avatar.png'; - return "https://www.gravatar.com/avatar/" + (md5(email)) + "?s=" + size + "&d=" + (encodeURIComponent(avatarDefaultUrl)); + return "https://www.gravatar.com/avatar/" + (md5(email)) + "?s=" + size + "&d=blank"; }; export { plainTextLog, githubPullRequest, githubCommit, githubRepo, githubWatchers, githubNetwork, githubAdmin, statusImage, ccXml, email, gravatarImage }; diff --git a/tests/unit/components/builds-item-test.js b/tests/unit/components/builds-item-test.js index b94e5daf..9f36158d 100644 --- a/tests/unit/components/builds-item-test.js +++ b/tests/unit/components/builds-item-test.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript 1.10.0 import { test, moduleForComponent } from 'ember-qunit'; moduleForComponent('builds-item', { - needs: ['helper:format-sha', 'helper:format-duration', 'helper:format-time', 'helper:format-message', 'helper:pretty-date', 'component:status-icon', 'component:request-icon'] + needs: ['helper:format-sha', 'helper:format-duration', 'helper:format-time', 'helper:format-message', 'helper:pretty-date', 'component:status-icon', 'component:request-icon', 'component:user-avatar'] }); test('it renders', function(assert) { diff --git a/tests/unit/components/user-avatar-test.js b/tests/unit/components/user-avatar-test.js new file mode 100644 index 00000000..06ca4396 --- /dev/null +++ b/tests/unit/components/user-avatar-test.js @@ -0,0 +1,61 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import Ember from 'ember'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('user-avatar', 'UserAvatarComponent | Unit', { + +}); + +test('it renders', function() { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... });" + + var attributes = { + type: 'organization', + login: 'testuser', + name: 'Test User', + avatarUrl: 'https://0.gravatar.com/avatar/595cf623f3cde2fa64fc784884c4bfec' + }; + + var org = Ember.Object.create(attributes); + var component = this.subject({user: org}); + this.append(); + + ok(component.$().hasClass('avatar'), 'component should have right class'); + equal(component.$('.pseudo-avatar').data('initials'), 'TU', 'initials should be correct'); + equal(component.$('.real-avatar').attr('src'), 'https://0.gravatar.com/avatar/595cf623f3cde2fa64fc784884c4bfec', 'avatar shoudl be right'); + +}); + +test('it handles a missing user name', function() { + + var attr = { + type: 'organization', + login: 'testorg' + }; + + var org = Ember.Object.create(attr); + var component = this.subject({user: org}); + this.append(); + + equal(component.$('.pseudo-avatar').data('initials'), 'T', 'only one letter if there is no name'); + +}); + + +test('can get avatars from commits', function() { + + + var attr = { + authorName: 'This is Author' + }; + + var user = Ember.Object.create(attr); + var component = this.subject({user: user}); + this.append(); + + equal(component.$('.real-avatar').attr('src'), 'https://www.gravatar.com/avatar/5e543256c480ac577d30f76f9120eb74?s=36&d=blank', 'get the right avatar url'); + + equal(component.$('.pseudo-avatar').data('initials'), 'TI', 'gets right initials'); + +}); diff --git a/tests/unit/models/commit-test.js b/tests/unit/models/commit-test.js index 9d457ef2..ee653c38 100644 --- a/tests/unit/models/commit-test.js +++ b/tests/unit/models/commit-test.js @@ -16,8 +16,8 @@ test('calculation of avatar urls via Gravatar', function() { committerAvatarUrl: null }); }); - equal(model.get('authorAvatarUrlOrGravatar'), 'https://www.gravatar.com/avatar/5c1e6d6e64e12aca17657581a48005d1?s=40&d=https%3A%2F%2Ftravis-ci.org%2Fimages%2Fui%2Fdefault-avatar.png', 'correctly sets gravatar image'); - return equal(model.get('committerAvatarUrlOrGravatar'), 'https://www.gravatar.com/avatar/5c1e6d6e64e12aca17657581a48005d1?s=40&d=https%3A%2F%2Ftravis-ci.org%2Fimages%2Fui%2Fdefault-avatar.png', 'correctly sets gravatar image'); + equal(model.get('authorAvatarUrlOrGravatar'), 'https://www.gravatar.com/avatar/5c1e6d6e64e12aca17657581a48005d1?s=40&d=blank', 'correctly sets gravatar image'); + return equal(model.get('committerAvatarUrlOrGravatar'), 'https://www.gravatar.com/avatar/5c1e6d6e64e12aca17657581a48005d1?s=40&d=blank', 'correctly sets gravatar image'); }); test('calculation of avatar urls via overriding parameter', function() { From d82ff4935956703cef56283646a8fd139425441f Mon Sep 17 00:00:00 2001 From: Lisa P Date: Tue, 26 Jan 2016 14:50:58 +0100 Subject: [PATCH 2/4] change component implementation --- app/components/user-avatar.js | 19 +-------- app/templates/components/build-header.hbs | 4 +- app/templates/components/builds-item.hbs | 2 +- app/templates/components/org-item.hbs | 2 +- app/templates/components/user-avatar.hbs | 4 +- app/templates/top.hbs | 2 +- tests/unit/components/user-avatar-test.js | 50 +++-------------------- 7 files changed, 14 insertions(+), 69 deletions(-) diff --git a/app/components/user-avatar.js b/app/components/user-avatar.js index 4013db9f..2c2efde2 100644 --- a/app/components/user-avatar.js +++ b/app/components/user-avatar.js @@ -7,25 +7,8 @@ export default Ember.Component.extend({ tagName: 'span', classNames: ['avatar'], - gravatarUrl: function() { - if (!this.get('isAuthor') && !this.get('isComitter')) { - if (this.get('user.type') === 'organization') { - return this.get('user.avatarUrl'); - } else { - return gravatarImage(this.get('user.email'), 36); - } - } else { - if (this.get('isAuthor')) { - return this.user.get('authorAvatarUrlOrGravatar'); - } else if (this.get('isCommitter')) { - return this.user.get('committerAvatarUrlorGravatar'); - } - } - }.property('gravatarUrl'), - userInitials: function() { - var name = this.get('user.name') || this.get('user.login') || - this.get('user.authorName') || this.get('user.committerName'); + var name = this.get('name'); var arr = name.split(' '); var initials; diff --git a/app/templates/components/build-header.hbs b/app/templates/components/build-header.hbs index d03f3f99..9be21c8b 100644 --- a/app/templates/components/build-header.hbs +++ b/app/templates/components/build-header.hbs @@ -38,12 +38,12 @@

{{#if commit.authorName}} - {{user-avatar user=commit isAuthor=true}} + {{user-avatar url=commit.authorAvatarUrlOrGravatar name=commit.authorName}} {{commit.authorName}} authored{{#if commit.authorIsCommitter}} and committed{{/if}} {{/if}} {{#unless commit.authorIsCommitter}} {{#if commit.committerName}} - {{user-avatar user=commit isComitter=true}} + {{user-avatar url=commit.committerAvatarUrlOrGravatar name=commit.committerName}} {{commit.committerName}} committed {{/if}} {{/unless}} diff --git a/app/templates/components/builds-item.hbs b/app/templates/components/builds-item.hbs index 7e38b4d5..9af01af9 100644 --- a/app/templates/components/builds-item.hbs +++ b/app/templates/components/builds-item.hbs @@ -20,7 +20,7 @@ {{/unless}}

- {{user-avatar user=build.commit isAuthor=true}} + {{user-avatar url=build.commit.authorAvatarUrlOrGravatar name=build.commit.authorName}} {{build.commit.authorName}}
diff --git a/app/templates/components/org-item.hbs b/app/templates/components/org-item.hbs index 4aba50c0..73fd8a87 100644 --- a/app/templates/components/org-item.hbs +++ b/app/templates/components/org-item.hbs @@ -1,5 +1,5 @@
- {{user-avatar user=account}} + {{user-avatar url=account.avatarUrl name=name}}
{{#link-to "account" account.login}} diff --git a/app/templates/components/user-avatar.hbs b/app/templates/components/user-avatar.hbs index 77a3a0f9..ce49589c 100644 --- a/app/templates/components/user-avatar.hbs +++ b/app/templates/components/user-avatar.hbs @@ -1,2 +1,4 @@ -avatar +{{#if url}} +avatar +{{/if}} diff --git a/app/templates/top.hbs b/app/templates/top.hbs index 87a6e78f..c5df2481 100644 --- a/app/templates/top.hbs +++ b/app/templates/top.hbs @@ -58,7 +58,7 @@ {{#if auth.signedIn}} {{#link-to "profile" class="navigation-anchor signed-in"}} {{userName}} - {{user-avatar user=user}} + {{user-avatar url=user.avatarUrl name=user.fullName}} {{/link-to}} {{/if}} {{#if auth.signingIn}} diff --git a/tests/unit/components/user-avatar-test.js b/tests/unit/components/user-avatar-test.js index 06ca4396..bd575f34 100644 --- a/tests/unit/components/user-avatar-test.js +++ b/tests/unit/components/user-avatar-test.js @@ -7,55 +7,15 @@ moduleForComponent('user-avatar', 'UserAvatarComponent | Unit', { }); test('it renders', function() { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... });" - var attributes = { - type: 'organization', - login: 'testuser', - name: 'Test User', - avatarUrl: 'https://0.gravatar.com/avatar/595cf623f3cde2fa64fc784884c4bfec' - }; + var name = "Hello Test"; + var url = "https://someurl.com/someimage.jpg"; - var org = Ember.Object.create(attributes); - var component = this.subject({user: org}); + var component = this.subject({url: url, name: name}); this.append(); ok(component.$().hasClass('avatar'), 'component should have right class'); - equal(component.$('.pseudo-avatar').data('initials'), 'TU', 'initials should be correct'); - equal(component.$('.real-avatar').attr('src'), 'https://0.gravatar.com/avatar/595cf623f3cde2fa64fc784884c4bfec', 'avatar shoudl be right'); - -}); - -test('it handles a missing user name', function() { - - var attr = { - type: 'organization', - login: 'testorg' - }; - - var org = Ember.Object.create(attr); - var component = this.subject({user: org}); - this.append(); - - equal(component.$('.pseudo-avatar').data('initials'), 'T', 'only one letter if there is no name'); - -}); - - -test('can get avatars from commits', function() { - - - var attr = { - authorName: 'This is Author' - }; - - var user = Ember.Object.create(attr); - var component = this.subject({user: user}); - this.append(); - - equal(component.$('.real-avatar').attr('src'), 'https://www.gravatar.com/avatar/5e543256c480ac577d30f76f9120eb74?s=36&d=blank', 'get the right avatar url'); - - equal(component.$('.pseudo-avatar').data('initials'), 'TI', 'gets right initials'); + equal(component.$('.pseudo-avatar').data('initials'), 'HT', 'initials should be correct'); + equal(component.$('.real-avatar').attr('src'), 'https://someurl.com/someimage.jpg', 'avatar should be right'); }); From 5d74d57ac65e2639af3b90891b11ea4354b065e3 Mon Sep 17 00:00:00 2001 From: Lisa P Date: Tue, 26 Jan 2016 18:40:03 +0100 Subject: [PATCH 3/4] add avatarUrl propertuy to user model --- app/components/user-avatar.js | 2 -- app/models/user.js | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/components/user-avatar.js b/app/components/user-avatar.js index 2c2efde2..f37d9f93 100644 --- a/app/components/user-avatar.js +++ b/app/components/user-avatar.js @@ -1,6 +1,4 @@ import Ember from 'ember'; -import config from 'travis/config/environment'; -import {gravatarImage} from '../utils/urls'; export default Ember.Component.extend({ diff --git a/app/models/user.js b/app/models/user.js index 294b5549..3f659cd8 100644 --- a/app/models/user.js +++ b/app/models/user.js @@ -3,6 +3,7 @@ import Model from 'travis/models/model'; import config from 'travis/config/environment'; import attr from 'ember-data/attr'; import { hasMany, belongsTo } from 'ember-data/relationships'; +import {gravatarImage} from '../utils/urls'; export default Model.extend({ ajax: Ember.inject.service(), @@ -132,5 +133,9 @@ export default Model.extend({ user = JSON.parse(this.get('sessionStorage').getItem('travis.user')); user[name.underscore()] = this.get(name); return this.get('sessionStorage').setItem('travis.user', JSON.stringify(user)); - } + }, + + avatarUrl: function() { + return gravatarImage(this.get('email'), 36); + }.property() }); From 22c938489e6d2b2651445a23d11ca3eb013a37f8 Mon Sep 17 00:00:00 2001 From: Lisa P Date: Wed, 27 Jan 2016 13:01:11 +0100 Subject: [PATCH 4/4] make gravatar depend on email --- app/models/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.js b/app/models/user.js index 3f659cd8..1954cde7 100644 --- a/app/models/user.js +++ b/app/models/user.js @@ -137,5 +137,5 @@ export default Model.extend({ avatarUrl: function() { return gravatarImage(this.get('email'), 36); - }.property() + }.property('email') });