UX: Show User popup when clicking on a user in the topic list.

This commit is contained in:
Robin Ward 2014-08-19 16:20:55 -04:00
parent 9c7bc57121
commit b46a373ff9
14 changed files with 110 additions and 66 deletions

View File

@ -110,52 +110,6 @@ Handlebars.registerHelper('shorten-url', function(property, options) {
return url.substring(0,80); return url.substring(0,80);
}); });
/**
Show an avatar for a user, intelligently making use of available properties
@method avatar
@for Handlebars
**/
Handlebars.registerHelper('avatar', function(user, options) {
if (typeof user === 'string') {
user = Ember.Handlebars.get(this, user, options);
}
if (user) {
var username = Em.get(user, 'username');
if (!username) username = Em.get(user, options.hash.usernamePath);
var title;
if (!options.hash.ignoreTitle) {
// first try to get a title
title = Em.get(user, 'title');
// if there was no title provided
if (!title) {
// try to retrieve a description
var description = Em.get(user, 'description');
// if a description has been provided
if (description && description.length > 0) {
// preprend the username before the description
title = username + " - " + description;
}
}
}
// this is simply done to ensure we cache images correctly
var uploadedAvatarId = Em.get(user, 'uploaded_avatar_id') || Em.get(user, 'user.uploaded_avatar_id');
var avatarTemplate = Discourse.User.avatarTemplate(username,uploadedAvatarId);
return new safe(Discourse.Utilities.avatarImg({
size: options.hash.imageSize,
extraClasses: Em.get(user, 'extras') || options.hash.extraClasses,
title: title || username,
avatarTemplate: avatarTemplate
}));
} else {
return '';
}
});
/** /**
Bound avatar helper. Bound avatar helper.

View File

@ -0,0 +1,45 @@
export function renderAvatar(user, options) {
options = options || {};
if (typeof user === 'string') {
user = Ember.Handlebars.get(this, user, options);
}
if (user) {
var username = Em.get(user, 'username');
if (!username) username = Em.get(user, options.usernamePath);
var title;
if (!options.ignoreTitle) {
// first try to get a title
title = Em.get(user, 'title');
// if there was no title provided
if (!title) {
// try to retrieve a description
var description = Em.get(user, 'description');
// if a description has been provided
if (description && description.length > 0) {
// preprend the username before the description
title = username + " - " + description;
}
}
}
// this is simply done to ensure we cache images correctly
var uploadedAvatarId = Em.get(user, 'uploaded_avatar_id') || Em.get(user, 'user.uploaded_avatar_id');
var avatarTemplate = Discourse.User.avatarTemplate(username,uploadedAvatarId);
return Discourse.Utilities.avatarImg({
size: options.imageSize,
extraClasses: Em.get(user, 'extras') || options.extraClasses,
title: title || username,
avatarTemplate: avatarTemplate
});
} else {
return '';
}
}
Handlebars.registerHelper('avatar', function(user, options) {
return new Handlebars.SafeString(renderAvatar.call(this, user, options.hash));
});

View File

@ -0,0 +1,12 @@
export default {
name: 'load-all-helpers',
initialize: function() {
Ember.keys(requirejs.entries).forEach(function(entry) {
if ((/\/helpers\//).test(entry)) {
require(entry, null, null, true);
}
});
}
};

View File

@ -5,6 +5,18 @@ var ApplicationRoute = Em.Route.extend({
this.controllerFor('topic-entrance').send('show', data); this.controllerFor('topic-entrance').send('show', data);
}, },
composePrivateMessage: function(user) {
var self = this;
this.transitionTo('userActivity', user).then(function () {
self.controllerFor('user-activity').send('composePrivateMessage');
});
},
expandUser: function(user) {
this.controllerFor('poster-expansion').show(user.get('username'), user.get('uploaded_avatar_id'));
return true;
},
error: function(err, transition) { error: function(err, transition) {
if (err.status === 404) { if (err.status === 404) {
// 404 // 404

View File

@ -25,13 +25,6 @@ Discourse.TopicRoute = Discourse.Route.extend({
} }
}, },
composePrivateMessage: function(user) {
var self = this;
this.transitionTo('userActivity', user).then(function () {
self.controllerFor('user-activity').send('composePrivateMessage');
});
},
showFlags: function(post) { showFlags: function(post) {
Discourse.Route.showModal(this, 'flag', post); Discourse.Route.showModal(this, 'flag', post);
this.controllerFor('flag').setProperties({ selected: null }); this.controllerFor('flag').setProperties({ selected: null });

View File

@ -2,6 +2,7 @@
<div id='main-outlet' {{bind-attr class=backgroundClass}}> <div id='main-outlet' {{bind-attr class=backgroundClass}}>
{{outlet}} {{outlet}}
{{render "poster-expansion"}}
</div> </div>
{{render "modal"}} {{render "modal"}}

View File

@ -40,11 +40,7 @@
<td class='category'>{{bound-category-link category showParent=true}}</td> <td class='category'>{{bound-category-link category showParent=true}}</td>
{{/unless}} {{/unless}}
<td class='posters'> {{view 'posters-column' posters=posters}}
{{#each posters}}
<a href="{{user.path}}" class="{{extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a>
{{/each}}
</td>
{{posts-count-column topic=model class="num"}} {{posts-count-column topic=model class="num"}}
<td {{bind-attr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td> <td {{bind-attr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td>

View File

@ -52,5 +52,4 @@
{{else}} {{else}}
<p class='loading'>{{i18n loading}}</p> <p class='loading'>{{i18n loading}}</p>
{{/if}} {{/if}}
{{/if}} {{/if}}

View File

@ -145,7 +145,6 @@
{{/if}} {{/if}}
{{render "share"}} {{render "share"}}
{{render "posterExpansion"}}
{{#if currentUser.enable_quoting}} {{#if currentUser.enable_quoting}}
{{render "quote-button"}} {{render "quote-button"}}

View File

@ -7,6 +7,7 @@ export default Discourse.View.extend({
_setup: function() { _setup: function() {
var self = this; var self = this;
this.appEvents.on('poster:expand', this, '_posterExpand'); this.appEvents.on('poster:expand', this, '_posterExpand');
this.appEvents.on('dom:clean', this, '_cleanUp');
$('html').off(clickOutsideEventName).on(clickOutsideEventName, function(e) { $('html').off(clickOutsideEventName).on(clickOutsideEventName, function(e) {
if (self.get('controller.visible')) { if (self.get('controller.visible')) {
@ -42,9 +43,14 @@ export default Discourse.View.extend({
}); });
}, },
_cleanUp: function() {
this.get('controller').close();
},
_removeEvents: function() { _removeEvents: function() {
$('html').off(clickOutsideEventName); $('html').off(clickOutsideEventName);
this.appEvents.off('poster:expand', this, '_posterExpand'); this.appEvents.off('poster:expand', this, '_posterExpand');
this.appEvents.off('dom:clean', this, '_cleanUp');
}.on('willDestroyElement') }.on('willDestroyElement')
}); });

View File

@ -0,0 +1,6 @@
export default Ember.CollectionView.extend({
classNames: ['posters'],
tagName: 'td',
content: Em.computed.alias('posters'),
itemViewClass: 'topic-list-poster'
});

View File

@ -0,0 +1,22 @@
import { renderAvatar } from 'discourse/helpers/user-avatar';
export default Ember.View.extend({
tagName: 'a',
attributeBindings: ['href'],
classNameBindings: ['content.extras'],
user: Em.computed.alias('content.user'),
href: Em.computed.alias('user.path'),
click: function(e) {
var user = this.get('user');
this.appEvents.trigger('poster:expand', $(e.target));
this.get('controller').send('expandUser', user);
return false;
},
render: function(buffer) {
var av = renderAvatar(this.get('content'), {usernamePath: 'user.username', imageSize: 'small'});
buffer.push(av);
}
});

View File

@ -9,7 +9,7 @@
margin-top: -2px; margin-top: -2px;
background-color: $secondary; background-color: $secondary;
padding: 12px 12px 5px 12px; padding: 12px 12px 5px 12px;
border: 1px solid scale-color-diff(); border: 1px solid scale-color-diff();
.avatar-placeholder { .avatar-placeholder {
width: 120px; width: 120px;

View File

@ -376,11 +376,10 @@ and (max-width : 850px) {
.topic-excerpt { .topic-excerpt {
padding-right: 20px; padding-right: 20px;
} }
th.posters { th.posters {
text-align: center; text-align: center;
} }
.posters { .posters {
min-width: 0; min-width: 0;
width: 50px; width: 50px;
a:not(.latest) { a:not(.latest) {