Bootbox теперь устарел

Начиная с этого коммита:

библиотека bootbox для диалоговых окон объявлена устаревшей.

Разработчики, пожалуйста, используйте сервис dialog из ядра вместо bootbox в ваших пользовательских темах и плагинах. Библиотека bootbox будет полностью удалена из ядра Discourse в течение 2023 года.

Вот несколько примеров PR из плагинов и тем, демонстрирующих переход на сервис dialog:

В моей кастомной теме у меня есть что-то вроде этого:

<script type="text/discourse-plugin" version="0.8">
    bootbox.alert('текст предупреждения');
</script>

Как я могу получить доступ к сервису диалогов в теме, поскольку, похоже, он не доступен глобально?

Самый простой вариант — загрузить сервис через lookup. Вот пример кода (он не протестирован, но мы используем что-то подобное в ядре, вне компонентов/контроллеров/роутов Ember):

<script type="text/discourse-plugin" version="0.8">
  import { getOwner } from "discourse-common/lib/get-owner";
  const dialog = getOwner(this).lookup("service:dialog");
  dialog.alert('текст предупреждения');
</script>

Спасибо. Я попробовал это, но получил ошибку:
SyntaxError: /discourse/theme-11/initializers/theme-field-36-common-html-script-2: 'import' и 'export' могут появляться только на верхнем уровне. (13:4)

А, точно, в этих тегах скрипта нужно использовать require. Если можно поделиться, покажите полный код того, что вы здесь делаете? Я хотел бы предложить альтернативу этому тегу <script>: мы перенесли большую часть кода темы в отдельные JS-файлы в компонентах темы, которые поддерживаем сами, и, возможно, вам будет проще провести здесь более общую рефакторинг.

Спасибо за предложение! Вот полный скрипт (с незначительными изменениями текста), который работал корректно, пока мы не заметили, что всплывающее окно Bootbox больше не отображает HTML-теги правильно.

<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>О нет!</h2>';

            let alertBody = '<p>Ваша учетная запись в настоящее время ограничена, и вы больше не имеете доступа к ценным ресурсам. <a href="https://meta.discourse.org">Нажмите здесь</a> для получения дополнительной информации.</p>';

            bootbox.alert(alertHeading + alertBody);
        });
    }
</script>

Привет, Тим,
Вот альтернативный вариант. Обратите внимание, что содержимое здесь должно быть размещено в файле инициализатора JS внутри компонента. Простой пример полной структуры компонента можно посмотреть здесь.

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 = "О нет!";
        const alertBody =
          'Ваша учетная запись в настоящее время ограничена, и вы больше не имеете доступа к ценным ресурсам. <a href="https://meta.discourse.org">Нажмите здесь</a> для получения дополнительной информации.';

        schedule("afterRender", () => {
          // задержка необходима для загрузки службы диалогов
          const dialog = getOwner(this).lookup("service:dialog");
          dialog.alert({
            message: htmlSafe(alertBody),
            title: alertHeading,
          });
        });
      }
    });
  },
};

Надеюсь, это поможет.

Это отлично. Большое спасибо!

Устаревание bootbox полностью устранено в этом PR: DEV: remove bootbox dependency by tyb-talks · Pull Request #27443 · discourse/discourse · GitHub. Как указано в исходном сообщении, используйте сервис dialog.