DEV: Refactor composer and logout dialogs (#18156)
This commit is contained in:
parent
08cb9ecca4
commit
b8adb70973
|
@ -18,9 +18,7 @@ import discourseComputed, {
|
|||
import DiscourseURL from "discourse/lib/url";
|
||||
import Draft from "discourse/models/draft";
|
||||
import I18n from "I18n";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import { Promise } from "rsvp";
|
||||
import bootbox from "bootbox";
|
||||
import { buildQuote } from "discourse/lib/quote";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
|
@ -87,6 +85,7 @@ export function addPopupMenuOptionsCallback(callback) {
|
|||
export default Controller.extend({
|
||||
topicController: controller("topic"),
|
||||
router: service(),
|
||||
dialog: service(),
|
||||
|
||||
checkedMessages: false,
|
||||
messageCount: null,
|
||||
|
@ -858,7 +857,7 @@ export default Controller.extend({
|
|||
timeLeft: durationTextFromSeconds(timeLeft),
|
||||
});
|
||||
|
||||
bootbox.alert(message);
|
||||
this.dialog.alert(message);
|
||||
return;
|
||||
} else {
|
||||
// Edge case where the user tries to post again immediately.
|
||||
|
@ -885,40 +884,37 @@ export default Controller.extend({
|
|||
currentTopic.id !== composer.get("topic.id") &&
|
||||
(this.isStaffUser || !currentTopic.closed)
|
||||
) {
|
||||
const message =
|
||||
"<h1>" + I18n.t("composer.posting_not_on_topic") + "</h1>";
|
||||
|
||||
let buttons = [
|
||||
{
|
||||
label: I18n.t("composer.cancel"),
|
||||
class: "btn-flat btn-text btn-reply-where-cancel",
|
||||
},
|
||||
];
|
||||
|
||||
buttons.push({
|
||||
label:
|
||||
I18n.t("composer.reply_here") +
|
||||
"<br/><div class='topic-title overflow-ellipsis'>" +
|
||||
currentTopic.get("fancyTitle") +
|
||||
"</div>",
|
||||
class: "btn-reply-here",
|
||||
callback: () => {
|
||||
composer.setProperties({ topic: currentTopic, post: null });
|
||||
this.save(true);
|
||||
},
|
||||
this.dialog.alert({
|
||||
title: I18n.t("composer.posting_not_on_topic"),
|
||||
buttons: [
|
||||
{
|
||||
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",
|
||||
action: () => this.save(true),
|
||||
},
|
||||
{
|
||||
label:
|
||||
I18n.t("composer.reply_here") +
|
||||
"<br/><div class='topic-title overflow-ellipsis'>" +
|
||||
currentTopic.get("fancyTitle") +
|
||||
"</div>",
|
||||
class: "btn-reply-here",
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -987,8 +983,11 @@ export default Controller.extend({
|
|||
// TODO: await this:
|
||||
this.destroyDraft();
|
||||
if (result.responseJson.message) {
|
||||
return bootbox.alert(result.responseJson.message, () => {
|
||||
DiscourseURL.routeTo(result.responseJson.route_to);
|
||||
return this.dialog.alert({
|
||||
message: result.responseJson.message,
|
||||
didConfirm: () => {
|
||||
DiscourseURL.routeTo(result.responseJson.route_to);
|
||||
},
|
||||
});
|
||||
}
|
||||
return DiscourseURL.routeTo(result.responseJson.route_to);
|
||||
|
@ -1010,7 +1009,9 @@ export default Controller.extend({
|
|||
.catch((error) => {
|
||||
composer.set("disableDrafts", false);
|
||||
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) => {
|
||||
bootbox.dialog(I18n.t("drafts.abandon.confirm"), [
|
||||
{
|
||||
label: I18n.t("drafts.abandon.no_value"),
|
||||
callback: () => resolve(data),
|
||||
},
|
||||
{
|
||||
label: I18n.t("drafts.abandon.yes_value"),
|
||||
class: "btn-danger",
|
||||
icon: iconHTML("far-trash-alt"),
|
||||
callback: () => {
|
||||
this.destroyDraft(data.draft_sequence).finally(() => {
|
||||
data.draft = null;
|
||||
resolve(data);
|
||||
});
|
||||
this.dialog.alert({
|
||||
message: I18n.t("drafts.abandon.confirm"),
|
||||
buttons: [
|
||||
{
|
||||
label: I18n.t("drafts.abandon.yes_value"),
|
||||
class: "btn-danger",
|
||||
icon: "far-trash-alt",
|
||||
action: () => {
|
||||
this.destroyDraft(data.draft_sequence).finally(() => {
|
||||
data.draft = null;
|
||||
resolve(data);
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
{
|
||||
label: I18n.t("drafts.abandon.no_value"),
|
||||
class: "btn-resume-editing",
|
||||
action: () => resolve(data),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import I18n from "I18n";
|
||||
import bootbox from "bootbox";
|
||||
import logout from "discourse/lib/logout";
|
||||
|
||||
let _showingLogout = false;
|
||||
|
@ -10,25 +9,27 @@ export default {
|
|||
after: "message-bus",
|
||||
|
||||
initialize(container) {
|
||||
const messageBus = container.lookup("service:message-bus");
|
||||
messageBus.subscribe("/logout", () => {
|
||||
if (_showingLogout) {
|
||||
return;
|
||||
const messageBus = container.lookup("service:message-bus"),
|
||||
dialog = container.lookup("service:dialog");
|
||||
|
||||
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;
|
||||
|
||||
bootbox.dialog(
|
||||
I18n.t("logout"),
|
||||
{
|
||||
label: I18n.t("home"),
|
||||
callback: logout,
|
||||
},
|
||||
{
|
||||
onEscape: logout,
|
||||
backdrop: "static",
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ import RestModel from "discourse/models/rest";
|
|||
import Site from "discourse/models/site";
|
||||
import Topic from "discourse/models/topic";
|
||||
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 { isEmpty } from "@ember/utils";
|
||||
import { propertyNotEqual } from "discourse/lib/computed";
|
||||
|
@ -119,6 +119,7 @@ export const SAVE_ICONS = {
|
|||
};
|
||||
|
||||
const Composer = RestModel.extend({
|
||||
dialog: service(),
|
||||
_categoryId: null,
|
||||
unlistTopic: false,
|
||||
noBump: false,
|
||||
|
@ -453,7 +454,9 @@ const Composer = RestModel.extend({
|
|||
const category = this.category;
|
||||
if (category && category.topic_template) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1277,28 +1280,23 @@ const Composer = RestModel.extend({
|
|||
) {
|
||||
const json = e.jqXHR.responseJSON;
|
||||
draftStatus = json.errors[0];
|
||||
if (json.extras && json.extras.description) {
|
||||
const buttons = [];
|
||||
|
||||
// ignore and force save draft
|
||||
buttons.push({
|
||||
label: I18n.t("composer.ignore"),
|
||||
class: "btn",
|
||||
callback: () => {
|
||||
this.set("draftForceSave", true);
|
||||
},
|
||||
if (json.extras?.description) {
|
||||
this.dialog.alert({
|
||||
message: json.extras.description,
|
||||
buttons: [
|
||||
{
|
||||
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({
|
||||
|
|
|
@ -182,9 +182,9 @@ acceptance("Composer", function (needs) {
|
|||
await fillIn("#reply-title", "this title triggers an error");
|
||||
await fillIn(".d-editor-input", "this is the *content* of a post");
|
||||
await click("#reply-control button.create");
|
||||
assert.ok(exists(".bootbox.modal"), "it pops up an error message");
|
||||
await click(".bootbox.modal a.btn-primary");
|
||||
assert.ok(!exists(".bootbox.modal"), "it dismisses the error");
|
||||
assert.ok(exists(".dialog-body"), "it pops up an error message");
|
||||
await click(".dialog-footer .btn-primary");
|
||||
assert.ok(!exists(".dialog-body"), "it dismisses the error");
|
||||
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(".d-editor-input", "custom message");
|
||||
await click("#reply-control button.create");
|
||||
|
||||
assert.strictEqual(
|
||||
query(".bootbox .modal-body").innerText,
|
||||
query("#dialog-holder .dialog-body").innerText,
|
||||
"This is a custom response"
|
||||
);
|
||||
assert.strictEqual(currentURL(), "/", "it doesn't change routes");
|
||||
|
||||
await click(".bootbox .btn-primary");
|
||||
await click(".dialog-footer .btn-primary");
|
||||
assert.strictEqual(
|
||||
currentURL(),
|
||||
"/faq",
|
||||
|
@ -764,11 +765,11 @@ acceptance("Composer", function (needs) {
|
|||
await click(".topic-post:nth-of-type(1) button.edit");
|
||||
|
||||
assert.strictEqual(
|
||||
query(".modal-body").innerText,
|
||||
query(".dialog-body").innerText,
|
||||
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) {
|
||||
|
@ -826,7 +827,7 @@ acceptance("Composer", function (needs) {
|
|||
|
||||
await visit("/u/charlie");
|
||||
await click("button.compose-pm");
|
||||
await click(".modal .btn-default");
|
||||
await click(".dialog-footer .btn-resume-editing");
|
||||
|
||||
const privateMessageUsers = selectKit("#private-message-users");
|
||||
assert.strictEqual(privateMessageUsers.header().value(), "codinghorror");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import I18n from "I18n";
|
||||
import EmberObject from "@ember/object";
|
||||
import User from "discourse/models/user";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
@ -6,10 +7,12 @@ import userFixtures from "discourse/tests/fixtures/user-fixtures";
|
|||
import {
|
||||
acceptance,
|
||||
exists,
|
||||
publishToMessageBus,
|
||||
query,
|
||||
queryAll,
|
||||
updateCurrentUser,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import * as logout from "discourse/lib/logout";
|
||||
import { click, currentRouteName, visit } from "@ember/test-helpers";
|
||||
import { cloneJSON } from "discourse-common/lib/object";
|
||||
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");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
|
||||
.dialog-close {
|
||||
margin-left: auto;
|
||||
flex-basis: content;
|
||||
.d-icon {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
|
|
@ -278,15 +278,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.bootbox.modal.reply-where-modal {
|
||||
max-width: 400px;
|
||||
margin-left: -200px;
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: var(--font-up-2);
|
||||
}
|
||||
|
||||
.reply-where-modal {
|
||||
.btn {
|
||||
display: block;
|
||||
text-align: left;
|
||||
|
|
Loading…
Reference in New Issue