Программное внесение пользовательских изменений в боковую панель

Это отличная функция, но что если содержимое пользовательского раздела боковой панели необходимо создавать программно? Я реализовал это способом, похожим на тот, что описал @Olya_Fursova выше, с той разницей, что содержимое генерируется путем запроса к API, а затем отображаются ссылки — некоторые ведут к категориям, а некоторые напрямую к определённым темам. Я столкнулся с двумя проблемами:

  • Если боковая панель скрыта при первоначальном отображении страницы, динамический контент не будет показан, так как контейнер боковой панели отсутствует. Кроме того, если боковая панель изначально отображается, затем сворачивается и снова разворачивается, динамический контент исчезает, потому что контейнер боковой панели перерисовывается без выполнения пользовательской логики. Вопрос: есть ли способ подключиться к процессу отображения боковой панели, чтобы выполнять мой пользовательский код каждый раз при её показе?
  • Когда нажатие на ссылки, которые я программно добавляю в боковую панель, приводит к полной перезагрузке страницы. Вопрос: есть ли способ предотвратить полную перезагрузку страницы при клике на одну из моих пользовательских ссылок в боковой панели?

Было бы действительно замечательно, если бы существовал способ программно изменять боковую панель!

Мы создали API для добавления пользовательских секций в боковую панель.

Некоторые примеры можно найти в комментариях здесь: discourse/app/assets/javascripts/discourse/app/lib/plugin-api.js at 00ab94bf53b784478d0aa7744bf3bb2d5b527580 · discourse/discourse · GitHub

Это помечено как экспериментальная функция, но её использование безопасно (мы, например, используем её для добавления контента чата в боковую панель при включении).

Это выглядит интересно, спасибо! Правда, мне ещё потребуется время, чтобы во всём разобраться, например, я пока не до конца понял, как работает маршрутизация. Кроме того, похоже, что ссылки в разделе могут быть только в виде плоского списка, верно? То, что я сейчас пытаюсь реализовать, выглядит примерно так, то есть с одним уровнем отступа:

Могу ли я добиться этого с помощью нового API для пользовательских разделов боковой панели?

Нет, мы по умолчанию не предусмотрели какой-либо отступ в боковой панели… но если вы можете расположить свои разделы в нужном порядке с помощью API, то, думаю, отступы можно будет реализовать с помощью стилей CSS?

После более тщательного изучения я уверен, что это сработает, да! Моя нынешняя проблема заключается в том, что список ссылок динамический и может меняться при каждой смене страницы. Мой наивный подход вызова api.addSidebarSection внутри api.onPageChange не работает, потому что (a) боковая панель обновляется только при её перерисовке через скрытие и повторное отображение, и (b) разделы дублируются, так как api.addSidebarSection не проверяет, используется ли ключ имени повторно.

Есть ли шанс реализовать раздел боковой панели, который обновляется при каждом переходе между страницами с помощью нового API?

Вы можете посмотреть, как плагин чата интегрирован с боковой панелью:

В этом случае состояние ссылок хранится в объекте сервиса, и при изменении состояния боковая панель обновляется:

Одно из возможных решений — подписаться на событие изменения страницы и обновлять ссылки. Псевдокод может выглядеть так:

import { tracked } from "@glimmer/tracking";

api.addSidebarSection(
  (BaseCustomSidebarSection, BaseCustomSidebarSectionLink) => {
    const TestSectionLink = class extends BaseCustomSidebarSectionLink {
      // определите здесь свойства вашей пользовательской ссылки
    };

    const SidebarTestSection = class extends BaseCustomSidebarSection {
      @tracked links = [];

      constructor() {
        super(...arguments);

        this.#updateLinks();
        this.onAppEvent("page:changed", () => this.#updateLinks());
      }

      get newLinksArray() {
        // список ссылок на основе текущего URL
      }

      #updateLinks() {
        this.links = this.newLinksArray.map(
          (link) =>
            new TestSectionLink({
              link,
            })
        );
      }

      get sectionLinks() {
        return this.links;
      }
    };
    return SidebarTestSection;
  }
);