При доступе к группам со страницы /g можно ли настроить так, чтобы ссылка на группу вела на /g/group-slug/messages, а не на /g/group-slug/members?
У нас есть несколько групп, которые используются для групповых сообщений. Было бы полезно сократить путь пользователей на один клик при переходе к сообщениям их группы. Для нас это важнее, чем просмотр участников группы.
Я знаю, что можно сделать это через прямую ссылку, но мне нужно, чтобы это работало со страницы /g?type=my, которая удобно динамична и ориентирована на пользователя.
Это не обычные ссылки. Они обрабатываются компонентом Ember link-to, и здесь задействована небольшая логика маршрутизации.
Самый простой способ реализовать это — перехватить клик по этому элементу и выполнить необходимые действия. Этот код размещается в секции common > header темы:
Если пользователь является участником группы и у группы есть сообщения, он будет перенаправлен во входящие. В противном случае будет использована страница по умолчанию /members.
При более внимательном рассмотрении выяснилось, что у них раньше были сообщения, которые были преобразованы в темы или удалены. Data Explorer показывает, что для этих групп в таблице Groups значение has_messages равно True.
Я пытался изменить это для данных групп через Rails, но у меня не получается:
Это сработало для всех, кроме двух — спасибо. Эти последние назойливые два, думаю, мне придётся просто удалить и создать заново!
При этом я обнаружил причину — это небольшой #баг.
При преобразовании личных сообщений группы в темы информация об участниках приглашения сохраняется. Хотя это удобно, если тему снова преобразовать обратно, это означает, что они ошибочно учитываются при выполнении Group.refresh_has_messages!.
Можно ли также перехватить ссылки, которые появляются при клике на упомянутую группу (@mentioned group) и последующем переходе в эту группу? Мне кажется, это единственные два способа попасть в группы, не прибегая к прямым URL-адресам.
Теперь я хочу (жаден, не так ли?) добиться того, чтобы все ссылки на группы вели себя так же, как и те, что ведут на страницу /g, благодаря вашему коду.
Конечно, вы можете попробовать что-то вроде этого во вкладке «Header» вашей темы или компонента. Я оставил несколько комментариев в сниппете, чтобы вы могли следить за процессом. Вы можете удалить их, когда будете готовы использовать код.
Действуют те же правила. Если пользователь является участником группы и у группы есть сообщения, Discourse перенаправит его в входящие сообщения группы. В противном случае пользователь попадёт в каталог участников.
<script type="text/discourse-plugin" version="0.8">
// Часть 1: изменение пути для ссылок в карточках групп. Это гарантирует, что
// заголовок ссылки отражает её назначение, а также обрабатывает открытие ссылки в новой вкладке.
const discourseComputed = require("discourse-common/utils/decorators").default;
api.modifyClass("component:group-card-contents", {
// Свойство groupPath используется для генерации href для ссылок на группы
// в карточке группы. Давайте изменим его
@discourseComputed("group")
groupPath(group) {
// получаем значение по умолчанию из ядра
let groupURL = this._super(...arguments);
// если пользователь соответствует нашим требованиям, изменяем URL, чтобы он вел в входящие
if (group.is_group_user && group.has_messages) {
groupURL = `${groupURL}/messages/`;
}
// возвращаем либо значение по умолчанию, либо изменённое
return groupURL;
}
});
// Часть 2: изменение маршрутизации внутри приложения. Это гарантирует, что обычная навигация
// внутри приложения обрабатывается корректно и направляет пользователя в входящие сообщения группы,
// если он соответствует требованиям
const DiscourseURL = require("discourse/lib/url").default;
const { groupPath } = require("discourse/lib/url");
const { action } = require("@ember/object");
api.modifyClass("controller:user-card", {
// showGroup здесь — это действие, принадлежащее контроллеру user-card.
// Именно оно вызывается при клике на имя группы / аватарку внутри карточек групп
@action
showGroup(group) {
// вызываем super, чтобы убедиться, что код из ядра загружен первым
this._super(...arguments);
// groupPath — это встроенная функция-помощник URL в Discourse
let groupURL = groupPath(group.name);
// если пользователь соответствует требованиям, изменяем URL
if (group.is_group_user && group.has_messages) {
groupURL = `${groupURL}/messages/`;
}
// вызываем routeTo() с либо значением по умолчанию, либо изменённым groupURL
DiscourseURL.routeTo(groupURL);
}
});
</script>
Вы молодец! Это отлично работает для любого случая с использованием карточек.
Теперь остался один тип ссылки, который не имеет направления: ссылка на группу в частном сообщении группы. Это на самом деле очень удобно для перехода к группе (и, следовательно, к входящим сообщениям) из сообщения группы.
Эти ссылки используют несколько иной сериализатор, так как там не нужны все данные о группах.
Тем не менее, вы можете сохранить отфильтрованный список групп текущего пользователя при первоначальной загрузке страницы и использовать его как справочник для проверки членства. Эта информация уже доступна в начальном пакете данных, поэтому дополнительных запросов или иных накладных расходов не возникает. Что-то вроде этого:
Разместите этот фрагмент в отдельных тегах скрипта и добавьте его в заголовок вместе с остальными фрагментами. Разделение необходимо, потому что код быстро завершает выполнение, если пользователь не авторизован.
У меня есть ещё одна вещь, с которой мне нужна помощь, чтобы полностью завершить это. Я знаю, что немного наглую, просив об этом.
Сейчас я пытаюсь модифицировать Pavilion, чтобы она тоже поддерживала такое поведение, используя простую логику из ваших трёх замечательных сниппетов. Однако у меня ничего не получается из-за моего неумения работать с JavaScript. Вот что я пытаюсь изменить:
Для некоторых групп, где существуют «призраки сообщений», это не работает. Эти группы можно идентифицировать с помощью следующего запроса (при условии, что в настройках взаимодействия группы ограничена возможность отправки сообщений):
SELECT id, name, has_messages, messageable_level
From groups
Where messageable_level < 10
AND messageable_level <> 3
AND has_messages = true
ORDER by id
Вы можете вручную изменить таблицу groups, чтобы принудительно сбросить это значение (конечно, в консоли Rails, предварительно сделав резервную копию!).