FIX: Small actions should show descriptions on the user stream
This commit is contained in:
parent
d71301e406
commit
cf91bca0cd
|
@ -13,27 +13,22 @@ const icons = {
|
|||
'visible.disabled': 'eye-slash'
|
||||
};
|
||||
|
||||
export function actionDescription(actionCode, createdAt) {
|
||||
return function() {
|
||||
const ac = this.get(actionCode);
|
||||
if (actionCode) {
|
||||
const dt = new Date(this.get(createdAt));
|
||||
const when = Discourse.Formatter.relativeAge(dt, {format: 'medium-with-ago'});
|
||||
return I18n.t(`action_codes.${ac}`, {when}).htmlSafe();
|
||||
}
|
||||
}.property(actionCode, createdAt);
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
layoutName: 'components/small-action', // needed because `time-gap` inherits from this
|
||||
classNames: ['small-action'],
|
||||
|
||||
description: function() {
|
||||
const actionCode = this.get('actionCode');
|
||||
if (actionCode) {
|
||||
const dt = new Date(this.get('post.created_at'));
|
||||
const when = Discourse.Formatter.relativeAge(dt, {format: 'medium-with-ago'});
|
||||
var result = I18n.t(`action_codes.${actionCode}`, {when});
|
||||
var cooked = this.get('post.cooked');
|
||||
|
||||
result = "<p>" + result + "</p>";
|
||||
|
||||
if (!Em.isEmpty(cooked)) {
|
||||
result += "<div class='custom-message'>" + cooked + "</div>";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}.property('actionCode', 'post.created_at', 'post.cooked'),
|
||||
description: actionDescription('actionCode', 'post.created_at'),
|
||||
|
||||
icon: function() {
|
||||
return icons[this.get('actionCode')] || 'exclamation';
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import { actionDescription } from 'discourse/components/small-action';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNameBindings: [':item', 'item.hidden', 'item.deleted', 'moderatorAction'],
|
||||
moderatorAction: Discourse.computed.propertyEqual('item.post_type', 'site.post_types.moderator_action'),
|
||||
actionDescription: actionDescription('item.action_code', 'item.created_at')
|
||||
});
|
|
@ -5,7 +5,7 @@ export default Ember.ObjectController.extend({
|
|||
_showFooter: function() {
|
||||
var showFooter;
|
||||
if (this.get("userActionType")) {
|
||||
var stat = _.find(this.get("model.stats"), { action_type: this.get("userActionType") });
|
||||
const stat = _.find(this.get("model.stats"), { action_type: this.get("userActionType") });
|
||||
showFooter = stat && stat.count <= this.get("model.stream.itemsLoaded");
|
||||
} else {
|
||||
showFooter = this.get("model.statsCountNonPM") <= this.get("model.stream.itemsLoaded");
|
||||
|
|
|
@ -11,5 +11,8 @@
|
|||
{{avatar post imageSize="small"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
{{{description}}}
|
||||
<p>{{description}}</p>
|
||||
{{#if post.cooked}}
|
||||
<div class='custom-message'>{{{post.cooked}}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<div class='clearfix info'>
|
||||
<a href={{item.userUrl}} data-user-card={{item.username}} class='avatar-link'><div class='avatar-wrapper'>{{avatar item imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
<span class='time'>{{format-date item.created_at}}</span>
|
||||
{{topic-status topic=item disableActions=true}}
|
||||
<span class="title">
|
||||
<a href={{item.postUrl}}>{{{item.title}}}</a>
|
||||
</span>
|
||||
<div class="category">{{category-link item.category}}</div>
|
||||
</div>
|
||||
|
||||
{{#if actionDescription}}
|
||||
<p class='excerpt'>{{actionDescription}}</p>
|
||||
{{/if}}
|
||||
|
||||
<p class='excerpt'>{{{item.excerpt}}}</p>
|
||||
|
||||
|
||||
{{#each item.children as |child|}}
|
||||
<div class='child-actions'>
|
||||
<i class="icon {{child.icon}}"></i>
|
||||
{{#each child.items as |grandChild|}}
|
||||
{{#if grandChild.removableBookmark}}
|
||||
<button class="btn btn-default remove-bookmark" {{action "removeBookmark" grandChild}}>
|
||||
{{fa-icon 'times'}} {{i18n "bookmarks.remove"}}
|
||||
</button>
|
||||
{{else}}
|
||||
<a href={{grandChild.userUrl}} data-user-card={{grandChild.username}} class='avatar-link'><div class='avatar-wrapper'>{{avatar grandChild imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
{{#if grandChild.edit_reason}} — <span class="edit-reason">{{grandChild.edit_reason}}</span>{{/if}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
|
@ -1,29 +1,3 @@
|
|||
{{#each item in model.content}}
|
||||
<div {{bind-attr class=":item item.hidden item.deleted item.moderator_action"}}>
|
||||
<div class='clearfix info'>
|
||||
<a href="{{unbound item.userUrl}}" data-user-card="{{unbound item.username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar item imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
<span class='time'>{{format-date item.created_at}}</span>
|
||||
{{topic-status topic=item disableActions=true}}
|
||||
<span class="title">
|
||||
<a href="{{unbound item.postUrl}}">{{{unbound item.title}}}</a>
|
||||
</span>
|
||||
<div class="category">{{category-link item.category}}</div>
|
||||
</div>
|
||||
<p class='excerpt'>{{{unbound item.excerpt}}}</p>
|
||||
{{#each child in item.children}}
|
||||
<div class='child-actions'>
|
||||
<i class="icon {{unbound child.icon}}"></i>
|
||||
{{#each grandChild in child.items}}
|
||||
{{#if grandChild.removableBookmark}}
|
||||
<button class="btn btn-default remove-bookmark" {{action "removeBookmark" grandChild}}>
|
||||
{{fa-icon 'times'}} {{i18n "bookmarks.remove"}}
|
||||
</button>
|
||||
{{else}}
|
||||
<a href="{{unbound grandChild.userUrl}}" data-user-card="{{unbound grandChild.username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar grandChild imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
{{#if grandChild.edit_reason}} — <span class="edit-reason">{{unbound grandChild.edit_reason}}</span>{{/if}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#each model.content as |item|}}
|
||||
{{stream-item item=item}}
|
||||
{{/each}}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import LoadMore from "discourse/mixins/load-more";
|
||||
|
||||
export default Ember.View.extend(LoadMore, {
|
||||
loading: false,
|
||||
eyelineSelector: '.user-stream .item',
|
||||
classNames: ['user-stream'],
|
||||
|
||||
_scrollTopOnModelChange: function() {
|
||||
Em.run.schedule('afterRender', function() {
|
||||
$(document).scrollTop(0);
|
||||
});
|
||||
}.observes('controller.model.user.id'),
|
||||
|
||||
actions: {
|
||||
loadMore() {
|
||||
const self = this;
|
||||
if (this.get('loading')) { return; }
|
||||
|
||||
this.set('loading', true);
|
||||
const stream = this.get('controller.model');
|
||||
stream.findItems().then(function() {
|
||||
self.set('loading', false);
|
||||
self.get('eyeline').flushRest();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -12,12 +12,12 @@ export default Ember.View.extend(LoadMore, {
|
|||
}.observes('controller.model.user.id'),
|
||||
|
||||
actions: {
|
||||
loadMore: function() {
|
||||
var self = this;
|
||||
loadMore() {
|
||||
const self = this;
|
||||
if (this.get('loading')) { return; }
|
||||
|
||||
this.set('loading', true);
|
||||
var stream = this.get('controller.model');
|
||||
const stream = this.get('controller.model');
|
||||
stream.findItems().then(function() {
|
||||
self.set('loading', false);
|
||||
self.get('eyeline').flushRest();
|
||||
|
|
|
@ -24,7 +24,7 @@ class UserActionsController < ApplicationController
|
|||
UserAction.stream(opts)
|
||||
end
|
||||
|
||||
render_serialized(stream, UserActionSerializer, root: "user_actions")
|
||||
render_serialized(stream, UserActionSerializer, root: 'user_actions')
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -154,6 +154,7 @@ SQL
|
|||
CASE WHEN coalesce(p.deleted_at, p2.deleted_at, t.deleted_at) IS NULL THEN false ELSE true END deleted,
|
||||
p.hidden,
|
||||
p.post_type,
|
||||
p.action_code,
|
||||
p.edit_reason,
|
||||
t.category_id
|
||||
FROM user_actions as a
|
||||
|
|
|
@ -29,11 +29,11 @@ class UserActionObserver < ActiveRecord::Observer
|
|||
return unless action && post && user && post.id
|
||||
|
||||
row = {
|
||||
action_type: action,
|
||||
user_id: user.id,
|
||||
acting_user_id: acting_user_id || post.user_id,
|
||||
target_topic_id: post.topic_id,
|
||||
target_post_id: post.id
|
||||
action_type: action,
|
||||
user_id: user.id,
|
||||
acting_user_id: acting_user_id || post.user_id,
|
||||
target_topic_id: post.topic_id,
|
||||
target_post_id: post.id
|
||||
}
|
||||
|
||||
if post.deleted_at.nil?
|
||||
|
@ -48,12 +48,12 @@ class UserActionObserver < ActiveRecord::Observer
|
|||
return if model.is_first_post?
|
||||
|
||||
row = {
|
||||
action_type: UserAction::REPLY,
|
||||
user_id: model.user_id,
|
||||
acting_user_id: model.user_id,
|
||||
target_post_id: model.id,
|
||||
target_topic_id: model.topic_id,
|
||||
created_at: model.created_at
|
||||
action_type: UserAction::REPLY,
|
||||
user_id: model.user_id,
|
||||
acting_user_id: model.user_id,
|
||||
target_post_id: model.id,
|
||||
target_topic_id: model.topic_id,
|
||||
created_at: model.created_at
|
||||
}
|
||||
|
||||
rows = [row]
|
||||
|
@ -79,12 +79,12 @@ class UserActionObserver < ActiveRecord::Observer
|
|||
|
||||
def log_topic(model)
|
||||
row = {
|
||||
action_type: model.archetype == Archetype.private_message ? UserAction::NEW_PRIVATE_MESSAGE : UserAction::NEW_TOPIC,
|
||||
user_id: model.user_id,
|
||||
acting_user_id: model.user_id,
|
||||
target_topic_id: model.id,
|
||||
target_post_id: -1,
|
||||
created_at: model.created_at
|
||||
action_type: model.archetype == Archetype.private_message ? UserAction::NEW_PRIVATE_MESSAGE : UserAction::NEW_TOPIC,
|
||||
user_id: model.user_id,
|
||||
acting_user_id: model.user_id,
|
||||
target_topic_id: model.id,
|
||||
target_post_id: -1,
|
||||
created_at: model.created_at
|
||||
}
|
||||
|
||||
rows = [row]
|
||||
|
|
|
@ -22,7 +22,8 @@ class UserActionSerializer < ApplicationSerializer
|
|||
:title,
|
||||
:deleted,
|
||||
:hidden,
|
||||
:moderator_action,
|
||||
:post_type,
|
||||
:action_code,
|
||||
:edit_reason,
|
||||
:category_id,
|
||||
:uploaded_avatar_id,
|
||||
|
@ -32,7 +33,7 @@ class UserActionSerializer < ApplicationSerializer
|
|||
|
||||
def excerpt
|
||||
cooked = object.cooked || PrettyText.cook(object.raw)
|
||||
PrettyText.excerpt(cooked, 300, { keep_emojis: true }) if cooked
|
||||
PrettyText.excerpt(cooked, 300, keep_emojis: true) if cooked
|
||||
end
|
||||
|
||||
def avatar_template
|
||||
|
@ -67,10 +68,6 @@ class UserActionSerializer < ApplicationSerializer
|
|||
object.title.present?
|
||||
end
|
||||
|
||||
def moderator_action
|
||||
object.post_type == Post.types[:moderator_action] || object.post_type == Post.types[:small_action]
|
||||
end
|
||||
|
||||
def include_reply_to_post_number?
|
||||
object.action_type == UserAction::REPLY
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue