Use small actions for moving posts

This commit is contained in:
Robin Ward 2015-07-31 16:30:18 -04:00
parent cf91bca0cd
commit 76aa0795b3
12 changed files with 88 additions and 89 deletions

View file

@ -10,7 +10,8 @@ const icons = {
'pinned_globally.enabled': 'thumb-tack',
'pinned_globally.disabled': 'thumb-tack unpinned',
'visible.enabled': 'eye',
'visible.disabled': 'eye-slash'
'visible.disabled': 'eye-slash',
'split_topic': 'sign-out'
};
export function actionDescription(actionCode, createdAt) {

View file

@ -1,12 +1,15 @@
import Presence from 'discourse/mixins/presence';
import SelectedPostsCount from 'discourse/mixins/selected-posts-count';
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
import { movePosts, mergeTopic } from 'discourse/models/topic';
// Modal related to merging of topics
export default ObjectController.extend(SelectedPostsCount, ModalFunctionality, Presence, {
export default Ember.Controller.extend(SelectedPostsCount, ModalFunctionality, Presence, {
needs: ['topic'],
saving: false,
selectedTopicId: null,
topicController: Em.computed.alias('controllers.topic'),
selectedPosts: Em.computed.alias('topicController.selectedPosts'),
selectedReplies: Em.computed.alias('topicController.selectedReplies'),
@ -22,38 +25,40 @@ export default ObjectController.extend(SelectedPostsCount, ModalFunctionality, P
return I18n.t('topic.merge_topic.title');
}.property('saving'),
onShow: function() {
onShow() {
this.set('controllers.modal.modalClass', 'split-modal');
},
actions: {
movePostsToExistingTopic: function() {
movePostsToExistingTopic() {
const topicId = this.get('model.id');
this.set('saving', true);
var promise = null;
let promise = null;
if (this.get('allPostsSelected')) {
promise = Discourse.Topic.mergeTopic(this.get('id'), this.get('selectedTopicId'));
promise = mergeTopic(topicId, this.get('selectedTopicId'));
} else {
var postIds = this.get('selectedPosts').map(function(p) { return p.get('id'); }),
replyPostIds = this.get('selectedReplies').map(function(p) { return p.get('id'); });
const postIds = this.get('selectedPosts').map(function(p) { return p.get('id'); });
const replyPostIds = this.get('selectedReplies').map(function(p) { return p.get('id'); });
promise = Discourse.Topic.movePosts(this.get('id'), {
promise = movePosts(topicId, {
destination_topic_id: this.get('selectedTopicId'),
post_ids: postIds,
reply_post_ids: replyPostIds
});
}
var mergeTopicController = this;
const self = this;
promise.then(function(result) {
// Posts moved
mergeTopicController.send('closeModal');
mergeTopicController.get('topicController').send('toggleMultiSelect');
self.send('closeModal');
self.get('topicController').send('toggleMultiSelect');
Em.run.next(function() { Discourse.URL.routeTo(result.url); });
}, function() {
// Error moving posts
mergeTopicController.flash(I18n.t('topic.merge_topic.error'));
mergeTopicController.set('saving', false);
}).catch(function() {
self.flash(I18n.t('topic.merge_topic.error'));
}).finally(function() {
self.set('saving', false);
});
return false;
}

View file

@ -1,15 +1,20 @@
import Presence from 'discourse/mixins/presence';
import SelectedPostsCount from 'discourse/mixins/selected-posts-count';
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
import { extractError } from 'discourse/lib/ajax-error';
import { movePosts } from 'discourse/models/topic';
// Modal related to auto closing of topics
export default ObjectController.extend(SelectedPostsCount, ModalFunctionality, Presence, {
export default Ember.Controller.extend(SelectedPostsCount, ModalFunctionality, Presence, {
needs: ['topic'],
topicName: null,
saving: false,
categoryId: null,
topicController: Em.computed.alias('controllers.topic'),
selectedPosts: Em.computed.alias('topicController.selectedPosts'),
selectedReplies: Em.computed.alias('topicController.selectedReplies'),
allPostsSelected: Em.computed.alias('topicController.allPostsSelected'),
buttonDisabled: function() {
if (this.get('saving')) return true;
@ -21,7 +26,7 @@ export default ObjectController.extend(SelectedPostsCount, ModalFunctionality, P
return I18n.t('topic.split_topic.action');
}.property('saving'),
onShow: function() {
onShow() {
this.setProperties({
'controllers.modal.modalClass': 'split-modal',
saving: false,
@ -31,39 +36,29 @@ export default ObjectController.extend(SelectedPostsCount, ModalFunctionality, P
},
actions: {
movePostsToNewTopic: function() {
movePostsToNewTopic() {
this.set('saving', true);
var postIds = this.get('selectedPosts').map(function(p) { return p.get('id'); }),
replyPostIds = this.get('selectedReplies').map(function(p) { return p.get('id'); }),
self = this,
categoryId = this.get('categoryId'),
saveOpts = {
title: this.get('topicName'),
post_ids: postIds,
reply_post_ids: replyPostIds
};
const postIds = this.get('selectedPosts').map(function(p) { return p.get('id'); }),
replyPostIds = this.get('selectedReplies').map(function(p) { return p.get('id'); }),
self = this,
categoryId = this.get('categoryId'),
saveOpts = {
title: this.get('topicName'),
post_ids: postIds,
reply_post_ids: replyPostIds
};
if (!Ember.isNone(categoryId)) { saveOpts.category_id = categoryId; }
Discourse.Topic.movePosts(this.get('id'), saveOpts).then(function(result) {
movePosts(this.get('model.id'), saveOpts).then(function(result) {
// Posts moved
self.send('closeModal');
self.get('topicController').send('toggleMultiSelect');
Em.run.next(function() { Discourse.URL.routeTo(result.url); });
Ember.run.next(function() { Discourse.URL.routeTo(result.url); });
}).catch(function(xhr) {
var error = I18n.t('topic.split_topic.error');
if (xhr) {
var json = xhr.responseJSON;
if (json && json.errors) {
error = json.errors[0];
}
}
// Error moving posts
self.flash(error);
self.flash(extractError(xhr, I18n.t('topic.split_topic.error')));
}).finally(function() {
self.set('saving', false);
});
return false;

View file

@ -1,4 +1,4 @@
function extractError(error) {
export function extractError(error, defaultMessage) {
if (error instanceof Error) {
Ember.Logger.error(error.stack);
}
@ -42,7 +42,7 @@ function extractError(error) {
}
}
return parsedError || I18n.t('generic_error');
return parsedError || defaultMessage || I18n.t('generic_error');
}
export function throwAjaxError(undoCallback) {

View file

@ -1,3 +1,4 @@
import { flushMap } from 'discourse/models/store';
import RestModel from 'discourse/models/rest';
const Topic = RestModel.extend({
@ -462,28 +463,6 @@ Topic.reopenClass({
return Discourse.ajax(url + ".json", {data: data});
},
mergeTopic(topicId, destinationTopicId) {
const promise = Discourse.ajax("/t/" + topicId + "/merge-topic", {
type: 'POST',
data: {destination_topic_id: destinationTopicId}
}).then(function (result) {
if (result.success) return result;
promise.reject(new Error("error merging topic"));
});
return promise;
},
movePosts(topicId, opts) {
const promise = Discourse.ajax("/t/" + topicId + "/move-posts", {
type: 'POST',
data: opts
}).then(function (result) {
if (result.success) return result;
promise.reject(new Error("error moving posts topic"));
});
return promise;
},
changeOwners(topicId, opts) {
const promise = Discourse.ajax("/t/" + topicId + "/change-owner", {
type: 'POST',
@ -523,4 +502,24 @@ Topic.reopenClass({
}
});
function moveResult(result) {
if (result.success) {
// We should be hesitant to flush the map but moving ids is one rare case
flushMap();
return result;
}
throw "error moving posts topic";
}
export function movePosts(topicId, data) {
return Discourse.ajax("/t/" + topicId + "/move-posts", { type: 'POST', data }).then(moveResult);
}
export function mergeTopic(topicId, destinationTopicId) {
return Discourse.ajax("/t/" + topicId + "/merge-topic", {
type: 'POST',
data: {destination_topic_id: destinationTopicId}
}).then(moveResult);
}
export default Topic;

View file

@ -1,10 +1,4 @@
<div id='move-selected' class="modal-body">
{{#if error}}
<div class="alert alert-error">
<button class="close" data-dismiss="alert">×</button>
</div>
{{/if}}
<p>{{{i18n 'topic.merge_topic.instructions' count=selectedPostsCount}}}</p>
<form>
@ -13,5 +7,7 @@
</div>
<div class="modal-footer">
<button class='btn btn-primary' {{bind-attr disabled="buttonDisabled"}} {{action "movePostsToExistingTopic"}}><i class="fa fa-sign-out"></i>{{buttonTitle}}</button>
{{#d-button class="btn-primary" disabled=buttonDisabled action="movePostsToExistingTopic"}}
{{fa-icon 'sign-out'}} {{buttonTitle}}
{{/d-button}}
</div>

View file

@ -1,10 +1,4 @@
<div id='move-selected' class="modal-body">
{{#if error}}
<div class="alert alert-error">
<button class="close" data-dismiss="alert">×</button>
</div>
{{/if}}
{{{i18n 'topic.split_topic.instructions' count=selectedPostsCount}}}
<form>
@ -18,5 +12,7 @@
</div>
<div class="modal-footer">
<button class='btn btn-primary' {{bind-attr disabled="buttonDisabled"}} {{action "movePostsToNewTopic"}}><i class='fa fa-sign-out'></i>{{buttonTitle}}</button>
{{#d-button class="btn-primary" disabled=buttonDisabled action="movePostsToNewTopic"}}
{{fa-icon 'sign-out'}} {{buttonTitle}}
{{/d-button}}
</div>

View file

@ -2,6 +2,6 @@ import SelectedPostsCount from 'discourse/mixins/selected-posts-count';
import ModalBodyView from "discourse/views/modal-body";
export default ModalBodyView.extend(SelectedPostsCount, {
templateName: 'modal/split_topic',
templateName: 'modal/split-topic',
title: I18n.t('topic.split_topic.title')
});

View file

@ -28,6 +28,8 @@
//= require_tree ./discourse/adapters
//= require ./discourse/models/rest
//= require ./discourse/models/model
//= require ./discourse/models/result-set
//= require ./discourse/models/store
//= require ./discourse/models/post-action-type
//= require ./discourse/models/action-summary
//= require ./discourse/models/post

View file

@ -123,11 +123,15 @@ class PostMover
end
def create_moderator_post_in_original_topic
move_type_str = PostMover.move_types[@move_type].to_s
original_topic.add_moderator_post(
user,
I18n.t("move_posts.#{PostMover.move_types[@move_type]}_moderator_post",
I18n.t("move_posts.#{move_type_str}_moderator_post",
count: post_ids.count,
topic_link: "[#{destination_topic.title}](#{destination_topic.url})"),
topic_link: "[#{destination_topic.title}](#{destination_topic.relative_url})"),
post_type: Post.types[:small_action],
action_code: "split_topic",
post_number: @first_post_number_moved
)
end

View file

@ -120,6 +120,7 @@ en:
email: 'send this link in an email'
action_codes:
split_topic: "split this topic"
autoclosed:
enabled: 'closed this topic %{when}'
disabled: 'opened this topic %{when}'

View file

@ -1242,11 +1242,11 @@ en:
move_posts:
new_topic_moderator_post:
one: "I moved a post to a new topic: %{topic_link}"
other: "I moved %{count} posts to a new topic: %{topic_link}"
one: "A post was split to a new topic: %{topic_link}"
other: "%{count} posts were split to a new topic: %{topic_link}"
existing_topic_moderator_post:
one: "I moved a post to an existing topic: %{topic_link}"
other: "I moved %{count} posts to an existing topic: %{topic_link}"
one: "A post was merged into an existing topic: %{topic_link}"
other: "%{count} posts were merged into an existing topic: %{topic_link}"
change_owner:
post_revision_text: "Ownership transferred from %{old_user} to %{new_user}"