Можно ли использовать `.gjs` для шаблонов маршрутов?

Поддерживаются ли сейчас glimmer-компоненты в роутах?

Я предполагаю, что для Discourse ответ — «нет», но буду рад узнать обратное.

Да, вы можете использовать файлы .gjs для шаблонов маршрутов в Discourse прямо сейчас. На самом деле, мы только что конвертировали сегодня целую кучу их в ядре! Посмотрите примеры по ссылке https://github.com/discourse/discourse/tree/main/app/assets/javascripts/discourse/app/templates.

«Кто-то» — это Discourse: мы спонсировали разработку ember-route-template, и он находится в нашей организации на GitHub :wink:

Мы пока не перешли на последнюю версию Ember 6.x, но используем этот аддон для включения соответствующей функциональности.

О, как прекрасно! Спасибо за быстрый ответ!

Ха-ха, я даже не заметил, что это в репозитории Discourse на GitHub. Хорошая мысль. :slight_smile:

Добавление нового маршрута в приложение оказалось для меня совсем неочевидным. Я запишу это здесь для других.

Я хотел добавить маршрут /print в корне.

Итоговый код, который сработал для меня, выглядит следующим образом. county-fence — это имя моего плагина, поэтому замените его на своё.

Маршрут Ember

assets/javascripts/discourse/routes/county-fence-route-map.js.es6

export default function() {
  this.route('print', { path: '/print' });
}

assets/javascripts/discourse/routes/print.js

import Route from "@ember/routing/route";

export default class PrintRoute extends Route {
  model() {
    return { message: "Это пользовательская страница печати!" };
  }
}

assets/javascripts/discourse/templates/print.gjs

import RouteTemplate from "ember-route-template";
import ...;

export default RouteTemplate(
  <template>
    ...
  </template>
)

Маршрут API

plugin.rb

after_initialize do
  require_relative "app/controllers/print_controller"
end

app/controllers/print_controller.rb

# frozen_string_literal: true
# Коды состояния HTTP: https://github.com/discourse/discourse/blob/main/lib/discourse.rb

class ::CountyFence::PrintController < ::ApplicationController
  requires_plugin CountyFence::PLUGIN_NAME


  def save_print
  end

  def list_prints
    render json: { name: "пончик", description: "вкусно!" }
  end

  def get_print
  end

end

Discourse::Application.routes.append do
  post "/print" => "county_fence/print#save_print"
  get "/print" => "county_fence/print#list_prints"
  get "/print/:id" => "county_fence/print#get_print"
end

Можно ли получить пустую страницу без макета, навигационных панелей и любых стилей CSS сайта? Я хочу использовать компонент Glimmer, но ни один из стилей сайта не помогает при создании страницы для печати.

Если речь идет просто о стилизации для печатной версии страницы и вас не беспокоит наличие навигационной панели и прочего лишнего контента при просмотре, вы можете использовать CSS-селектор @media print для изменения стилей при печати. В Discourse уже скрыто множество элементов при печати (discourse/app/assets/stylesheets/common/printer-friendly.scss at main · discourse/discourse · GitHub). Вы можете предварительно просмотреть страницу, используя режим print media simulation в инструментах разработчика Firefox. Аналогичная функция должна быть доступна в инструментах разработчика Chrome.

Если вам нужен полностью чистый холст для работы — не только в режиме печати, но и при обычном просмотре в браузере, можно применить небольшую CSS-хитрость.
Предположим, что ваш Glimmer-компонент имеет корневой div с id="print-component__root". Мы можем заставить CSS проверять его наличие с помощью селектора :has() (или просто добавлять/удалять класс у элемента body в жизненном цикле Glimmer-компонента) и выборочно применять стилизацию.

body:has(#print-component__root) {
  header,
  .avatar,
  .sidebar-wrapper,
  ... {
    all: unset !important;  // all: unset может быть слишком агрессивным
    display: none !important;
  }
}

#print-component__root {
  // обычная стилизация
}

Возможно, существует более эффективный и чистый способ, который фактически удаляет элементы DOM, но предложенный CSS-подход является хорошим обходным решением для сброса всего оформления.

Мои SCSS-файлы не загружаются. Есть какие-нибудь идеи? Я настроил файлы согласно плагину чата в ядре.

В файле plugins.rb у меня написано:

register_asset "stylesheets/common/index.scss"

В файле assets/stylesheets/common/index.scss:

@import "common";

В файле assets/stylesheets/common/common.scss:

body:has(#print-root) {
  header,
  .avatar,
  .sidebar-wrapper {
    all: unset;  // all: unset может быть немного слишком агрессивным
    display: none !important;
  }
}

