diff --git a/app/assets/javascripts/discourse/app/lib/transform-post.js b/app/assets/javascripts/discourse/app/lib/transform-post.js index 44dbe1d5cdd..b2d5e01ce2c 100644 --- a/app/assets/javascripts/discourse/app/lib/transform-post.js +++ b/app/assets/javascripts/discourse/app/lib/transform-post.js @@ -148,6 +148,7 @@ export default function transformPost( postAtts.actionCodeWho = post.action_code_who; postAtts.topicUrl = topic.get("url"); postAtts.isSaving = post.isSaving; + postAtts.staged = post.staged; if (post.notice) { postAtts.notice = post.notice; diff --git a/app/assets/javascripts/discourse/app/models/composer.js b/app/assets/javascripts/discourse/app/models/composer.js index 9851d480dc3..5fee7738421 100644 --- a/app/assets/javascripts/discourse/app/models/composer.js +++ b/app/assets/javascripts/discourse/app/models/composer.js @@ -961,23 +961,29 @@ const Composer = RestModel.extend({ this.set("composeState", SAVING); const rollback = throwAjaxError((error) => { - post.set("cooked", oldCooked); + post.setProperties({ cooked: oldCooked, staged: false }); + this.appEvents.trigger("post-stream:refresh", { id: post.id }); + this.set("composeState", OPEN); if (error.jqXHR && error.jqXHR.status === 409) { this.set("editConflict", true); } }); + post.setProperties({ cooked: props.cooked, staged: true }); + this.appEvents.trigger("post-stream:refresh", { id: post.id }); + return promise .then(() => { - // rest model only sets props after it is saved - post.set("cooked", props.cooked); return post.save(props).then((result) => { this.clearState(); return result; }); }) - .catch(rollback); + .catch(rollback) + .finally(() => { + post.set("staged", false); + }); }, serialize(serializer, dest) { diff --git a/app/assets/javascripts/discourse/app/widgets/post.js b/app/assets/javascripts/discourse/app/widgets/post.js index c2e2bfd48c8..c1330f4c245 100644 --- a/app/assets/javascripts/discourse/app/widgets/post.js +++ b/app/assets/javascripts/discourse/app/widgets/post.js @@ -735,7 +735,7 @@ export default createWidget("post", { } const classNames = ["topic-post", "clearfix"]; - if (attrs.id === -1 || attrs.isSaving) { + if (attrs.id === -1 || attrs.isSaving || attrs.staged) { classNames.push("staged"); } if (attrs.selected) { diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js index 45035e01fe8..cd0bb88cf25 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js @@ -346,6 +346,43 @@ acceptance("Composer", function (needs) { ); }); + test("Editing a post stages new content", async function (assert) { + await visit("/t/internationalization-localization/280"); + await click(".topic-post:nth-of-type(1) button.show-more-actions"); + await click(".topic-post:nth-of-type(1) button.edit"); + + await fillIn(".d-editor-input", "will return empty json"); + await fillIn("#reply-title", "This is the new text for the title"); + await click("#reply-control button.create"); + + assert.equal(find(".topic-post.staged").length, 1); + assert.ok( + find(".topic-post:nth-of-type(1)")[0].className.includes("staged") + ); + assert.equal( + find(".topic-post.staged .cooked").text().trim(), + "will return empty json" + ); + }); + + test("Editing a post can rollback to old content", async function (assert) { + await visit("/t/internationalization-localization/280"); + await click(".topic-post:nth-of-type(1) button.show-more-actions"); + await click(".topic-post:nth-of-type(1) button.edit"); + + await fillIn(".d-editor-input", "this will 409"); + await fillIn("#reply-title", "This is the new text for the title"); + await click("#reply-control button.create"); + + assert.equal(find(".topic-post.staged").length, 0); + assert.equal( + find(".topic-post .cooked")[0].innerText, + "Any plans to support localization of UI elements, so that I (for example) could set up a completely German speaking forum?" + ); + + await click(".bootbox.modal .btn-primary"); + }); + test("Composer can switch between edits", async function (assert) { await visit("/t/this-is-a-test-topic/9"); diff --git a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js index 339872180a0..0276932058a 100644 --- a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js +++ b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js @@ -479,6 +479,8 @@ export function applyDefaultHandlers(pretender) { const data = parsePostData(request.requestBody); if (data.post.raw === "this will 409") { return response(409, { errors: ["edit conflict"] }); + } else if (data.post.raw === "will return empty json") { + return response(200, {}); } data.post.id = request.params.post_id; data.post.version = 2;