FEATURE: add full editing access to queued posts (#5047)

For pending new topics: the body of the post, title, categories
and the tags are editable.

For pending new replies: only the body is applicable and thus
editable

DISCUSSION: https://meta.discourse.org/t/66754
This commit is contained in:
Kyle Zhao 2017-08-15 12:44:05 -04:00 committed by Sam
parent 1146772deb
commit c3249f6e93
6 changed files with 196 additions and 16 deletions

View File

@ -17,10 +17,42 @@ function updateState(state, opts) {
};
}
export default Ember.Component.extend(bufferedProperty('post'), {
export default Ember.Component.extend(bufferedProperty('editables'), {
editing: propertyEqual('post', 'currentlyEditing'),
editables: {},
_confirmDelete: updateState('rejected', {deleteUser: true}),
_initEditables: function() {
const post = this.get('post');
const postOptions = post.get('post_options');
this.set('editables.raw', post.get('raw'));
this.set('editables.category', post.get('category'));
this.set('editables.category_id', post.get('category.id'));
this.set('editables.title', postOptions.title);
this.set('editables.tags', postOptions.tags);
}.on('init'),
_categoryChanged: function() {
this.set('buffered.category', Discourse.Category.findById(this.get('buffered.category_id')));
}.observes('buffered.category_id'),
editTitleAndCategory: function() {
return this.get('editing') && !this.get('post.topic');
}.property('editing'),
tags: function() {
return this.get('editables.tags') || this.get('post.topic.tags') || [];
}.property('editables.tags'),
showTags: function() {
return this.siteSettings.tagging_enabled && !this.get('editing') && this.get('tags').length > 0;
}.property('editing', 'tags'),
editTags: function() {
return this.siteSettings.tagging_enabled && this.get('editing') && !this.get('post.topic');
}.property('editing'),
actions: {
approve: updateState('approved'),
reject: updateState('rejected'),
@ -38,7 +70,14 @@ export default Ember.Component.extend(bufferedProperty('post'), {
},
confirmEdit() {
this.get('post').update({ raw: this.get('buffered.raw') }).then(() => {
const buffered = this.get('buffered');
this.get('post').update(buffered.getProperties(
'raw',
'title',
'tags',
'category_id'
)).then(() => {
this.commitBuffer();
this.set('currentlyEditing', null);
});

View File

@ -20,24 +20,41 @@
</div>
<div class='clearfix'></div>
<span class='post-title'>
{{i18n "queue.topic"}}
{{#if post.topic}}
{{topic-link post.topic}}
{{else}}
{{post.post_options.title}}
{{/if}}
{{category-badge post.category}}
</span>
{{#if editTitleAndCategory}}
<span class="edit-title">
{{text-field value=buffered.title maxlength=siteSettings.max_topic_title_length}}
</span>
{{category-chooser value=buffered.category_id}}
{{else}}
<span class='post-title'>
{{i18n "queue.topic"}}
{{#if post.topic}}
{{topic-link post.topic}}
{{else}}
{{editables.title}}
{{/if}}
{{category-badge editables.category}}
</span>
{{/if}}
<div class='body'>
{{#if editing}}
{{d-editor value=buffered.raw}}
{{else}}
{{cook-text post.raw}}
{{cook-text editables.raw}}
{{/if}}
</div>
{{#if showTags}}
<div class="list-tags">
{{#each tags as |t|}}
{{discourse-tag t}}
{{/each}}
</div>
{{else if editTags}}
{{tag-chooser tags=buffered.tags categoryId=buffered.category_id width='100%'}}
{{/if}}
<div class='queue-controls'>
{{#if editing}}
{{d-button action="confirmEdit"

View File

@ -20,10 +20,17 @@ class QueuedPostsController < ApplicationController
def update
qp = QueuedPost.where(id: params[:id]).first
if params[:queued_post][:raw].present?
qp.update_column(:raw, params[:queued_post][:raw])
update_params = params[:queued_post]
qp.raw = update_params[:raw] if update_params[:raw].present?
unless qp.topic_id
qp.post_options['title'] = update_params[:title] if update_params[:title].present?
qp.post_options['category'] = update_params[:category_id].to_i if update_params[:category_id].present?
qp.post_options['tags'] = update_params[:tags] if update_params[:tags].present?
end
qp.save(validate: false)
state = params[:queued_post][:state]
begin
if state == 'approved'

View File

@ -27,7 +27,7 @@ describe QueuedPostsController do
end
end
context 'update' do
describe '#update' do
let!(:user) { log_in(:moderator) }
let(:qp) { Fabricate(:queued_post) }
@ -43,7 +43,7 @@ describe QueuedPostsController do
end
context 'rejected' do
it 'updates the post to approved' do
it 'updates the post to rejected' do
xhr :put, :update, id: qp.id, queued_post: { state: 'rejected' }
expect(response).to be_success
@ -53,5 +53,66 @@ describe QueuedPostsController do
end
end
context 'editing content' do
let(:changes) do
{
raw: 'new raw',
title: 'new title',
category_id: 10,
tags: ['new_tag']
}
end
context 'when it is a topic' do
let(:queued_topic) { Fabricate(:queued_topic) }
before do
xhr :put, :update, id: queued_topic.id, queued_post: changes
expect(response).to be_success
end
it 'updates raw' do
expect(queued_topic.reload.raw).to eq(changes[:raw])
end
it 'updates the title' do
expect(queued_topic.reload.post_options['title']).to eq(changes[:title])
end
it 'updates the category' do
expect(queued_topic.reload.post_options['category']).to eq(changes[:category_id])
end
it 'updates the tags' do
expect(queued_topic.reload.post_options['tags']).to eq(changes[:tags])
end
end
context 'when it is a reply' do
let(:queued_reply) { Fabricate(:queued_post) }
before do
xhr :put, :update, id: queued_reply.id, queued_post: changes
expect(response).to be_success
end
it 'updates raw' do
expect(queued_reply.reload.raw).to eq(changes[:raw])
end
it 'does not update the title' do
expect(queued_reply.reload.post_options['title']).to be_nil
end
it 'does not update the category' do
original_category = queued_reply.post_options['category']
expect(queued_reply.reload.post_options['category']).to eq(original_category)
end
it 'does not update the tags' do
expect(queued_reply.reload.post_options['tags']).to be_nil
end
end
end
end
end

View File

@ -15,3 +15,12 @@ Fabricator(:queued_post) do
image_sizes: { "http://foo.bar/image.png" => { "width" => 0, "height" => 222 } } }
end
end
Fabricator(:queued_topic, from: :queued_post) do
topic nil
raw 'This post should be queued up, and more importantly, this is a new topic'
post_options do
{ category: 1,
title: 'This is a new topic' }
end
end

View File

@ -0,0 +1,47 @@
import { acceptance } from "helpers/qunit-helpers";
acceptance("Queued Posts", {
loggedIn: true,
settings: { tagging_enabled: true }
});
QUnit.test("For topics: body of post, title, category and tags are all editbale", assert => {
server.get("/queued_posts", () => { //eslint-disable-line no-undef
return [
200,
{"Content-Type": "application/json"},
{"users":[{"id":3,"username":"test_user","avatar_template":"/letter_avatar_proxy/v2/letter/t/eada6e/{size}.png","active":true,"admin":false,"moderator":false,"last_seen_at":"2017-08-11T20:48:05.405Z","last_emailed_at":null,"created_at":"2017-08-07T02:23:33.309Z","last_seen_age":"1d","last_emailed_age":null,"created_at_age":"6d","username_lower":"test_user","trust_level":0,"trust_level_locked":false,"flag_level":0,"title":null,"suspended_at":null,"suspended_till":null,"suspended":null,"blocked":false,"time_read":"19m","staged":false,"days_visited":4,"posts_read_count":12,"topics_entered":6,"post_count":2}],"queued_posts":[{"id":22,"queue":"default","user_id":3,"state":1,"topic_id":null,"approved_by_id":null,"rejected_by_id":null,"raw":"some content","post_options":{"archetype":"regular","category":"1","typing_duration_msecs":"3200","composer_open_duration_msecs":"19007","visible":true,"is_warning":false,"title":"a new topic that needs to be reviewed","ip_address":"172.17.0.1","first_post_checks":true,"is_poll":true},"created_at":"2017-08-11T20:43:41.115Z","category_id":1,"can_delete_user":true}],"__rest_serializer":"1","refresh_queued_posts":"/queued_posts?status=new"}
];
});
visit("/queued-posts");
click(".queued-posts .queued-post button.edit");
andThen(() => {
assert.ok(exists(".d-editor-container"), "the body should be editable");
assert.ok(exists(".edit-title .ember-text-field"), "the title should be editable");
assert.ok(exists(".category-combobox"), "category should be editbale");
assert.ok(exists(".tag-chooser"), "tags should be editable");
});
});
QUnit.test("For replies: only the body of post is editbale", assert => {
server.get("/queued_posts", () => { //eslint-disable-line no-undef
return [
200,
{"Content-Type": "application/json"},
{"users":[{"id":3,"username":"test_user","avatar_template":"/letter_avatar_proxy/v2/letter/t/eada6e/{size}.png","active":true,"admin":false,"moderator":false,"last_seen_at":"2017-08-11T20:48:05.405Z","last_emailed_at":null,"created_at":"2017-08-07T02:23:33.309Z","last_seen_age":"1d","last_emailed_age":null,"created_at_age":"6d","username_lower":"test_user","trust_level":0,"trust_level_locked":false,"flag_level":0,"title":null,"suspended_at":null,"suspended_till":null,"suspended":null,"blocked":false,"time_read":"19m","staged":false,"days_visited":4,"posts_read_count":12,"topics_entered":6,"post_count":2}],"topics":[{"id":11,"title":"This is a topic","fancy_title":"This is a topic","slug":"this-is-a-topic","posts_count":2}],"queued_posts":[{"id":4,"queue":"default","user_id":3,"state":1,"topic_id":11,"approved_by_id":null,"rejected_by_id":null,"raw":"edited haahaasdfasdfasdfasdf","post_options":{"archetype":"regular","category":"3","reply_to_post_number":"2","typing_duration_msecs":"1900","composer_open_duration_msecs":"12096","visible":true,"is_warning":false,"featured_link":"","ip_address":"172.17.0.1","first_post_checks":true,"is_poll":true},"created_at":"2017-08-07T19:11:52.018Z","category_id":3,"can_delete_user":true}],"__rest_serializer":"1","refresh_queued_posts":"/queued_posts?status=new"}
];
});
visit("/queued-posts");
click(".queued-posts .queued-post button.edit");
andThen(() => {
assert.ok(exists(".d-editor-container"), "the body should be editable");
assert.notOk(exists(".edit-title .ember-text-field"), "title should not be editbale");
assert.notOk(exists(".category-combobox"), "category should not be editable");
assert.notOk(exists("div.tag-chooser"), "tags should not be editable");
});
});