the bootbox library for dialogs is now deprecated.
Developers, please use the dialog service in core instead of bootbox in your custom themes and plugins. The bootbox library will be removed from core Discourse entirely sometime in 2023.
Here are some example PRs from plugins and themes that show how to transition to the dialog service:
The easiest option would be to load the service using the lookup. Here’s an example code (this is untested, but we use something like this in core, outside of Ember components/controllers/routes):
Thanks. I tried this but am getting an error: SyntaxError: /discourse/theme-11/initializers/theme-field-36-common-html-script-2: 'import' and 'export' may only appear at the top level. (13:4)
Ah, right, we need to use requires in these script tags. If it’s ok to share, what’s the full code of what you are doing here? I’d like to propose an alternative to this <script> tag, we’ve moved most theme code to standalone JS files in the theme components that we maintain ourselves and it might be easier to do a more general refactor here for you.
Thanks for the offer! Here is the full script (with some text slightly modified), which was working fine until we noticed the Bootbox popup no longer rendered HTML tags correctly.
<script type="text/discourse-plugin" version="0.8">
if (typeof bootbox === 'undefined') {
console.log('Cannot trigger undefined "bootbox"');
return;
}
let currentUser = api.getCurrentUser();
if (currentUser) {
api.container.lookup('store:main').find('user', currentUser.username).then((user) => {
let userGroups = user.groups.map(group => group.name);
let bodyClasses = userGroups.map(group => `user-group--${group}`);
document.querySelector('body').classList.add(...bodyClasses)
let showPopup;
switch(true) {
case userGroups.includes('restricted_member'):
showPopup = true;
break;
case userGroups.includes('users_all'):
case userGroups.includes('officers'):
showPopup = false;
break;
default:
showPopup = true;
break;
}
if (!showPopup) {
return;
}
let alertHeading = '<h2>Oh no!</h2>';
let alertBody = '<p>Your account is currently restricted and you no longer have access to valuable resources. <a href="https://meta.discourse.org">Click here</a> for more information.</p>';
bootbox.alert(alertHeading + alertBody);
});
}
</script>
Hi Tim,
Here’s the alternative, note that the contents here needs to go in an initializer JS file in a component. You can see a simple example of a full component structure here.
import { withPluginApi } from "discourse/lib/plugin-api";
import { getOwner } from "discourse-common/lib/get-owner";
import { schedule } from "@ember/runloop";
import { htmlSafe } from "@ember/template";
export default {
name: "tester-initializer",
initialize() {
withPluginApi("0.8", (api) => {
const currentUser = api.getCurrentUser();
if (currentUser) {
const userGroups = currentUser.groups.map((group) => group.name);
let showPopup = false;
switch (true) {
case userGroups.includes("admins"):
showPopup = true;
break;
}
if (!showPopup) {
return;
}
const alertHeading = "Oh no!";
const alertBody =
'Your account is currently restricted and you no longer have access to valuable resources. <a href="https://meta.discourse.org">Click here</a> for more information.';
schedule("afterRender", () => {
// delay needed so that the dialog service is loaded
const dialog = getOwner(this).lookup("service:dialog");
dialog.alert({
message: htmlSafe(alertBody),
title: alertHeading,
});
});
}
});
},
};