Refactor flagged posts into components

This commit is contained in:
Robin Ward 2017-09-08 16:27:07 -04:00
parent 40eba8cd93
commit be0eb0a554
11 changed files with 241 additions and 193 deletions

View File

@ -0,0 +1,36 @@
import showModal from 'discourse/lib/show-modal';
export default Ember.Component.extend({
tagName: '',
removeAfter(promise) {
return promise.then(() => {
this.attrs.removePost();
}).catch(() => {
bootbox.alert(I18n.t("admin.flags.error"));
});
},
_spawnModal(name, model, modalClass) {
let controller = showModal(name, { model, admin: true, modalClass });
controller.removeAfter = (p) => this.removeAfter(p);
},
actions: {
showAgreeFlagModal() {
this._spawnModal('admin-agree-flag', this.get('flaggedPost'), 'agree-flag-modal');
},
showDeleteFlagModal() {
this._spawnModal('admin-delete-flag', this.get('flaggedPost'), 'delete-flag-modal');
},
disagree() {
this.removeAfter(this.get('flaggedPost').disagreeFlags());
},
defer() {
this.removeAfter(this.get('flaggedPost').deferFlags());
}
}
});

View File

@ -5,7 +5,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
_agreeFlag(action) {
let flaggedPost = this.get('model');
return this.removeAfter(flaggedPost.agreeFlags(action), flaggedPost).then(() => {
return this.removeAfter(flaggedPost.agreeFlags(action)).then(() => {
this.send('closeModal');
});
},

View File

@ -6,14 +6,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
actions: {
deletePostDeferFlag() {
let flaggedPost = this.get('model');
this.removeAfter(flaggedPost.deferFlags(true), flaggedPost).then(() => {
this.removeAfter(flaggedPost.deferFlags(true)).then(() => {
this.send('closeModal');
});
},
deletePostAgreeFlag() {
let flaggedPost = this.get('model');
this.removeAfter(flaggedPost.agreeFlags('delete'), flaggedPost).then(() => {
this.removeAfter(flaggedPost.agreeFlags('delete')).then(() => {
this.send('closeModal');
});
}

View File

@ -27,7 +27,7 @@ const FlaggedPost = Post.extend({
disposedAt: postAction.disposed_at,
dispositionIcon: this.dispositionIcon(postAction.disposition),
tookAction: postAction.staff_took_action
}
};
});
},
@ -144,25 +144,31 @@ const FlaggedPost = Post.extend({
});
FlaggedPost.reopenClass({
findAll(args) {
let { offset, filter } = args;
offset = offset || 0;
let { filter } = args;
let result = [];
result.set('loading', true);
return ajax('/admin/flags/' + filter + '.json?offset=' + offset).then(function (data) {
let data = {};
if (args.topic_id) {
data.topic_id = args.topic_id;
}
if (args.offset) {
data.offset = args.offset;
}
return ajax(`/admin/flags/${filter}.json`, { data }).then(response => {
// users
let userLookup = {};
data.users.forEach(user => userLookup[user.id] = AdminUser.create(user));
response.users.forEach(user => userLookup[user.id] = AdminUser.create(user));
// topics
let topicLookup = {};
data.topics.forEach(topic => topicLookup[topic.id] = Topic.create(topic));
response.topics.forEach(topic => topicLookup[topic.id] = Topic.create(topic));
// posts
data.posts.forEach(post => {
response.posts.forEach(post => {
let f = FlaggedPost.create(post);
f.userLookup = userLookup;
f.topicLookup = topicLookup;

View File

@ -2,6 +2,6 @@ import FlaggedPost from 'admin/models/flagged-post';
export default Discourse.Route.extend({
model() {
return FlaggedPost.findAll('active');
return FlaggedPost.findAll({ filter: 'active' });
}
});

View File

@ -2,6 +2,6 @@ import FlaggedPost from 'admin/models/flagged-post';
export default Discourse.Route.extend({
model() {
return FlaggedPost.findAll('old');
return FlaggedPost.findAll({ filter: 'old' });
},
});

View File

@ -8,7 +8,10 @@ export default Ember.Route.extend({
return Ember.RSVP.hash({
topic,
flaggedPosts: FlaggedPost.findAll({ filter: 'active' })
flaggedPosts: FlaggedPost.findAll({
filter: 'active',
topic_id: params.id
})
});
},

View File

@ -0,0 +1,169 @@
<tr class="flagged-post {{flaggedPost.extraClasses}}">
<td class='excerpt'>
<div class="flex-center-align">
<div class="flagged-post-avatar">
{{#if flaggedPost.postAuthorFlagged}}
{{#if flaggedPost.user}}
{{#link-to 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="large"}}{{/link-to}}
{{#if flaggedPost.wasEdited}}
{{d-icon "pencil" title="admin.flags.was_edited"}}
{{/if}}
{{/if}}
{{/if}}
{{#if canAct}}
{{#if flaggedPost.previous_flags_count}}
<span title="{{i18n 'admin.flags.previous_flags_count' count=flaggedPost.previous_flags_count}}" class="badge-notification flagged-posts">{{flaggedPost.previous_flags_count}}</span>
{{/if}}
{{/if}}
</div>
<div class="topic-excerpt">
<h3>
{{#if flaggedPost.topic.isPrivateMessage}}
<span class="private-message-glyph">{{d-icon "envelope"}}</span>
{{/if}}
{{topic-status topic=flaggedPost.topic}}
<a href='{{unbound flaggedPost.url}}'>{{{unbound flaggedPost.topic.fancyTitle}}}</a>
</h3>
{{#unless site.mobileView}}
{{#if flaggedPost.postAuthorFlagged}}
<p>{{{flaggedPost.excerpt}}}</p>
{{/if}}
{{/unless}}
</div>
</div>
{{#if site.mobileView}}
{{#if flaggedPost.postAuthorFlagged}}
<p>{{{flaggedPost.excerpt}}}</p>
{{/if}}
{{/if}}
</td>
<td class='flaggers'>
<table>
<tbody>
{{#each flaggedPost.flaggers as |flagger|}}
<tr>
<td class='avatar'>
{{#link-to 'adminUser' flagger.user}}
{{avatar flagger.user imageSize="medium"}}
{{/link-to}}
</td>
<td>
{{#link-to 'adminUser' flagger.user}}
{{flagger.user.username}}
{{/link-to}}
{{format-age flagger.flaggedAt}}
<br>
{{flagger.flagType}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</td>
<td class='flaggers result'>
{{#if showResolvedBy}}
<table>
<tbody>
{{#each flaggedPost.flaggers as |flagger|}}
<tr>
<td class='avatar'>
{{#link-to 'adminUser' flagger.disposedBy}}
{{avatar flagger.disposedBy imageSize="medium"}}
{{/link-to}}
</td>
<td>
{{format-age flagger.disposedAt}}
{{{flagger.dispositionIcon}}}
{{#if flagger.tookAction}}
{{d-icon "gavel" title="admin.flags.took_action"}}
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{/if}}
</td>
</tr>
{{#if flaggedPost.topicFlagged}}
<tr class='message'>
<td colspan="3">
<div>
{{{i18n 'admin.flags.topic_flagged'}}}&nbsp;<a href='{{unbound flaggedPost.url}}' class="btn">{{i18n 'admin.flags.visit_topic'}}</a>
</div>
</td>
</tr>
{{/if}}
{{#each flaggedPost.conversations as |c|}}
<tr class='message'>
<td colspan="3">
<div>
{{#if c.response}}
<p>
{{#link-to 'adminUser' c.response.user}}{{avatar c.response.user imageSize="medium"}}{{/link-to}}&nbsp;{{{c.response.excerpt}}}
</p>
{{#if c.reply}}
<p>
{{#link-to 'adminUser' c.reply.user}}{{avatar c.reply.user imageSize="medium"}}{{/link-to}}&nbsp;{{{c.reply.excerpt}}}
{{#if c.hasMore}}
<a href="{{unbound c.permalink}}">{{i18n 'admin.flags.more'}}</a>
{{/if}}
</p>
{{/if}}
<a href="{{unbound c.permalink}}">
{{d-button
class="btn-reply"
icon="reply"
label="admin.flags.reply_message"}}
</a>
{{/if}}
</div>
</td>
</tr>
{{/each}}
{{#if canAct}}
<tr>
<td colspan="3" class="action">
{{d-button
title="admin.flags.agree_title"
label="admin.flags.agree"
icon="thumbs-o-up"
action="showAgreeFlagModal"
ellipsis=true}}
{{#if flaggedPost.postHidden}}
{{d-button
title="admin.flags.disagree_flag_unhide_post_title"
action="disagree"
icon="thumbs-o-down"
label="admin.flags.disagree_flag_unhide_post"}}
{{else}}
{{d-button
title="admin.flags.disagree_flag_title"
action="disagree"
icon="thumbs-o-down"
label="admin.flags.disagree_flag"}}
{{/if}}
{{d-button
title="admin.flags.defer_flag_title"
action="defer"
icon="external-link"
label="admin.flags.defer_flag"}}
{{d-button
class="btn-danger"
title="admin.flags.delete_title"
action="showDeleteFlagModal"
icon="trash-o"
label="admin.flags.delete"}}
</td>
</tr>
{{/if}}

View File

@ -10,157 +10,17 @@
</thead>
<tbody>
{{#each flaggedPosts as |flaggedPost|}}
<tr class="flagged-post {{flaggedPost.extraClasses}}">
<td class='excerpt'>
<div class="flex-center-align">
<div class="flagged-post-avatar">
{{#if flaggedPost.postAuthorFlagged}}
{{#if flaggedPost.user}}
{{#link-to 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="large"}}{{/link-to}}
{{#if flaggedPost.wasEdited}}
{{d-icon "pencil" title="admin.flags.was_edited"}}
{{/if}}
{{/if}}
{{/if}}
{{#if canAct}}
{{#if flaggedPost.previous_flags_count}}
<span title="{{i18n 'admin.flags.previous_flags_count' count=flaggedPost.previous_flags_count}}" class="badge-notification flagged-posts">{{flaggedPost.previous_flags_count}}</span>
{{/if}}
{{/if}}
</div>
<div class="topic-excerpt">
<h3>
{{#if flaggedPost.topic.isPrivateMessage}}
<span class="private-message-glyph">{{d-icon "envelope"}}</span>
{{/if}}
{{topic-status topic=flaggedPost.topic}}
<a href='{{unbound flaggedPost.url}}'>{{{unbound flaggedPost.topic.fancyTitle}}}</a>
</h3>
{{#unless site.mobileView}}
{{#if flaggedPost.postAuthorFlagged}}
<p>{{{flaggedPost.excerpt}}}</p>
{{/if}}
{{/unless}}
</div>
</div>
{{#if site.mobileView}}
{{#if flaggedPost.postAuthorFlagged}}
<p>{{{flaggedPost.excerpt}}}</p>
{{/if}}
{{/if}}
</td>
<td class='flaggers'>
<table>
<tbody>
{{#each flaggedPost.flaggers as |flagger|}}
<tr>
<td class='avatar'>
{{#link-to 'adminUser' flagger.user}}
{{avatar flagger.user imageSize="medium"}}
{{/link-to}}
</td>
<td>
{{#link-to 'adminUser' flagger.user}}
{{flagger.user.username}}
{{/link-to}}
{{format-age flagger.flaggedAt}}
<br>
{{flagger.flagType}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</td>
<td class='flaggers result'>
{{#if showResolvedBy}}
<table>
<tbody>
{{#each flaggedPost.flaggers as |flagger|}}
<tr>
<td class='avatar'>
{{#link-to 'adminUser' flagger.disposedBy}}
{{avatar flagger.disposedBy imageSize="medium"}}
{{/link-to}}
</td>
<td>
{{format-age flagger.disposedAt}}
{{{flagger.dispositionIcon}}}
{{#if flagger.tookAction}}
{{d-icon "gavel" title="admin.flags.took_action"}}
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{/if}}
</td>
</tr>
{{#if flaggedPost.topicFlagged}}
<tr class='message'>
<td colspan="3">
<div>
{{{i18n 'admin.flags.topic_flagged'}}}&nbsp;<a href='{{unbound flaggedPost.url}}' class="btn">{{i18n 'admin.flags.visit_topic'}}</a>
</div>
</td>
</tr>
{{/if}}
{{#each flaggedPost.conversations as |c|}}
<tr class='message'>
<td colspan="3">
<div>
{{#if c.response}}
<p>
{{#link-to 'adminUser' c.response.user}}{{avatar c.response.user imageSize="medium"}}{{/link-to}}&nbsp;{{{c.response.excerpt}}}
</p>
{{#if c.reply}}
<p>
{{#link-to 'adminUser' c.reply.user}}{{avatar c.reply.user imageSize="medium"}}{{/link-to}}&nbsp;{{{c.reply.excerpt}}}
{{#if c.hasMore}}
<a href="{{unbound c.permalink}}">{{i18n 'admin.flags.more'}}</a>
{{/if}}
</p>
{{/if}}
<a href="{{unbound c.permalink}}">
<button class='btn btn-reply'>{{d-icon "reply"}}&nbsp;{{i18n 'admin.flags.reply_message'}}</button>
</a>
{{/if}}
</div>
</td>
</tr>
{{/each}}
{{#if canAct}}
<tr>
<td colspan="3" class="action">
<button title='{{i18n 'admin.flags.agree_title'}}' class='btn' {{action "showAgreeFlagModal" flaggedPost}}>{{d-icon "thumbs-o-up"}}{{i18n 'admin.flags.agree'}}&hellip;</button>
{{#if flaggedPost.postHidden}}
<button title='{{i18n 'admin.flags.disagree_flag_unhide_post_title'}}' class='btn' {{action "disagree" flaggedPost}}>{{d-icon "thumbs-o-down"}}{{i18n 'admin.flags.disagree_flag_unhide_post'}}</button>
{{else}}
<button title='{{i18n 'admin.flags.disagree_flag_title'}}' class='btn' {{action "disagree" flaggedPost}}>{{d-icon "thumbs-o-down"}}{{i18n 'admin.flags.disagree_flag'}}</button>
{{/if}}
<button title='{{i18n 'admin.flags.defer_flag_title'}}' class='btn' {{action "defer" flaggedPost}}>{{d-icon "external-link"}}{{i18n 'admin.flags.defer_flag'}}</button>
<button title='{{i18n 'admin.flags.delete_title'}}' class='btn btn-danger' {{action "showDeleteFlagModal" flaggedPost}}>{{d-icon "trash-o"}}{{i18n 'admin.flags.delete'}}&hellip;</button>
</td>
</tr>
{{/if}}
{{flagged-post
flaggedPost=flaggedPost
canAct=canAct
showResolvedBy=showResolvedBy
removePost=(action "removePost" flaggedPost)
}}
{{/each}}
</tbody>
</table>
{{/load-more}}
{{else}}
<p>{{i18n 'admin.flags.no_results'}}</p>
{{/if}}

View File

@ -1,39 +1,20 @@
import FlaggedPost from 'admin/models/flagged-post';
import showModal from 'discourse/lib/show-modal';
export default Ember.Component.extend({
canAct: Ember.computed.equal('filter', 'active'),
showResolvedBy: Ember.computed.equal('filter', 'old'),
removeAfter(promise, flaggedPost) {
return promise.then(() => {
this.get('flaggedPosts').removeObject(flaggedPost);
}).catch(() => {
bootbox.alert(I18n.t("admin.flags.error"));
});
},
_spawnModal(name, flaggedPost, modalClass) {
let controller = showModal(name, {
model: flaggedPost,
admin: true,
modalClass
});
controller.removeAfter = (p, f) => this.removeAfter(p, f);
},
actions: {
disagree(flaggedPost) {
this.removeAfter(flaggedPost.disagreeFlags(), flaggedPost);
},
defer(flaggedPost) {
this.removeAfter(flaggedPost.deferFlags(), flaggedPost);
removePost(flaggedPost) {
this.get('flaggedPosts').removeObject(flaggedPost);
},
loadMore() {
const flaggedPosts = this.get('flaggedPosts');
return FlaggedPost.findAll(this.get('query'), flaggedPosts.length+1).then(data => {
return FlaggedPost.findAll({
filter: this.get('query'),
offset: flaggedPosts.length+1
}).then(data => {
if (data.length===0) {
flaggedPosts.set("allLoaded",true);
}
@ -41,12 +22,5 @@ export default Ember.Component.extend({
});
},
showAgreeFlagModal(flaggedPost) {
this._spawnModal('admin-agree-flag', flaggedPost, 'agree-flag-modal');
},
showDeleteFlagModal(flaggedPost) {
this._spawnModal('admin-delete-flag', flaggedPost, 'delete-flag-modal');
}
}
});

View File

@ -3,7 +3,7 @@
{{/if}}
{{#if translatedLabel}}
<span class='d-button-label'>{{{translatedLabel}}}</span>
<span class='d-button-label'>{{{translatedLabel}}}{{#if ellipsis}}&hellip;{{/if}}</span>
{{/if}}
{{yield}}