DEV: Refactor composer and logout dialogs (#18156)

This commit is contained in:
Penar Musaraj 2022-09-13 12:30:52 -04:00 committed by GitHub
parent 08cb9ecca4
commit b8adb70973
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 136 additions and 111 deletions

View File

@ -18,9 +18,7 @@ import discourseComputed, {
import DiscourseURL from "discourse/lib/url"; import DiscourseURL from "discourse/lib/url";
import Draft from "discourse/models/draft"; import Draft from "discourse/models/draft";
import I18n from "I18n"; import I18n from "I18n";
import { iconHTML } from "discourse-common/lib/icon-library";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import bootbox from "bootbox";
import { buildQuote } from "discourse/lib/quote"; import { buildQuote } from "discourse/lib/quote";
import deprecated from "discourse-common/lib/deprecated"; import deprecated from "discourse-common/lib/deprecated";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
@ -87,6 +85,7 @@ export function addPopupMenuOptionsCallback(callback) {
export default Controller.extend({ export default Controller.extend({
topicController: controller("topic"), topicController: controller("topic"),
router: service(), router: service(),
dialog: service(),
checkedMessages: false, checkedMessages: false,
messageCount: null, messageCount: null,
@ -858,7 +857,7 @@ export default Controller.extend({
timeLeft: durationTextFromSeconds(timeLeft), timeLeft: durationTextFromSeconds(timeLeft),
}); });
bootbox.alert(message); this.dialog.alert(message);
return; return;
} else { } else {
// Edge case where the user tries to post again immediately. // Edge case where the user tries to post again immediately.
@ -885,40 +884,37 @@ export default Controller.extend({
currentTopic.id !== composer.get("topic.id") && currentTopic.id !== composer.get("topic.id") &&
(this.isStaffUser || !currentTopic.closed) (this.isStaffUser || !currentTopic.closed)
) { ) {
const message = this.dialog.alert({
"<h1>" + I18n.t("composer.posting_not_on_topic") + "</h1>"; title: I18n.t("composer.posting_not_on_topic"),
buttons: [
let buttons = [ {
{ label:
label: I18n.t("composer.cancel"), I18n.t("composer.reply_original") +
class: "btn-flat btn-text btn-reply-where-cancel", "<br/><div class='topic-title overflow-ellipsis'>" +
}, this.get("model.topic.fancyTitle") +
]; "</div>",
class: "btn-primary btn-reply-on-original",
buttons.push({ action: () => this.save(true),
label: },
I18n.t("composer.reply_here") + {
"<br/><div class='topic-title overflow-ellipsis'>" + label:
currentTopic.get("fancyTitle") + I18n.t("composer.reply_here") +
"</div>", "<br/><div class='topic-title overflow-ellipsis'>" +
class: "btn-reply-here", currentTopic.get("fancyTitle") +
callback: () => { "</div>",
composer.setProperties({ topic: currentTopic, post: null }); class: "btn-reply-here",
this.save(true); action: () => {
}, composer.setProperties({ topic: currentTopic, post: null });
this.save(true);
},
},
{
label: I18n.t("composer.cancel"),
class: "btn-flat btn-text btn-reply-where-cancel",
},
],
class: "reply-where-modal",
}); });
buttons.push({
label:
I18n.t("composer.reply_original") +
"<br/><div class='topic-title overflow-ellipsis'>" +
this.get("model.topic.fancyTitle") +
"</div>",
class: "btn-primary btn-reply-on-original",
callback: () => this.save(true),
});
bootbox.dialog(message, buttons, { classes: "reply-where-modal" });
return; return;
} }
} }
@ -987,8 +983,11 @@ export default Controller.extend({
// TODO: await this: // TODO: await this:
this.destroyDraft(); this.destroyDraft();
if (result.responseJson.message) { if (result.responseJson.message) {
return bootbox.alert(result.responseJson.message, () => { return this.dialog.alert({
DiscourseURL.routeTo(result.responseJson.route_to); message: result.responseJson.message,
didConfirm: () => {
DiscourseURL.routeTo(result.responseJson.route_to);
},
}); });
} }
return DiscourseURL.routeTo(result.responseJson.route_to); return DiscourseURL.routeTo(result.responseJson.route_to);
@ -1010,7 +1009,9 @@ export default Controller.extend({
.catch((error) => { .catch((error) => {
composer.set("disableDrafts", false); composer.set("disableDrafts", false);
if (error) { if (error) {
this.appEvents.one("composer:will-open", () => bootbox.alert(error)); this.appEvents.one("composer:will-open", () =>
this.dialog.alert(error)
);
} }
}); });
@ -1295,23 +1296,27 @@ export default Controller.extend({
} }
return new Promise((resolve) => { return new Promise((resolve) => {
bootbox.dialog(I18n.t("drafts.abandon.confirm"), [ this.dialog.alert({
{ message: I18n.t("drafts.abandon.confirm"),
label: I18n.t("drafts.abandon.no_value"), buttons: [
callback: () => resolve(data), {
}, label: I18n.t("drafts.abandon.yes_value"),
{ class: "btn-danger",
label: I18n.t("drafts.abandon.yes_value"), icon: "far-trash-alt",
class: "btn-danger", action: () => {
icon: iconHTML("far-trash-alt"), this.destroyDraft(data.draft_sequence).finally(() => {
callback: () => { data.draft = null;
this.destroyDraft(data.draft_sequence).finally(() => { resolve(data);
data.draft = null; });
resolve(data); },
});
}, },
}, {
]); label: I18n.t("drafts.abandon.no_value"),
class: "btn-resume-editing",
action: () => resolve(data),
},
],
});
}); });
}, },

View File

@ -1,5 +1,4 @@
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import logout from "discourse/lib/logout"; import logout from "discourse/lib/logout";
let _showingLogout = false; let _showingLogout = false;
@ -10,25 +9,27 @@ export default {
after: "message-bus", after: "message-bus",
initialize(container) { initialize(container) {
const messageBus = container.lookup("service:message-bus"); const messageBus = container.lookup("service:message-bus"),
messageBus.subscribe("/logout", () => { dialog = container.lookup("service:dialog");
if (_showingLogout) {
return; if (!messageBus) {
return;
}
messageBus.subscribe("/logout", function () {
if (!_showingLogout) {
_showingLogout = true;
dialog.alert({
message: I18n.t("logout"),
confirmButtonLabel: "home",
didConfirm: logout,
didCancel: logout,
shouldDisplayCancel: false,
});
} }
_showingLogout = true; _showingLogout = true;
bootbox.dialog(
I18n.t("logout"),
{
label: I18n.t("home"),
callback: logout,
},
{
onEscape: logout,
backdrop: "static",
}
);
}); });
}, },
}; };

View File

@ -18,7 +18,7 @@ import RestModel from "discourse/models/rest";
import Site from "discourse/models/site"; import Site from "discourse/models/site";
import Topic from "discourse/models/topic"; import Topic from "discourse/models/topic";
import User from "discourse/models/user"; import User from "discourse/models/user";
import bootbox from "bootbox"; import { inject as service } from "@ember/service";
import deprecated from "discourse-common/lib/deprecated"; import deprecated from "discourse-common/lib/deprecated";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { propertyNotEqual } from "discourse/lib/computed"; import { propertyNotEqual } from "discourse/lib/computed";
@ -119,6 +119,7 @@ export const SAVE_ICONS = {
}; };
const Composer = RestModel.extend({ const Composer = RestModel.extend({
dialog: service(),
_categoryId: null, _categoryId: null,
unlistTopic: false, unlistTopic: false,
noBump: false, noBump: false,
@ -453,7 +454,9 @@ const Composer = RestModel.extend({
const category = this.category; const category = this.category;
if (category && category.topic_template) { if (category && category.topic_template) {
if (this.reply.trim() === category.topic_template.trim()) { if (this.reply.trim() === category.topic_template.trim()) {
bootbox.alert(I18n.t("composer.error.topic_template_not_modified")); this.dialog.alert(
I18n.t("composer.error.topic_template_not_modified")
);
return true; return true;
} }
} }
@ -1277,28 +1280,23 @@ const Composer = RestModel.extend({
) { ) {
const json = e.jqXHR.responseJSON; const json = e.jqXHR.responseJSON;
draftStatus = json.errors[0]; draftStatus = json.errors[0];
if (json.extras && json.extras.description) {
const buttons = [];
// ignore and force save draft if (json.extras?.description) {
buttons.push({ this.dialog.alert({
label: I18n.t("composer.ignore"), message: json.extras.description,
class: "btn", buttons: [
callback: () => { {
this.set("draftForceSave", true); label: I18n.t("composer.reload"),
}, class: "btn-primary",
action: () => window.location.reload(),
},
{
label: I18n.t("composer.ignore"),
class: "btn",
action: () => this.set("draftForceSave", true),
},
],
}); });
// reload
buttons.push({
label: I18n.t("composer.reload"),
class: "btn btn-primary",
callback: () => {
window.location.reload();
},
});
bootbox.dialog(json.extras.description, buttons);
} }
} }
this.setProperties({ this.setProperties({

View File

@ -182,9 +182,9 @@ acceptance("Composer", function (needs) {
await fillIn("#reply-title", "this title triggers an error"); await fillIn("#reply-title", "this title triggers an error");
await fillIn(".d-editor-input", "this is the *content* of a post"); await fillIn(".d-editor-input", "this is the *content* of a post");
await click("#reply-control button.create"); await click("#reply-control button.create");
assert.ok(exists(".bootbox.modal"), "it pops up an error message"); assert.ok(exists(".dialog-body"), "it pops up an error message");
await click(".bootbox.modal a.btn-primary"); await click(".dialog-footer .btn-primary");
assert.ok(!exists(".bootbox.modal"), "it dismisses the error"); assert.ok(!exists(".dialog-body"), "it dismisses the error");
assert.ok(exists(".d-editor-input"), "the composer input is visible"); assert.ok(exists(".d-editor-input"), "the composer input is visible");
}); });
@ -223,13 +223,14 @@ acceptance("Composer", function (needs) {
await fillIn("#reply-title", "This title doesn't matter"); await fillIn("#reply-title", "This title doesn't matter");
await fillIn(".d-editor-input", "custom message"); await fillIn(".d-editor-input", "custom message");
await click("#reply-control button.create"); await click("#reply-control button.create");
assert.strictEqual( assert.strictEqual(
query(".bootbox .modal-body").innerText, query("#dialog-holder .dialog-body").innerText,
"This is a custom response" "This is a custom response"
); );
assert.strictEqual(currentURL(), "/", "it doesn't change routes"); assert.strictEqual(currentURL(), "/", "it doesn't change routes");
await click(".bootbox .btn-primary"); await click(".dialog-footer .btn-primary");
assert.strictEqual( assert.strictEqual(
currentURL(), currentURL(),
"/faq", "/faq",
@ -764,11 +765,11 @@ acceptance("Composer", function (needs) {
await click(".topic-post:nth-of-type(1) button.edit"); await click(".topic-post:nth-of-type(1) button.edit");
assert.strictEqual( assert.strictEqual(
query(".modal-body").innerText, query(".dialog-body").innerText,
I18n.t("drafts.abandon.confirm") I18n.t("drafts.abandon.confirm")
); );
await click(".modal-footer .btn.btn-default"); await click(".dialog-footer .btn-resume-editing");
}); });
test("Can switch states without abandon popup", async function (assert) { test("Can switch states without abandon popup", async function (assert) {
@ -826,7 +827,7 @@ acceptance("Composer", function (needs) {
await visit("/u/charlie"); await visit("/u/charlie");
await click("button.compose-pm"); await click("button.compose-pm");
await click(".modal .btn-default"); await click(".dialog-footer .btn-resume-editing");
const privateMessageUsers = selectKit("#private-message-users"); const privateMessageUsers = selectKit("#private-message-users");
assert.strictEqual(privateMessageUsers.header().value(), "codinghorror"); assert.strictEqual(privateMessageUsers.header().value(), "codinghorror");

View File

@ -1,3 +1,4 @@
import I18n from "I18n";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import User from "discourse/models/user"; import User from "discourse/models/user";
import selectKit from "discourse/tests/helpers/select-kit-helper"; import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -6,10 +7,12 @@ import userFixtures from "discourse/tests/fixtures/user-fixtures";
import { import {
acceptance, acceptance,
exists, exists,
publishToMessageBus,
query, query,
queryAll, queryAll,
updateCurrentUser, updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers"; } from "discourse/tests/helpers/qunit-helpers";
import * as logout from "discourse/lib/logout";
import { click, currentRouteName, visit } from "@ember/test-helpers"; import { click, currentRouteName, visit } from "@ember/test-helpers";
import { cloneJSON } from "discourse-common/lib/object"; import { cloneJSON } from "discourse-common/lib/object";
import { test } from "qunit"; import { test } from "qunit";
@ -305,3 +308,27 @@ acceptance(
}); });
} }
); );
acceptance("User - Logout", function (needs) {
needs.user({ username: "eviltrout" });
test("Dialog works", async function (assert) {
sinon.stub(logout, "default");
await visit("/u/eviltrout");
await publishToMessageBus("/logout");
assert.ok(exists(".dialog-body"));
assert.ok(
!exists(".dialog-footer .btn-default"),
"no cancel button present"
);
assert.strictEqual(
query(".dialog-footer .btn-primary").innerText,
I18n.t("home"),
"primary dialog button is present"
);
await click(".dialog-overlay");
assert.ok(logout.default.called, "logout helper was called");
});
});

View File

@ -59,6 +59,7 @@
.dialog-close { .dialog-close {
margin-left: auto; margin-left: auto;
flex-basis: content;
.d-icon { .d-icon {
color: var(--primary-high); color: var(--primary-high);
} }

View File

@ -278,15 +278,7 @@
} }
} }
.bootbox.modal.reply-where-modal { .reply-where-modal {
max-width: 400px;
margin-left: -200px;
h1 {
margin: 0;
font-size: var(--font-up-2);
}
.btn { .btn {
display: block; display: block;
text-align: left; text-align: left;