Чтобы убедиться, что проблема связана с загрузкой SCSS, а не с предоставленным вами правилом стилей, попробуйте добавить стиль без селектора :has(). Например:

.sidebar-wrapper {
  outline: 5px solid red;
}

Также рекомендую перезапустить ваш Rails-сервер. В прошлом у меня возникали проблемы, когда добавление или удаление вызовов register_asset требовало полной перезагрузки Docker-контейнера.

  • Я удалил селектор :has().\n* Поместил код в index.scss, чтобы убедиться, что проблема не в директиве @import.\n* Выполнял d/rake assets:clobber tmp:clear и d/rails s.\n\nПока ничего не помогает загрузить файл.\n\nБольшинство других файлов вызывают автоматическую перезагрузку в браузере. Этот файл этого не делает. Поэтому я думаю, что проблема может быть в register_asset. Мне кажется, что register_asset автоматически ищет в папке assets? Все примеры, которые я вижу, указывают на то, что это так.

d/rails c и DiscoursePluginRegistry.stylesheets показывают:

"county-fence"=>#<Set: {"/src/plugins/county-fence/assets/stylesheets/common/index.scss"}>

Значит, что-то происходит. ^^

В логах d/rails s я обнаружил следующее: No such file or directory @ rb_sysopen - /src/app/assets/stylesheets/plugin-cf.scss.

Таким образом, хотя плагин символически связан в папке /plugins под именем county-fence, и мой плагин явно назван county-fence в файле plugins.rb, какой-то код считывает имя исходной директории plugin-cf и строит предположения относительно имени скомпилированного CSS-файла для моего плагина.

Это баг или особенность? :smiley:

Мораль этой истории, по-моему, такова: ни при каких обстоятельствах не называйте директорию плагина иначе, чем имя самого плагина. Правильно названной символической ссылки недостаточно.

РЕДАКТИРОВАНИЕ: также register_asset "stylesheets/common/index.scss", plugin: "county-fence" является обходным путем, который принудительно устанавливает правильное имя плагина.

У меня возникли проблемы с применением правил внутри body:has(). Они, похоже, не обновляются в конвейере компиляции ассетов. Я запускаю d/rake assets:clobber tmp:clear и перезапускаю сервер с помощью d/rails s, но они всё равно не обновляются.

Например, я могу добавить body { background-color: red !important; } в секцию body:has(), но это правило вообще не отображается в стилях для элемента body. Дело не только в том, что оно переопределяется — его просто нет в разделе “styles” в инструментах разработчика.

Если же я размещаю ту же строку CSS вне body:has(), то всё отображается корректно.

document.querySelector("body:has(#print-root)") !== null в консоли браузера возвращает true. И некоторые правила из body:has() применяются.

Мне интересно, не может ли быть в конвейере генерации ассетов правил, которые препятствуют применению этих изменений.

Я думаю, что моё решение для этого — просто включать стили напрямую в компонент glimmer для страницы. Это единственное, что я пробовал, и это работает стабильно. Тогда мне не приходится возиться с условными правилами CSS.

Пайплайн компиляции CSS доставляет мне массу проблем — он крайне непоследователен в обновлении и применении правил… элементы исчезают, и я не понимаю почему. Не знаю, связано ли это с запуском в контейнере Docker? Я полностью отказался от символической ссылки на папку плагинов — полагаю, она вызывала проблемы с монтированием тома Docker и отслеживанием файлов/перекompиляцией. Вероятно, я смогу создать минимальный репозиторий для воспроизведения этих проблем… Посмотрю, получится ли у меня сделать это и опубликовать в ближайшие несколько дней.

Дополнение к этому…

Теперь iframe, рендеримый из Stripe, вызывает отображение пустой страницы в нижней части макета для печати. Iframe жестко задан с display: block !important непосредственно в элементе.

Думаю, я обойду эту конкретную ошибку, удалив iframe при загрузке этого маршрута… (Кстати, Stripe рендерит div на всю ширину страницы, который отслеживает все события кликов — это кажется довольно вторжением в частную жизнь… Я полагаю, это связано с плагином подписок.)

Но я смотрю в будущее и预见аю долгий путь «выбивания кротов» при устранении неполадок на странице печати. Любое будущее изменение, добавляющее новый элемент в макет, даже если он не заметен визуально, может привести к сбоям при печати.

Для меня действительно неидеальная ситуация наследовать макет сайта для этого маршрута. Есть ли способ отказаться от этого или задать свой собственный макет?