В моей теме, когда загружается страница отображения темы, мне нужно получить ID этой темы (и название, если возможно, но ID будет достаточно).
Затем я использую эту информацию в своей теме для выполнения API-запроса, чтобы получить данные о теме (с вызовом эндпоинта вроде forum-name/t/topic-name/id.json…)
Как можно получить ID темы при загрузке страницы отображения темы?
Очевидные методы недостаточны
Очевидное решение — использовать window.location.href или window.location.pathname для получения информации из URL. Проблема в том, что URL страницы отображения темы может иметь разные формы. Часто он выглядит так: forum-name/t/topic-name/topic-id
Если бы это всегда был такой формат, то использование window.location.pathname сработало бы отлично — я бы получил “t/topic-name/topic-id”.
НО иногда к URL страницы отображения темы добавляется порядковый номер категории темы, поэтому URL выглядит так: forum-name/t/topic-name/topic-id/category-index.
Таким образом, использование window.location.pathname недостаточно, потому что программно я не знаю, будет ли последний параметр ID темы или индексом категории.
Возможно, существует способ решить это с помощью регулярных выражений, но это требует серьёзных навыков работы с ними. Также может быть способ решить задачу с помощью jQuery, анализируя элементы на странице, которые могут содержать ID, — но мне пока не удалось заставить это работать.
На моём форуме это чаще всего происходит при клике на тему. Последняя часть URL — это номер темы в категории, если вы перешли на неё из списка категории. Возможно, это настройка в Discourse? На meta-форуме такого не наблюдается, но я не думаю, что делаю что-то особенное, чтобы это происходило на моём форуме.
Однако я не всегда могу полагаться на это, потому что если тема является первой в категории, к ней не добавляется индекс категории. Так что, насколько я понимаю, сейчас нет хорошего способа определить, появится ли тема в индексе категории или нет.
Получение ID из div-элемента возможно, но, к сожалению, это значительно медленнее, чем получение его напрямую из URL или другим прямым способом. Если другого решения нет, не подскажете, какой jQuery-код нужен, чтобы получить значение этого атрибута href?
Это может сработать, но не очень эффективно, так как вы делаете дополнительный AJAX-запрос при каждом просмотре страницы темы каждым пользователем — включая анонимов. Это создаст значительную ненужную нагрузку на ваш сервер.
Это работает! Большое спасибо. Я понимаю, что с помощью метода match здесь вы анализируете URL, чтобы получить, предположительно, третье вхождение символа “/”, так как ID всегда появляется после третьего “/” в URL, который имеет формат “/t/name/id/otherstuff”. Не могли бы вы немного объяснить, как именно ваше регулярное выражение это делает? Это было бы очень полезно в моём изучении регулярных выражений.
Спасибо за информацию. То есть именно “linked_post_number” иногда появляется и сбивает мой API-вызов. Вы здесь говорите, что он “необязательный” — есть ли способ гарантировать, что он никогда не будет отображаться?
Когда пользователь заходит на страницу просмотра темы, я хочу:
Программно узнать все теги, связанные с этой темой. Обратите внимание, что некоторые теги скрыты от просмотра пользователем.
Добавить на страницу темы кнопку, которая при нажатии добавляет определённый скрытый тег к теме (если его там ещё нет) и удаляет его (если тег уже есть).
Всё это вполне реализуемо с помощью Admin API и JavaScript/jQuery (при условии, что я смогу получить правильный URL темы для использования в API-вызовах).
Полагаю, единственный другой способ сделать что-то подобное — создать плагин, углубившись в 1. Ember, 2. Rails и 3. исходный код Discourse. Я изучил ключевые посты и документацию Discourse о том, как это сделать, но процесс идёт медленно, так как необходимо действительно понимать эти три компонента. Поэтому пока я сосредоточился на подходе через API.
Мне было бы интересно узнать, есть ли другой способ сделать это, который уменьшил бы нагрузку на сервер.
Я мог бы с уверенностью помочь вам с кодом, если бы решение состояло из одного шага, но здесь задействовано несколько этапов. Если вам нужна помощь в виде консультации по выполнению работы или обучению написанию компонентов темы самостоятельно, пожалуйста, опубликуйте запрос на рынке, и я свяжусь с вами.
Полноценный объект темы загружается на стороне клиента при открытии страницы темы. Теперь, если вы хотите использовать его, вам нужно добавить свой код в шаблон для работы с этими данными или «переоткрыть» классы, чтобы использовать загруженные данные (то есть по сути создать свои собственные вычисляемые свойства и применять их в шаблоне). На стороне клиента уже загружено большинство необходимых данных (возможно, даже больше, чем нужно), без дополнительных вызовов API. Также вам понадобятся plugin-outlet для вставки собственного HTML в существующие шаблоны.
Вам поможет изучение кодовой базы и метаданных по упомянутым выше терминам. Я с радостью помогу вам здесь, если вы застрянете, в пределах моих возможностей по времени. Удачи!
Спасибо. Я знаком с некоторыми основными моментами, которые вы упомянули, но один пункт вызывает у меня трудности (и, уверен, именно такие вещи часто ставят в тупик многих):
На странице отображения темы загружается шаблон /templates/components/topic-category.hbs. Именно он отвечает за отображение категории, а также тега под заголовком темы.
В шаблоне topic-category перечисляются topic.tags. Это ключевой элемент информации, необходимый для решения моей задачи.
Вот где я застрял: Как передать информацию topic.tags в JavaScript?
Например, если бы я просто хотел вывести содержимое topic.tags в консоль, как бы я это сделал?
Я знаю, как переопределять шаблоны. Например, в теме я могу создать файл по пути discourse/templates/components/topic-category.hbs, скопировать туда содержимое шаблона и внести желаемые изменения в отображение. (Я использую структуру с отдельными файлами, описанную здесь).
В своей теме я также знаю, как добавлять JavaScript по пути theme/initializers/initializer-file.js.es6.
И я могу заставить их взаимодействовать с помощью jQuery. Например, я мог бы поместить topic.tags в div внутри шаблона, а затем получить доступ к этому div из инициализатора с помощью jQuery, чтобы извлечь его содержимое.
Но это слишком обходной путь. Как можно получить информацию topic.tags напрямую, чтобы я мог её распарсить и обработать?
Я бы вывел всю тему в консоль и нашел бы необходимый ключ. Взаимодействия с jQuery должны выполняться и выполняются внутри компонентов. didInsertElement — это хук компонента, который полезен в данном случае.
Судя по всему, вам нужен вычисляемый параметр (computed property), зависящий от topic.tags, который возвращает результат вашей манипуляции в соответствующем контроллере или компоненте. Его можно использовать напрямую в шаблоне. Также не опускайте руки в этом вопросе. Это займёт время, но определённо окупится способами, о которых вы даже не могли мечтать.
Что вы имеете в виду под «внутри компонентов» — в каком файле мне размещать код jQuery? (в моей теме я могу использовать jQuery в файле theme/intializers/intializer-file.js.es6, но это, кажется, не считается «внутри» компонента)
В каком файле должен находиться код для didInsertElement?
На этом этапе вам действительно стоит ознакомиться с руководством по Ember. Компонент — это пакет функциональности, который можно развернуть и подключить к другим элементам.
Спасибо, ребята, вся эта информация очень полезна. Я изучаю руководства и общую документацию. Также было бы очень полезно узнать название файла, куда нужно вставить (i) код jQuery и (ii) код didInsertElement. Такая конкретная информация станет большой помощью для дальнейшего анализа.
Вы можете использовать reopen для различных классов Ember и внедрять в них свой код. Чтобы лучше понять, как это делается, изучите плагины или темы, которые используют этот подход.
@JQ331 Как вы, вероятно, знаете, я нашёл регулярные выражения в Google и попробовал их здесь! Вы можете вводить различные варианты, чтобы получить наилучшие результаты.
Если теги скрыты от обычного пользователя, как может помочь дополнительный вызов? Сериализатор в любом случае должен скрывать эти теги от обычного пользователя. Если этого не происходит, то вы создаёте уязвимость в безопасности контента.
Если вы идёте на все эти сложности, чтобы обойти ограничения изменений только на стороне фронтенда, я бы предложил вам решиться и реализовать это в виде плагина. Тогда вы сможете выполнить сериализацию за один раз, вместо того чтобы иметь запутанную настройку с дополнительными вызовами.
Это имеет смысл. Я хотел бы узнать больше об использовании сериализатора — хотя сериализатор является одним из самых важных этапов при создании плагина для Discourse, я пока не нашёл документации, в которой были бы приведены базовые примеры его использования. Знаете ли вы о такой документации?
Когда вы говорите, что сериализатор должен скрывать эти теги, не могли бы вы привести какой-нибудь псевдокод, чтобы проиллюстрировать, что вы имеете в виду? (Не обязательно, чтобы он полностью работал — я просто пытаюсь разобраться в концепции).
Это как джазовая музыка: лучшие практики обычно уже существуют в ландшафте открытых плагинов с открытым исходным кодом, как и все записи. Не ждите идеального руководства по выполнению всего — вам часто придется вникать в суть (кхм) и учиться на уже существующих решениях.
Найдите плагин из #plugin, который функционально похож на то, что вы хотите сделать, или реализует часть вашей задачи, изучите его код и посмотрите, как он достигает своих целей. То же самое касается исходного кода Discourse, который можно использовать как источник «лучших практик», особенно в контексте Discourse.
Склонируйте существующий плагин локально, внесите несколько изменений и поэкспериментируйте.
Сериализаторы просто фильтруют данные, передаваемые из контроллеров и моделей, и могут выполнять некоторые базовые преобразования.
def tags
# Вызов метода `pluck` вместе с `includes` вызывает N+1 запросы
tags = topic.tags.map(&:name)
if scope.is_staff?
tags
else
tags - scope.hidden_tag_names
end
end
Как видно здесь, скрытые теги исключаются для пользователей, не являющихся сотрудниками.