DEV: Refactor the last few bootbox dialogs (#18416)

This commit is contained in:
Penar Musaraj
2022-10-07 11:38:27 -04:00
committed by GitHub
parent 6426932834
commit a1d67122b1
34 changed files with 331 additions and 333 deletions

View File

@ -1,9 +1,9 @@
import Category from "discourse/models/category"; import Category from "discourse/models/category";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import { bufferedProperty } from "discourse/mixins/buffered-content"; import { bufferedProperty } from "discourse/mixins/buffered-content";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { or } from "@ember/object/computed"; import { or } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
@ -13,6 +13,7 @@ export default Component.extend(bufferedProperty("host"), {
tagName: "tr", tagName: "tr",
categoryId: null, categoryId: null,
category: null, category: null,
dialog: service(),
editing: or("host.isNew", "editToggled"), editing: or("host.isNew", "editToggled"),
@ -61,12 +62,13 @@ export default Component.extend(bufferedProperty("host"), {
}, },
delete() { delete() {
bootbox.confirm(I18n.t("admin.embedding.confirm_delete"), (result) => { return this.dialog.confirm({
if (result) { message: I18n.t("admin.embedding.confirm_delete"),
this.host.destroyRecord().then(() => { didConfirm: () => {
return this.host.destroyRecord().then(() => {
this.deleteHost(this.host); this.deleteHost(this.host);
}); });
} },
}); });
}, },

View File

@ -1,13 +1,14 @@
import Controller, { inject as controller } from "@ember/controller"; import Controller, { inject as controller } from "@ember/controller";
import I18n from "I18n"; import I18n from "I18n";
import { action } from "@ember/object"; import { action } from "@ember/object";
import bootbox from "bootbox";
import { bufferedProperty } from "discourse/mixins/buffered-content"; import { bufferedProperty } from "discourse/mixins/buffered-content";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service";
export default Controller.extend(bufferedProperty("emailTemplate"), { export default Controller.extend(bufferedProperty("emailTemplate"), {
adminCustomizeEmailTemplates: controller(), adminCustomizeEmailTemplates: controller(),
dialog: service(),
emailTemplate: null, emailTemplate: null,
saved: false, saved: false,
@ -42,11 +43,11 @@ export default Controller.extend(bufferedProperty("emailTemplate"), {
@action @action
revertChanges() { revertChanges() {
this.set("saved", false); this.set("saved", false);
bootbox.confirm(
I18n.t("admin.customize.email_templates.revert_confirm"), this.dialog.yesNoConfirm({
(result) => { title: I18n.t("admin.customize.email_templates.revert_confirm"),
if (result) { didConfirm: () => {
this.emailTemplate return this.emailTemplate
.revert() .revert()
.then((props) => { .then((props) => {
const buffered = this.buffered; const buffered = this.buffered;
@ -54,8 +55,7 @@ export default Controller.extend(bufferedProperty("emailTemplate"), {
this.commitBuffer(); this.commitBuffer();
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
} },
} });
);
}, },
}); });

View File

@ -10,7 +10,6 @@ import Controller from "@ember/controller";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import ThemeSettings from "admin/models/theme-settings"; import ThemeSettings from "admin/models/theme-settings";
import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
@ -306,14 +305,10 @@ export default Controller.extend({
editTheme() { editTheme() {
if (this.get("model.remote_theme.is_git")) { if (this.get("model.remote_theme.is_git")) {
bootbox.confirm( this.dialog.confirm({
I18n.t("admin.customize.theme.edit_confirm"), message: I18n.t("admin.customize.theme.edit_confirm"),
(result) => { didConfirm: () => this.transitionToEditRoute(),
if (result) { });
this.transitionToEditRoute();
}
}
);
} else { } else {
this.transitionToEditRoute(); this.transitionToEditRoute();
} }

View File

@ -1,12 +1,13 @@
import { gte, sort } from "@ember/object/computed"; import { gte, sort } from "@ember/object/computed";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service";
const MAX_FIELDS = 30; const MAX_FIELDS = 30;
export default Controller.extend({ export default Controller.extend({
dialog: service(),
fieldTypes: null, fieldTypes: null,
createDisabled: gte("model.length", MAX_FIELDS), createDisabled: gte("model.length", MAX_FIELDS),
sortedFields: sort("model", "fieldSortOrder"), sortedFields: sort("model", "fieldSortOrder"),
@ -53,18 +54,17 @@ export default Controller.extend({
// Only confirm if we already been saved // Only confirm if we already been saved
if (f.get("id")) { if (f.get("id")) {
bootbox.confirm( this.dialog.yesNoConfirm({
I18n.t("admin.user_fields.delete_confirm"), message: I18n.t("admin.user_fields.delete_confirm"),
function (result) { didConfirm: () => {
if (result) { return f
f.destroyRecord() .destroyRecord()
.then(function () { .then(function () {
model.removeObject(f); model.removeObject(f);
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
} },
} });
);
} else { } else {
model.removeObject(f); model.removeObject(f);
} }

View File

@ -2,11 +2,12 @@ import I18n from "I18n";
import Mixin from "@ember/object/mixin"; import Mixin from "@ember/object/mixin";
import ModalFunctionality from "discourse/mixins/modal-functionality"; import ModalFunctionality from "discourse/mixins/modal-functionality";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import bootbox from "bootbox";
import { extractError } from "discourse/lib/ajax-error"; import { extractError } from "discourse/lib/ajax-error";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
import { inject as service } from "@ember/service";
export default Mixin.create(ModalFunctionality, { export default Mixin.create(ModalFunctionality, {
dialog: service(),
errorMessage: null, errorMessage: null,
reason: null, reason: null,
message: null, message: null,
@ -40,15 +41,15 @@ export default Mixin.create(ModalFunctionality, {
(this.message && this.message.length > 1)) (this.message && this.message.length > 1))
) { ) {
this.send("hideModal"); this.send("hideModal");
bootbox.confirm(I18n.t("admin.user.confirm_cancel_penalty"), (result) => { this.dialog.confirm({
if (result) { message: I18n.t("admin.user.confirm_cancel_penalty"),
didConfirm: () => {
next(() => { next(() => {
this.set("confirmClose", true); this.set("confirmClose", true);
this.send("closeModal"); this.send("closeModal");
}); });
} else { },
next(() => this.send("reopenModal")); didCancel: () => this.send("reopenModal"),
}
}); });
return false; return false;
} }

View File

@ -1,8 +1,9 @@
import I18n from "I18n"; import I18n from "I18n";
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import bootbox from "bootbox"; import { inject as service } from "@ember/service";
export default Route.extend({ export default Route.extend({
dialog: service(),
model(params) { model(params) {
return { return {
model: this.modelFor("adminCustomizeEmailStyle"), model: this.modelFor("adminCustomizeEmailStyle"),
@ -26,17 +27,15 @@ export default Route.extend({
transition.intent.name !== this.routeName transition.intent.name !== this.routeName
) { ) {
transition.abort(); transition.abort();
bootbox.confirm( this.dialog.confirm({
I18n.t("admin.customize.theme.unsaved_changes_alert"), message: I18n.t("admin.customize.theme.unsaved_changes_alert"),
I18n.t("admin.customize.theme.discard"), confirmButtonLabel: "admin.customize.theme.discard",
I18n.t("admin.customize.theme.stay"), cancelButtonLabel: "admin.customize.theme.stay",
(result) => { didConfirm: () => {
if (!result) {
this._shouldAlertUnsavedChanges = false; this._shouldAlertUnsavedChanges = false;
transition.retry(); transition.retry();
} },
} });
);
} }
}, },
}, },

View File

@ -1,8 +1,10 @@
import I18n from "I18n"; import I18n from "I18n";
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import bootbox from "bootbox"; import { inject as service } from "@ember/service";
export default Route.extend({ export default Route.extend({
dialog: service(),
model(params) { model(params) {
const all = this.modelFor("adminCustomizeThemes"); const all = this.modelFor("adminCustomizeThemes");
const model = all.findBy("id", parseInt(params.theme_id, 10)); const model = all.findBy("id", parseInt(params.theme_id, 10));
@ -56,17 +58,16 @@ export default Route.extend({
transition.intent.name !== this.routeName transition.intent.name !== this.routeName
) { ) {
transition.abort(); transition.abort();
bootbox.confirm(
I18n.t("admin.customize.theme.unsaved_changes_alert"), this.dialog.confirm({
I18n.t("admin.customize.theme.discard"), message: I18n.t("admin.customize.theme.unsaved_changes_alert"),
I18n.t("admin.customize.theme.stay"), confirmButtonLabel: "admin.customize.theme.discard",
(result) => { cancelButtonLabel: "admin.customize.theme.stay",
if (!result) { didConfirm: () => {
this.set("shouldAlertUnsavedChanges", false); this.set("shouldAlertUnsavedChanges", false);
transition.retry(); transition.retry();
} },
} });
);
} }
}, },
}, },

View File

@ -2,23 +2,11 @@ import { COMPONENTS, THEMES } from "admin/models/theme";
import I18n from "I18n"; import I18n from "I18n";
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import { scrollTop } from "discourse/mixins/scroll-top"; import { scrollTop } from "discourse/mixins/scroll-top";
import bootbox from "bootbox"; import { inject as service } from "@ember/service";
export function showUnassignedComponentWarning(theme, callback) {
bootbox.confirm(
I18n.t("admin.customize.theme.unsaved_parent_themes"),
I18n.t("admin.customize.theme.discard"),
I18n.t("admin.customize.theme.stay"),
(result) => {
if (!result) {
theme.set("recentlyInstalled", false);
}
callback(result);
}
);
}
export default Route.extend({ export default Route.extend({
dialog: service(),
serialize(model) { serialize(model) {
return { theme_id: model.get("id") }; return { theme_id: model.get("id") };
}, },
@ -72,10 +60,14 @@ export default Route.extend({
const model = this.controller.model; const model = this.controller.model;
if (model.warnUnassignedComponent) { if (model.warnUnassignedComponent) {
transition.abort(); transition.abort();
showUnassignedComponentWarning(model, (result) => {
if (!result) { this.dialog.yesNoConfirm({
message: I18n.t("admin.customize.theme.unsaved_parent_themes"),
didConfirm: () => {
model.set("recentlyInstalled", false);
transition.retry(); transition.retry();
} },
didCancel: () => model.set("recentlyInstalled", false),
}); });
} }
}, },

View File

@ -1,9 +1,12 @@
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import I18n from "I18n";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
import { showUnassignedComponentWarning } from "admin/routes/admin-customize-themes-show"; import { inject as service } from "@ember/service";
export default Route.extend({ export default Route.extend({
dialog: service(),
queryParams: { queryParams: {
repoUrl: null, repoUrl: null,
repoName: null, repoName: null,
@ -35,11 +38,13 @@ export default Route.extend({
const currentTheme = this.controllerFor( const currentTheme = this.controllerFor(
"adminCustomizeThemes.show" "adminCustomizeThemes.show"
).model; ).model;
if (currentTheme && currentTheme.warnUnassignedComponent) { if (currentTheme?.warnUnassignedComponent) {
showUnassignedComponentWarning(currentTheme, (result) => { this.dialog.yesNoConfirm({
if (!result) { message: I18n.t("admin.customize.theme.unsaved_parent_themes"),
didConfirm: () => {
currentTheme.set("recentlyInstalled", false);
showModal("admin-install-theme", { admin: true }); showModal("admin-install-theme", { admin: true });
} },
}); });
} else { } else {
showModal("admin-install-theme", { admin: true }); showModal("admin-install-theme", { admin: true });

View File

@ -3,10 +3,9 @@ import I18n from "I18n";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import Service, { inject as service } from "@ember/service"; import Service, { inject as service } from "@ember/service";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import { getOwner } from "discourse-common/lib/get-owner"; import { getOwner } from "discourse-common/lib/get-owner";
import { iconHTML } from "discourse-common/lib/icon-library";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { htmlSafe } from "@ember/template";
// A service that can act as a bridge between the front end Discourse application // A service that can act as a bridge between the front end Discourse application
// and the admin application. Use this if you need front end code to access admin // and the admin application. Use this if you need front end code to access admin
@ -79,30 +78,27 @@ export default Service.extend({
: Promise.resolve(); : Promise.resolve();
return tryEmail.then(() => { return tryEmail.then(() => {
let message = I18n.messageFormat("flagging.delete_confirm_MF", { let message = htmlSafe(
I18n.messageFormat("flagging.delete_confirm_MF", {
POSTS: adminUser.get("post_count"), POSTS: adminUser.get("post_count"),
TOPICS: adminUser.get("topic_count"), TOPICS: adminUser.get("topic_count"),
email: email:
adminUser.get("email") || I18n.t("flagging.hidden_email_address"), adminUser.get("email") || I18n.t("flagging.hidden_email_address"),
ip_address: ip_address:
adminUser.get("ip_address") || I18n.t("flagging.ip_address_missing"), adminUser.get("ip_address") ||
}); I18n.t("flagging.ip_address_missing"),
})
);
let userId = adminUser.get("id"); let userId = adminUser.get("id");
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const buttons = [ this.dialog.deleteConfirm({
{ message,
label: I18n.t("composer.cancel"), class: "flagging-delete-spammer",
class: "d-modal-cancel", confirmButtonLabel: "flagging.yes_delete_spammer",
link: true, confirmButtonIcon: "exclamation-triangle",
}, didConfirm: () => {
{
label:
`${iconHTML("exclamation-triangle")} ` +
I18n.t("flagging.yes_delete_spammer"),
class: "btn btn-danger confirm-delete",
callback() {
return ajax(`/admin/users/${userId}.json`, { return ajax(`/admin/users/${userId}.json`, {
type: "DELETE", type: "DELETE",
data: { data: {
@ -126,11 +122,6 @@ export default Service.extend({
reject(); reject();
}); });
}, },
},
];
bootbox.dialog(message, buttons, {
classes: "flagging-delete-spammer",
}); });
}); });
}); });

View File

@ -1,7 +1,6 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { next, schedule } from "@ember/runloop"; import { next, schedule } from "@ember/runloop";
import bootbox from "bootbox";
import { openBookmarkModal } from "discourse/controllers/bookmark"; import { openBookmarkModal } from "discourse/controllers/bookmark";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { import {
@ -11,8 +10,10 @@ import {
import Scrolling from "discourse/mixins/scrolling"; import Scrolling from "discourse/mixins/scrolling";
import I18n from "I18n"; import I18n from "I18n";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import { inject as service } from "@ember/service";
export default Component.extend(Scrolling, { export default Component.extend(Scrolling, {
dialog: service(),
classNames: ["bookmark-list-wrapper"], classNames: ["bookmark-list-wrapper"],
didInsertElement() { didInsertElement() {
@ -64,12 +65,10 @@ export default Component.extend(Scrolling, {
if (!bookmark.reminder_at) { if (!bookmark.reminder_at) {
return deleteBookmark(); return deleteBookmark();
} }
bootbox.confirm(I18n.t("bookmarks.confirm_delete"), (result) => { this.dialog.deleteConfirm({
if (result) { message: I18n.t("bookmarks.confirm_delete"),
deleteBookmark(); didConfirm: () => deleteBookmark(),
} else { didCancel: () => resolve(false),
resolve(false);
}
}); });
}); });
}, },

View File

@ -11,7 +11,6 @@ import {
} from "discourse/lib/time-shortcut"; } from "discourse/lib/time-shortcut";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import discourseComputed, { bind } from "discourse-common/utils/decorators"; import discourseComputed, { bind } from "discourse-common/utils/decorators";
import { formattedReminderTime } from "discourse/lib/bookmark"; import { formattedReminderTime } from "discourse/lib/bookmark";
import { and, notEmpty } from "@ember/object/computed"; import { and, notEmpty } from "@ember/object/computed";
@ -377,10 +376,9 @@ export default Component.extend({
}; };
if (this.existingBookmarkHasReminder) { if (this.existingBookmarkHasReminder) {
bootbox.confirm(I18n.t("bookmarks.confirm_delete"), (result) => { this.dialog.deleteConfirm({
if (result) { message: I18n.t("bookmarks.confirm_delete"),
deleteAction(); didConfirm: () => deleteAction(),
}
}); });
} else { } else {
deleteAction(); deleteAction();

View File

@ -2,13 +2,13 @@ import Category from "discourse/models/category";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import { classify, dasherize } from "@ember/string"; import { classify, dasherize } from "@ember/string";
import discourseComputed, { bind } from "discourse-common/utils/decorators"; import discourseComputed, { bind } from "discourse-common/utils/decorators";
import optionalService from "discourse/lib/optional-service"; import optionalService from "discourse/lib/optional-service";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { action, set } from "@ember/object"; import { action, set } from "@ember/object";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { inject as service } from "@ember/service";
let _components = {}; let _components = {};
@ -22,6 +22,7 @@ export function addPluginReviewableParam(reviewableType, param) {
export default Component.extend({ export default Component.extend({
adminTools: optionalService(), adminTools: optionalService(),
dialog: service(),
tagName: "", tagName: "",
updating: null, updating: null,
editing: false, editing: false,
@ -269,14 +270,13 @@ export default Component.extend({
return; return;
} }
let msg = performableAction.get("confirm_message"); const message = performableAction.get("confirm_message");
let requireRejectReason = performableAction.get("require_reject_reason"); let requireRejectReason = performableAction.get("require_reject_reason");
let customModal = performableAction.get("custom_modal"); let customModal = performableAction.get("custom_modal");
if (msg) { if (message) {
bootbox.confirm(msg, (answer) => { this.dialog.confirm({
if (answer) { message,
return this._performConfirmed(performableAction); didConfirm: () => this._performConfirmed(performableAction),
}
}); });
} else if (requireRejectReason) { } else if (requireRejectReason) {
showModal("reject-reason-reviewable", { showModal("reject-reason-reviewable", {

View File

@ -1,10 +1,11 @@
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
export default Component.extend({ export default Component.extend({
tagName: "", tagName: "",
dialog: service(),
publishing: false, publishing: false,
@discourseComputed("topic.destination_category_id") @discourseComputed("topic.destination_category_id")
@ -18,11 +19,12 @@ export default Component.extend({
}, },
publish() { publish() {
bootbox.confirm(I18n.t("shared_drafts.confirm_publish"), (result) => { this.dialog.yesNoConfirm({
if (result) { message: I18n.t("shared_drafts.confirm_publish"),
didConfirm: () => {
this.set("publishing", true); this.set("publishing", true);
const destinationCategoryId = this.topic.destination_category_id; const destinationCategoryId = this.topic.destination_category_id;
this.topic return this.topic
.publish() .publish()
.then(() => { .then(() => {
this.topic.setProperties({ this.topic.setProperties({
@ -34,7 +36,7 @@ export default Component.extend({
.finally(() => { .finally(() => {
this.set("publishing", false); this.set("publishing", false);
}); });
} },
}); });
}, },
}, },

View File

@ -2,12 +2,12 @@ import { and, reads } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { htmlSafe } from "@ember/template";
export default Component.extend({ export default Component.extend({
dialog: service(), dialog: service(),
@ -100,19 +100,18 @@ export default Component.extend({
@action @action
deleteSynonym(tag, event) { deleteSynonym(tag, event) {
event?.preventDefault(); event?.preventDefault();
bootbox.confirm(
I18n.t("tagging.delete_synonym_confirm", { tag_name: tag.text }),
(result) => {
if (!result) {
return;
}
tag this.dialog.yesNoConfirm({
message: I18n.t("tagging.delete_synonym_confirm", {
tag_name: tag.text,
}),
didConfirm: () => {
return tag
.destroyRecord() .destroyRecord()
.then(() => this.tagInfo.synonyms.removeObject(tag)) .then(() => this.tagInfo.synonyms.removeObject(tag))
.catch(popupAjaxError); .catch(popupAjaxError);
} },
); });
}, },
actions: { actions: {
@ -146,17 +145,15 @@ export default Component.extend({
}, },
addSynonyms() { addSynonyms() {
bootbox.confirm( this.dialog.confirm({
message: htmlSafe(
I18n.t("tagging.add_synonyms_explanation", { I18n.t("tagging.add_synonyms_explanation", {
count: this.newSynonyms.length, count: this.newSynonyms.length,
tag_name: this.tagInfo.name, tag_name: this.tagInfo.name,
}), })
(result) => { ),
if (!result) { didConfirm: () => {
return; return ajax(`/tag/${this.tagInfo.name}/synonyms`, {
}
ajax(`/tag/${this.tagInfo.name}/synonyms`, {
type: "POST", type: "POST",
data: { data: {
synonyms: this.newSynonyms, synonyms: this.newSynonyms,
@ -177,8 +174,8 @@ export default Component.extend({
} }
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
} },
); });
}, },
}, },
}); });

View File

@ -2,15 +2,16 @@ import Controller from "@ember/controller";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import { cookAsync } from "discourse/lib/text"; import { cookAsync } from "discourse/lib/text";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { readOnly } from "@ember/object/computed"; import { readOnly } from "@ember/object/computed";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { inject as service } from "@ember/service";
export default Controller.extend({ export default Controller.extend({
dialog: service(),
init() { init() {
this._super(...arguments); this._super(...arguments);
this.saveAttrNames = [ this.saveAttrNames = [
@ -79,20 +80,18 @@ export default Controller.extend({
}, },
clearFeaturedTopicFromProfile() { clearFeaturedTopicFromProfile() {
bootbox.confirm( this.dialog.yesNoConfirm({
I18n.t("user.feature_topic_on_profile.clear.warning"), message: I18n.t("user.feature_topic_on_profile.clear.warning"),
(result) => { didConfirm: () => {
if (result) { return ajax(`/u/${this.model.username}/clear-featured-topic`, {
ajax(`/u/${this.model.username}/clear-featured-topic`, {
type: "PUT", type: "PUT",
}) })
.then(() => { .then(() => {
this.model.set("featured_topic", null); this.model.set("featured_topic", null);
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
} },
} });
);
}, },
useCurrentTimezone() { useCurrentTimezone() {

View File

@ -5,14 +5,14 @@ import I18n from "I18n";
import { SECOND_FACTOR_METHODS } from "discourse/models/user"; import { SECOND_FACTOR_METHODS } from "discourse/models/user";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { findAll } from "discourse/models/login-method"; import { findAll } from "discourse/models/login-method";
import { iconHTML } from "discourse-common/lib/icon-library";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { inject as service } from "@ember/service";
export default Controller.extend(CanCheckEmails, { export default Controller.extend(CanCheckEmails, {
dialog: service(),
loading: false, loading: false,
dirty: false, dirty: false,
resetPasswordLoading: false, resetPasswordLoading: false,
@ -127,34 +127,21 @@ export default Controller.extend(CanCheckEmails, {
if (this.loading) { if (this.loading) {
return; return;
} }
const message = I18n.t("user.second_factor.disable_confirm");
const buttons = [ this.dialog.deleteConfirm({
{ title: I18n.t("user.second_factor.disable_confirm"),
label: I18n.t("cancel"), confirmButtonLabel: "user.second_factor.disable",
class: "d-modal-cancel", confirmButtonIcon: "ban",
link: true, didConfirm: () => {
},
{
icon: iconHTML("ban"),
label: I18n.t("user.second_factor.disable"),
class: "btn-danger btn-icon-text",
callback: () => {
this.model this.model
.disableAllSecondFactors() .disableAllSecondFactors()
.then(() => { .then(() => {
const usernameLower = this.model.username.toLowerCase(); const usernameLower = this.model.username.toLowerCase();
DiscourseURL.redirectTo( DiscourseURL.redirectTo(userPath(`${usernameLower}/preferences`));
userPath(`${usernameLower}/preferences`)
);
}) })
.catch((e) => this.handleError(e)) .catch((e) => this.handleError(e))
.finally(() => this.set("loading", false)); .finally(() => this.set("loading", false));
}, },
},
];
bootbox.dialog(message, buttons, {
classes: "disable-second-factor-modal",
}); });
}, },

View File

@ -7,7 +7,6 @@ import I18n from "I18n";
import NavItem from "discourse/models/nav-item"; import NavItem from "discourse/models/nav-item";
import Topic from "discourse/models/topic"; import Topic from "discourse/models/topic";
import { readOnly } from "@ember/object/computed"; import { readOnly } from "@ember/object/computed";
import bootbox from "bootbox";
import { endWith } from "discourse/lib/computed"; import { endWith } from "discourse/lib/computed";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
@ -167,15 +166,14 @@ export default DiscoverySortableController.extend(
}); });
} }
bootbox.confirm(confirmText, (result) => { this.dialog.deleteConfirm({
if (!result) { message: confirmText,
return; didConfirm: () => {
} return this.tag
this.tag
.destroyRecord() .destroyRecord()
.then(() => this.transitionToRoute("tags.index")) .then(() => this.transitionToRoute("tags.index"))
.catch(() => this.dialog.alert(I18n.t("generic_error"))); .catch(() => this.dialog.alert(I18n.t("generic_error")));
},
}); });
}, },

View File

@ -3,7 +3,6 @@ import { alias, notEmpty } from "@ember/object/computed";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import I18n from "I18n"; import I18n from "I18n";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
@ -91,23 +90,20 @@ export default Controller.extend({
tags: joinedTags, tags: joinedTags,
}); });
const string = I18n.t("tagging.delete_unused_confirmation", { const message = I18n.t("tagging.delete_unused_confirmation", {
count: tags.length, count: tags.length,
tags: tagsString, tags: tagsString,
}); });
bootbox.confirm( this.dialog.deleteConfirm({
string, message,
I18n.t("tagging.cancel_delete_unused"), confirmButtonLabel: "tagging.delete_unused",
I18n.t("tagging.delete_unused"), didConfirm: () => {
(proceed) => { return ajax("/tags/unused", { type: "DELETE" })
if (proceed) {
ajax("/tags/unused", { type: "DELETE" })
.then(() => this.send("triggerRefresh")) .then(() => this.send("triggerRefresh"))
.catch(popupAjaxError); .catch(popupAjaxError);
} },
} });
);
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
}, },

View File

@ -4,7 +4,6 @@ import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality"; import ModalFunctionality from "discourse/mixins/modal-functionality";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import Topic from "discourse/models/topic"; import Topic from "discourse/models/topic";
import bootbox from "bootbox";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
@ -320,16 +319,12 @@ export default Controller.extend(ModalFunctionality, {
}, },
removeTags() { removeTags() {
bootbox.confirm( this.dialog.deleteConfirm({
I18n.t("topics.bulk.confirm_remove_tags", { message: I18n.t("topics.bulk.confirm_remove_tags", {
count: this.get("model.topics").length, count: this.get("model.topics").length,
}), }),
(result) => { didConfirm: () => this.performAndRefresh({ type: "remove_tags" }),
if (result) { });
this.performAndRefresh({ type: "remove_tags" });
}
}
);
}, },
}, },
}); });

View File

@ -1,7 +1,6 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { equal, reads } from "@ember/object/computed"; import { equal, reads } from "@ember/object/computed";
import bootbox from "bootbox";
import { INPUT_DELAY } from "discourse-common/config/environment"; import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
@ -9,8 +8,10 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import Invite from "discourse/models/invite"; import Invite from "discourse/models/invite";
import I18n from "I18n"; import I18n from "I18n";
import { inject as service } from "@ember/service";
export default Controller.extend({ export default Controller.extend({
dialog: service(),
user: null, user: null,
model: null, model: null,
filter: null, filter: null,
@ -93,15 +94,16 @@ export default Controller.extend({
@action @action
destroyAllExpired() { destroyAllExpired() {
bootbox.confirm(I18n.t("user.invited.remove_all_confirm"), (confirm) => { this.dialog.deleteConfirm({
if (confirm) { message: I18n.t("user.invited.remove_all_confirm"),
Invite.destroyAllExpired() didConfirm: () => {
return Invite.destroyAllExpired()
.then(() => { .then(() => {
this.set("removedAll", true); this.set("removedAll", true);
this.send("triggerRefresh"); this.send("triggerRefresh");
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
} },
}); });
}, },
@ -113,12 +115,13 @@ export default Controller.extend({
@action @action
reinviteAll() { reinviteAll() {
bootbox.confirm(I18n.t("user.invited.reinvite_all_confirm"), (confirm) => { this.dialog.yesNoConfirm({
if (confirm) { message: I18n.t("user.invited.reinvite_all_confirm"),
Invite.reinviteAll() didConfirm: () => {
return Invite.reinviteAll()
.then(() => this.set("reinvitedAll", true)) .then(() => this.set("reinvitedAll", true))
.catch(popupAjaxError); .catch(popupAjaxError);
} },
}); });
}, },

View File

@ -1,6 +1,5 @@
import { avatarFor, avatarImg } from "discourse/widgets/post"; import { avatarFor, avatarImg } from "discourse/widgets/post";
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
import { h } from "virtual-dom"; import { h } from "virtual-dom";
@ -10,18 +9,16 @@ import { makeArray } from "discourse-common/lib/helpers";
createWidget("pm-remove-group-link", { createWidget("pm-remove-group-link", {
tagName: "a.remove-invited.no-text.btn-icon.btn", tagName: "a.remove-invited.no-text.btn-icon.btn",
template: hbs`{{d-icon "times"}}`, template: hbs`{{d-icon "times"}}`,
services: ["dialog"],
click() { click() {
bootbox.confirm( this.dialog.deleteConfirm({
I18n.t("private_message_info.remove_allowed_group", { message: I18n.t("private_message_info.remove_allowed_group", {
name: this.attrs.name, name: this.attrs.name,
}), }),
(confirmed) => { confirmButtonLabel: "private_message_info.remove_group",
if (confirmed) { didConfirm: () => this.sendWidgetAction("removeAllowedGroup", this.attrs),
this.sendWidgetAction("removeAllowedGroup", this.attrs); });
}
}
);
}, },
}); });
@ -48,22 +45,23 @@ createWidget("pm-map-user-group", {
createWidget("pm-remove-link", { createWidget("pm-remove-link", {
tagName: "a.remove-invited.no-text.btn-icon.btn", tagName: "a.remove-invited.no-text.btn-icon.btn",
template: hbs`{{d-icon "times"}}`, template: hbs`{{d-icon "times"}}`,
services: ["dialog"],
click() { click() {
const messageKey = this.attrs.isCurrentUser const messageKey = this.attrs.isCurrentUser
? "leave_message" ? "leave_message"
: "remove_allowed_user"; : "remove_allowed_user";
bootbox.confirm( this.dialog.deleteConfirm({
I18n.t(`private_message_info.${messageKey}`, { message: I18n.t(`private_message_info.${messageKey}`, {
name: this.attrs.user.username, name: this.attrs.user.username,
}), }),
(confirmed) => { confirmButtonLabel: this.attrs.isCurrentUser
if (confirmed) { ? "private_message_info.leave"
this.sendWidgetAction("removeAllowedUser", this.attrs.user); : "private_message_info.remove_user",
} didConfirm: () =>
} this.sendWidgetAction("removeAllowedUser", this.attrs.user),
); });
}, },
}); });

View File

@ -21,7 +21,7 @@
{{#each this.dialog.buttons as |button|}} {{#each this.dialog.buttons as |button|}}
<DButton @icon={{button.icon}} @class={{button.class}} @action={{action "handleButtonAction" button}} @translatedLabel={{button.label}} /> <DButton @icon={{button.icon}} @class={{button.class}} @action={{action "handleButtonAction" button}} @translatedLabel={{button.label}} />
{{else}} {{else}}
<DButton @class="btn-primary" @action={{this.dialog.didConfirmWrapped}} @icon={{this.dialog.confirmButtonIcon}} @label={{this.dialog.confirmButtonLabel}} /> <DButton @class={{this.dialog.confirmButtonClass}} @action={{this.dialog.didConfirmWrapped}} @icon={{this.dialog.confirmButtonIcon}} @label={{this.dialog.confirmButtonLabel}} />
{{#if this.dialog.shouldDisplayCancel}} {{#if this.dialog.shouldDisplayCancel}}
<DButton @class="btn-default" @action={{this.dialog.cancel}} @label={{this.dialog.cancelButtonLabel}} /> <DButton @class="btn-default" @action={{this.dialog.cancel}} @label={{this.dialog.cancelButtonLabel}} />
{{/if}} {{/if}}

View File

@ -12,6 +12,7 @@ export default Service.extend({
confirmButtonIcon: null, confirmButtonIcon: null,
confirmButtonLabel: null, confirmButtonLabel: null,
confirmButtonClass: null,
cancelButtonLabel: null, cancelButtonLabel: null,
shouldDisplayCancel: null, shouldDisplayCancel: null,
@ -29,6 +30,7 @@ export default Service.extend({
confirmButtonIcon, confirmButtonIcon,
confirmButtonLabel = "ok_value", confirmButtonLabel = "ok_value",
confirmButtonClass = "btn-primary",
cancelButtonLabel = "cancel_value", cancelButtonLabel = "cancel_value",
shouldDisplayCancel, shouldDisplayCancel,
@ -47,6 +49,7 @@ export default Service.extend({
title, title,
titleElementId: title !== null ? "dialog-title" : null, titleElementId: title !== null ? "dialog-title" : null,
confirmButtonClass,
confirmButtonLabel, confirmButtonLabel,
confirmButtonIcon, confirmButtonIcon,
cancelButtonLabel, cancelButtonLabel,
@ -108,6 +111,14 @@ export default Service.extend({
}); });
}, },
deleteConfirm(params) {
return this.confirm({
...params,
confirmButtonClass: "btn-danger",
confirmButtonLabel: params.confirmButtonLabel || "delete",
});
},
reset() { reset() {
this.setProperties({ this.setProperties({
message: null, message: null,

View File

@ -54,9 +54,9 @@ acceptance("Admin - Suspend User", function (needs) {
await click(".d-modal-cancel"); await click(".d-modal-cancel");
assert.strictEqual(count(".bootbox.modal:visible"), 1); assert.strictEqual(count(".dialog-body:visible"), 1);
await click(".modal-footer .btn-default"); await click(".dialog-footer .btn-default");
assert.strictEqual(count(".suspend-user-modal:visible"), 1); assert.strictEqual(count(".suspend-user-modal:visible"), 1);
assert.strictEqual( assert.strictEqual(
query(".suspend-message").value, query(".suspend-message").value,
@ -64,11 +64,11 @@ acceptance("Admin - Suspend User", function (needs) {
); );
await click(".d-modal-cancel"); await click(".d-modal-cancel");
assert.strictEqual(count(".bootbox.modal:visible"), 1); assert.strictEqual(count(".dialog-body:visible"), 1);
assert.ok(!exists(".suspend-user-modal:visible")); assert.ok(!exists(".suspend-user-modal:visible"));
await click(".modal-footer .btn-primary"); await click(".dialog-footer .btn-primary");
assert.ok(!exists(".bootbox.modal:visible")); assert.ok(!exists(".dialog-body:visible"));
}); });
test("suspend, then unsuspend a user", async function (assert) { test("suspend, then unsuspend a user", async function (assert) {

View File

@ -215,15 +215,15 @@ acceptance("Bookmarking", function (needs) {
await click("#delete-bookmark"); await click("#delete-bookmark");
assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); assert.ok(exists(".dialog-body"), "it asks for delete confirmation");
assert.ok( assert.ok(
query(".bootbox.modal").innerText.includes( query(".dialog-body").innerText.includes(
I18n.t("bookmarks.confirm_delete") I18n.t("bookmarks.confirm_delete")
), ),
"it shows delete confirmation message" "it shows delete confirmation message"
); );
await click(".bootbox.modal .btn-primary"); await click(".dialog-footer .btn-danger");
assert.notOk( assert.notOk(
exists(".topic-post:first-child button.bookmark.bookmarked"), exists(".topic-post:first-child button.bookmark.bookmarked"),
@ -444,15 +444,15 @@ acceptance("Bookmarking", function (needs) {
await click("#topic-footer-button-bookmark"); await click("#topic-footer-button-bookmark");
await click("#delete-bookmark"); await click("#delete-bookmark");
assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); assert.ok(exists(".dialog-body"), "it asks for delete confirmation");
assert.ok( assert.ok(
query(".bootbox.modal").innerText.includes( query(".dialog-body").innerText.includes(
I18n.t("bookmarks.confirm_delete") I18n.t("bookmarks.confirm_delete")
), ),
"it shows delete confirmation message" "it shows delete confirmation message"
); );
await click(".bootbox.modal .btn-primary"); await click(".dialog-footer .btn-danger");
assert.strictEqual( assert.strictEqual(
query("#topic-footer-button-bookmark").innerText, query("#topic-footer-button-bookmark").innerText,

View File

@ -150,7 +150,7 @@ acceptance("Composer Actions", function (needs) {
const composerActions = selectKit(".composer-actions"); const composerActions = selectKit(".composer-actions");
await composerActions.expand(); await composerActions.expand();
await composerActions.selectRowByValue("reply_as_new_topic"); await composerActions.selectRowByValue("reply_as_new_topic");
assert.ok(!exists(".bootbox")); assert.ok(!exists(".dialog-body"));
}); });
test("reply_as_new_group_message", async function (assert) { test("reply_as_new_group_message", async function (assert) {
@ -471,10 +471,10 @@ acceptance("Composer Actions With New Topic Draft", function (needs) {
await composerActions.selectRowByValue("reply_as_new_topic"); await composerActions.selectRowByValue("reply_as_new_topic");
assert.strictEqual( assert.strictEqual(
query(".bootbox .modal-body").innerText, query(".dialog-body").innerText.trim(),
I18n.t("composer.composer_actions.reply_as_new_topic.confirm") I18n.t("composer.composer_actions.reply_as_new_topic.confirm")
); );
await click(".modal-footer .btn.btn-primary"); await click(".dialog-footer .btn-primary");
assert.ok( assert.ok(
query(".d-editor-input").value.startsWith( query(".d-editor-input").value.startsWith(

View File

@ -223,7 +223,7 @@ acceptance("Composer", function (needs) {
assert.ok(exists(".d-modal"), "it pops up a confirmation dialog"); assert.ok(exists(".d-modal"), "it pops up a confirmation dialog");
await click(".modal-footer .discard-draft"); await click(".modal-footer .discard-draft");
assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled"); assert.ok(!exists(".modal-body"), "the confirmation can be cancelled");
}); });
test("Create a topic with server side errors", async function (assert) { test("Create a topic with server side errors", async function (assert) {

View File

@ -1,6 +1,5 @@
import { import {
acceptance, acceptance,
count,
exists, exists,
query, query,
} from "discourse/tests/helpers/qunit-helpers"; } from "discourse/tests/helpers/qunit-helpers";
@ -123,9 +122,11 @@ acceptance("flagging", function (needs) {
const silenceUntilCombobox = selectKit(".silence-until .combobox"); const silenceUntilCombobox = selectKit(".silence-until .combobox");
await silenceUntilCombobox.expand(); await silenceUntilCombobox.expand();
await silenceUntilCombobox.selectRowByValue("tomorrow"); await silenceUntilCombobox.selectRowByValue("tomorrow");
assert.ok(exists(".modal-body"));
await fillIn(".silence-reason", "for breaking the rules"); await fillIn(".silence-reason", "for breaking the rules");
await click(".perform-silence"); await click(".perform-silence");
assert.ok(!exists(".bootbox.modal:visible")); assert.ok(!exists(".modal-body"));
}); });
test("Gets dismissable warning from canceling incomplete silence from take action", async function (assert) { test("Gets dismissable warning from canceling incomplete silence from take action", async function (assert) {
@ -140,17 +141,17 @@ acceptance("flagging", function (needs) {
await silenceUntilCombobox.selectRowByValue("tomorrow"); await silenceUntilCombobox.selectRowByValue("tomorrow");
await fillIn(".silence-reason", "for breaking the rules"); await fillIn(".silence-reason", "for breaking the rules");
await click(".d-modal-cancel"); await click(".d-modal-cancel");
assert.strictEqual(count(".bootbox.modal:visible"), 1); assert.ok(exists(".dialog-body"));
await click(".modal-footer .btn-default"); await click(".dialog-footer .btn-default");
assert.ok(!exists(".bootbox.modal:visible")); assert.ok(!exists(".dialog-body"));
assert.ok(exists(".silence-user-modal"), "it shows the silence modal"); assert.ok(exists(".silence-user-modal"), "it shows the silence modal");
await click(".d-modal-cancel"); await click(".d-modal-cancel");
assert.strictEqual(count(".bootbox.modal:visible"), 1); assert.ok(exists(".dialog-body"));
await click(".modal-footer .btn-primary"); await click(".dialog-footer .btn-primary");
assert.ok(!exists(".bootbox.modal:visible")); assert.ok(!exists(".dialog-body"));
}); });
test("CTRL + ENTER accepts the modal", async function (assert) { test("CTRL + ENTER accepts the modal", async function (assert) {

View File

@ -15,7 +15,7 @@ acceptance("Shared Drafts", function () {
assert.strictEqual(categoryChooser.header().value(), "3"); assert.strictEqual(categoryChooser.header().value(), "3");
await click(".publish-shared-draft"); await click(".publish-shared-draft");
await click(".bootbox .btn-primary"); await click(".dialog-footer .btn-primary");
assert.ok(!exists(".shared-draft-controls")); assert.ok(!exists(".shared-draft-controls"));
}); });

View File

@ -20,7 +20,7 @@ acceptance("User's bookmarks", function (needs) {
await dropdown.expand(); await dropdown.expand();
await dropdown.selectRowByValue("remove"); await dropdown.selectRowByValue("remove");
assert.notOk(exists(".bootbox.modal"), "it should not show the modal"); assert.notOk(exists(".dialog-body"), "it should not show the modal");
}); });
test("it renders search controls if there are bookmarks", async function (assert) { test("it renders search controls if there are bookmarks", async function (assert) {
@ -51,10 +51,10 @@ acceptance("User's bookmarks - reminder", function (needs) {
await dropdown.expand(); await dropdown.expand();
await dropdown.selectRowByValue("remove"); await dropdown.selectRowByValue("remove");
assert.ok(exists(".bootbox.modal"), "it asks for delete confirmation"); assert.ok(exists(".dialog-body"), "it asks for delete confirmation");
await click(".bootbox.modal a.btn-primary"); await click(".dialog-footer .btn-danger");
assert.notOk(exists(".bootbox.modal")); assert.notOk(exists(".dialog-body"));
}); });
test("bookmarks with reminders have a clear reminder option", async function (assert) { test("bookmarks with reminders have a clear reminder option", async function (assert) {

View File

@ -364,4 +364,28 @@ module("Integration | Component | dialog-holder", function (hooks) {
assert.notOk(query(".dialog-footer"), "no footer"); assert.notOk(query(".dialog-footer"), "no footer");
assert.notOk(query(".dialog-header"), "no header"); assert.notOk(query(".dialog-header"), "no header");
}); });
test("delete confirm", async function (assert) {
await render(hbs`<DialogHolder />`);
this.dialog.deleteConfirm({ message: "A delete confirm message" });
await settled();
assert.strictEqual(
query(".dialog-body").innerText.trim(),
"A delete confirm message",
"dialog message is shown"
);
assert.strictEqual(
query(".dialog-footer .btn-danger").innerText.trim(),
I18n.t("delete"),
"dialog primary button use danger class and label is Delete"
);
assert.notOk(
query(".dialog-footer .btn-primary"),
".btn-primary element is not present in the dialog"
);
});
}); });

View File

@ -9,10 +9,10 @@ import discourseComputed from "discourse-common/utils/decorators";
import Draft from "discourse/models/draft"; import Draft from "discourse/models/draft";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box"; import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import I18n from "I18n"; import I18n from "I18n";
import bootbox from "bootbox";
import { camelize } from "@ember/string"; import { camelize } from "@ember/string";
import { equal, gt } from "@ember/object/computed"; import { equal, gt } from "@ember/object/computed";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { inject as service } from "@ember/service";
// Component can get destroyed and lose state // Component can get destroyed and lose state
let _topicSnapshot = null; let _topicSnapshot = null;
@ -26,6 +26,7 @@ export function _clearSnapshots() {
} }
export default DropdownSelectBoxComponent.extend({ export default DropdownSelectBoxComponent.extend({
dialog: service(),
seq: 0, seq: 0,
pluginApiIdentifiers: ["composer-actions"], pluginApiIdentifiers: ["composer-actions"],
classNames: ["composer-actions"], classNames: ["composer-actions"],
@ -283,14 +284,13 @@ export default DropdownSelectBoxComponent.extend({
replyAsNewTopicSelected(options) { replyAsNewTopicSelected(options) {
Draft.get("new_topic").then((response) => { Draft.get("new_topic").then((response) => {
if (response.draft) { if (response.draft) {
bootbox.confirm( this.dialog.confirm({
I18n.t("composer.composer_actions.reply_as_new_topic.confirm"), message: I18n.t(
(result) => { "composer.composer_actions.reply_as_new_topic.confirm"
if (result) { ),
this._replyAsNewTopicSelect(options); confirmButtonLabel: "composer.ok_proceed",
} didConfirm: () => this._replyAsNewTopicSelect(options),
} });
);
} else { } else {
this._replyAsNewTopicSelect(options); this._replyAsNewTopicSelect(options);
} }

View File

@ -254,6 +254,7 @@ en:
ok_value: "OK" ok_value: "OK"
cancel_value: "Cancel" cancel_value: "Cancel"
submit: "Submit" submit: "Submit"
delete: "Delete"
generic_error: "Sorry, an error has occurred." generic_error: "Sorry, an error has occurred."
generic_error_with_reason: "An error occurred: %{error}" generic_error_with_reason: "An error occurred: %{error}"
sign_up: "Sign Up" sign_up: "Sign Up"
@ -1918,6 +1919,9 @@ en:
leave_message: "Do you really want to leave this message?" leave_message: "Do you really want to leave this message?"
remove_allowed_user: "Do you really want to remove %{name} from this message?" remove_allowed_user: "Do you really want to remove %{name} from this message?"
remove_allowed_group: "Do you really want to remove %{name} from this message?" remove_allowed_group: "Do you really want to remove %{name} from this message?"
leave: "Leave"
remove_group: "Remove group"
remove_user: "Remove user"
email: "Email" email: "Email"
username: "Username" username: "Username"
@ -2169,6 +2173,7 @@ en:
edit_conflict: "edit conflict" edit_conflict: "edit conflict"
esc: "esc" esc: "esc"
esc_label: "Click or press Esc to dismiss" esc_label: "Click or press Esc to dismiss"
ok_proceed: "Ok, proceed"
group_mentioned_limit: group_mentioned_limit:
one: "<b>Warning!</b> You mentioned <a href='%{group_link}'>%{group}</a>, however this group has more members than the administrator configured mention limit of %{count} user. Nobody will be notified." one: "<b>Warning!</b> You mentioned <a href='%{group_link}'>%{group}</a>, however this group has more members than the administrator configured mention limit of %{count} user. Nobody will be notified."
@ -2669,7 +2674,7 @@ en:
remove_tags: "Remove All Tags" remove_tags: "Remove All Tags"
confirm_remove_tags: confirm_remove_tags:
one: "All tags will be removed from this topic. Are you sure?" one: "All tags will be removed from this topic. Are you sure?"
other: "All tags will be removed from <b>%{count}</b> topics. Are you sure?" other: "All tags will be removed from %{count} topics. Are you sure?"
progress: progress:
one: "Progress: <strong>%{count}</strong> topic" one: "Progress: <strong>%{count}</strong> topic"
other: "Progress: <strong>%{count}</strong> topics" other: "Progress: <strong>%{count}</strong> topics"
@ -3998,7 +4003,6 @@ en:
tag_list_joiner: ", " tag_list_joiner: ", "
delete_unused: "Delete Unused Tags" delete_unused: "Delete Unused Tags"
delete_unused_description: "Delete all tags which are not attached to any topics or personal messages" delete_unused_description: "Delete all tags which are not attached to any topics or personal messages"
cancel_delete_unused: "Cancel"
filters: filters:
without_category: "%{filter} %{tag} topics" without_category: "%{filter} %{tag} topics"
with_category: "%{filter} %{tag} topics in %{category}" with_category: "%{filter} %{tag} topics in %{category}"