mirror of
https://github.com/discourse/discourse.git
synced 2026-08-05 18:57:20 -05:00
FIX: load saved draft when clicking reply to post (#33543)
In the past we have always relied on automatically opening the composer and auto loading the existing draft when visiting a topic that has a draft post reply. This is fine to auto load the draft, but when the composer is closed and reopened on the same page then we have an issue. The result is that the draft is then deleted because the draft key is set and the composer body is blank, since it has never been populated when clicking the reply to post button. To solve this we can check for existing drafts when clicking the reply to post button, then load the draft into the composer. _The challenging part of this change is that we have a number of tests that were relying on a false positive. Hence in the specs I have switched some tests to use a fixture that does not have drafts and in some cases kept the same fixture but mocked the response as having no drafts returned._
This commit is contained in:
@@ -39,6 +39,7 @@ import { escapeExpression } from "discourse/lib/utilities";
|
||||
import Bookmark, { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark";
|
||||
import Category from "discourse/models/category";
|
||||
import Composer from "discourse/models/composer";
|
||||
import Draft from "discourse/models/draft";
|
||||
import Post from "discourse/models/post";
|
||||
import Topic from "discourse/models/topic";
|
||||
import TopicTimer from "discourse/models/topic-timer";
|
||||
@@ -685,7 +686,7 @@ export default class TopicController extends Controller {
|
||||
|
||||
// Post related methods
|
||||
@action
|
||||
replyToPost(post) {
|
||||
async replyToPost(post) {
|
||||
const composerController = this.composer;
|
||||
const topic = post ? post.get("topic") : this.model;
|
||||
const quoteState = this.quoteState;
|
||||
@@ -731,6 +732,16 @@ export default class TopicController extends Controller {
|
||||
opts.topic = topic;
|
||||
}
|
||||
|
||||
if (!opts.quote) {
|
||||
const draftData = await Draft.get(opts.draftKey);
|
||||
|
||||
if (draftData.draft) {
|
||||
const data = JSON.parse(draftData.draft);
|
||||
opts.reply = data.reply;
|
||||
opts.draftSequence = draftData.draft_sequence;
|
||||
}
|
||||
}
|
||||
|
||||
composerController.open(opts);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -469,7 +469,20 @@ import { i18n } from "discourse-i18n";
|
||||
|
||||
assert
|
||||
.dom(".d-editor-input")
|
||||
.hasNoValue("discards draft and reset composer textarea");
|
||||
.hasValue(
|
||||
"This is a draft of the first post",
|
||||
"loads the existing draft"
|
||||
);
|
||||
});
|
||||
|
||||
test("Loads draft in composer when clicking reply on a topic with existing draft", async function (assert) {
|
||||
await visit("/t/internationalization-localization/280");
|
||||
|
||||
await click("#topic-footer-buttons .btn.create");
|
||||
|
||||
assert
|
||||
.dom(".d-editor-input")
|
||||
.hasValue("This is a draft of the first post");
|
||||
});
|
||||
|
||||
test("Autosaves drafts after clicking keep editing in discard modal", async function (assert) {
|
||||
@@ -477,6 +490,9 @@ import { i18n } from "discourse-i18n";
|
||||
assert.step("saveDraft");
|
||||
return response(200, {});
|
||||
});
|
||||
pretender.get("/drafts/topic_280.json", function () {
|
||||
return response(200, { draft: null });
|
||||
});
|
||||
|
||||
await visit("/t/internationalization-localization/280");
|
||||
|
||||
@@ -661,7 +677,7 @@ import { i18n } from "discourse-i18n";
|
||||
});
|
||||
|
||||
test("Composer can toggle between edit and reply on the OP", async function (assert) {
|
||||
await visit("/t/this-is-a-test-topic/9");
|
||||
await visit("/t/this-is-a-test-topic/54081");
|
||||
|
||||
await click(".topic-post[data-post-number='1'] button.edit");
|
||||
assert
|
||||
@@ -684,7 +700,7 @@ import { i18n } from "discourse-i18n";
|
||||
});
|
||||
|
||||
test("Composer can toggle between edit and reply on a reply", async function (assert) {
|
||||
await visit("/t/this-is-a-test-topic/9");
|
||||
await visit("/t/this-is-a-test-topic/54081");
|
||||
|
||||
await click(".topic-post[data-post-number='2'] button.edit");
|
||||
assert
|
||||
@@ -788,7 +804,7 @@ import { i18n } from "discourse-i18n";
|
||||
});
|
||||
|
||||
test("Composer can toggle between reply and createTopic", async function (assert) {
|
||||
await visit("/t/this-is-a-test-topic/9");
|
||||
await visit("/t/this-is-a-test-topic/54081");
|
||||
await click(".topic-post[data-post-number='1'] button.reply");
|
||||
|
||||
await selectKit(".composer-actions").expand();
|
||||
@@ -844,11 +860,11 @@ import { i18n } from "discourse-i18n";
|
||||
});
|
||||
|
||||
test("Composer can toggle whisper when clicking reply to topic after reply to whisper", async function (assert) {
|
||||
await visit("/t/topic-with-whisper/960");
|
||||
await visit("/t/topic-with-whisper/54081");
|
||||
|
||||
await click(".topic-post[data-post-number='3'] button.reply");
|
||||
await click("#reply-control .save-or-cancel button.cancel");
|
||||
await click(".topic-footer-main-buttons button.create");
|
||||
await click(".timeline-footer-controls button.create");
|
||||
await click(".reply-details summary div");
|
||||
assert
|
||||
.dom('.reply-details li[data-value="toggle_whisper"]')
|
||||
@@ -1456,6 +1472,11 @@ import { i18n } from "discourse-i18n";
|
||||
glimmer_post_stream_mode: postStreamMode,
|
||||
allow_uncategorized_topics: true,
|
||||
});
|
||||
needs.pretender((server, helper) => {
|
||||
server.get("/drafts/topic_280.json", function () {
|
||||
return helper.response(200, { draft: null });
|
||||
});
|
||||
});
|
||||
|
||||
test("buttons can support a shortcut", async function (assert) {
|
||||
withPluginApi("0", (api) => {
|
||||
|
||||
@@ -15,6 +15,9 @@ acceptance("Emoji", function (needs) {
|
||||
server.get("/emojis/search-aliases.json", () => {
|
||||
return helper.response([]);
|
||||
});
|
||||
server.get("/drafts/topic_280.json", function () {
|
||||
return helper.response(200, { draft: null });
|
||||
});
|
||||
});
|
||||
|
||||
test("emoji is cooked properly", async function (assert) {
|
||||
|
||||
@@ -11,6 +11,11 @@ import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
acceptance("Discourse Presence Plugin", function (needs) {
|
||||
needs.user({ whisperer: true });
|
||||
needs.pretender((server, helper) => {
|
||||
server.get("/drafts/topic_280.json", function () {
|
||||
return helper.response(200, { draft: null });
|
||||
});
|
||||
});
|
||||
|
||||
test("Doesn't break topic creation", async function (assert) {
|
||||
await visit("/");
|
||||
|
||||
Reference in New Issue
Block a user