Отображать разный контент в теме в зависимости от групповой принадлежности пользователя?

Я работаю с хостингом discourse.org, поэтому в данном случае использование плагинов для меня невозможно. Представьте, что у меня есть тема, которую может увидеть любой.

Если пользователь состоит в группе «A», я хочу, чтобы он видел этот контент. Если нет — я хочу, чтобы он видел другой контент. При этом часть темы должна быть видна всем. Схематично это выглядит так…

Это контент, который видят все.

{мечты: только для людей из группы A}
Спасибо, что вы в специальной группе!
{/мечты}

{мечты: только для людей НЕ из группы A}
У нас есть специальная группа, в которую можно вступить. [Узнайте больше об этом](…)
{/мечты}

Я уверен (но точно не помню, как это делается), что это можно реализовать с помощью компонента темы, который добавляет CSS-классы к контенту, отображение которого нужно «переключать». Если лучшего варианта не найти, я поступлю именно так.

Но CSS display: none — это слабое решение. Я бы хотел, чтобы то, что не должны видеть пользователи, исчезало из DOM. Желательно на стороне сервера, но я согласен и на решение, основанное на JavaScript, которое скрывает контент на стороне браузера. (Обойти это сложнее, чем просто использовать display: none в CSS, и требует гораздо большей изобретательности.)

поднимаю! никто? :~(

почему мы не можем упомянуть @team :wink:

Сейчас у меня нет времени подробно вникать в это, но этот компонент темы может вам помочь, так как он, как я помню, выводит все группы текущего пользователя в тег body. Затем вы, вероятно, сможете использовать CSS-селекторы для показа/скрытия элементов в зависимости от того, присутствуют ли в теге body определённые классы групп.

А в сочетании с информацией из этого поста о том, какие HTML-элементы можно использовать в редакторе и как оборачивать текст редактора в классы, это может сработать:

Да, я только что проверил это здесь, и это должно сработать, если использовать этот компонент вместе с чем-то вроде:

<span data-group-a>Текст только для группы A</span>
<span data-group-b>Текст только для группы B</span>

А затем добавить CSS-селекторы, которые делают что-то вроде:

span[data-group-a] {display: none;}
body.group-a span[data-group-a] {display: block;}

Или что-то в этом роде…

Извините за все правки. Я просто протестировал это на одном из своих экземпляров, и всё работает.

Но, как вы упомянули, возможно, это не то, что вы искали :slight_smile:

Это может быть возможно с помощью JavaScript темы: добавить что-то в секцию <head>, чтобы выбрать элементы и удалить их. Всё ещё может потребоваться использование span и оборачивание, как описано выше, но удаление будет происходить через скрипт.

Хорошо, я понял, что это мне тоже может понадобиться, поэтому я копнул глубже :slight_smile:

Этот код пока не работает и выглядит не очень красиво, но, думаю, он уже почти готов для вставки в часть <head> темы. Нужно лишь правильно подобрать способ выбора элементов с помощью JS:

<script type="text/discourse-plugin" version="0.8.42">

  api.decorateCookedElement(
    element => {
      var hasGroupA = document.body.classList.contains('group-a');

      const group_a_spans = element.querySelectorAll("span[data-group-a]");

      if (!group_a_spans.length) {
        return;
      }

      if (!hasGroupA) {
        group_a_spans.forEach(function (el) {
           el.innerHTML = "";
        });
      }

      },
      { id: "THEME-ID", onlyStream: true }
   );
</script>

ВАЖНО: Думаю, будет сложно полностью скрыть всю информацию от поисковиков и подобных систем. Поэтому, хотя этот метод лучше, чем простое скрытие через CSS, я не считаю, что он полностью предотвратит просмотр информации людьми.

ИЗМЕНЕНИЕ: Исправил, чтобы селекторы CSS работали. Повторяйте код для каждой группы, которую хотите использовать. Замените THEME-ID на уникальное имя. Я думаю, теперь это должно работать :slight_smile:

Ой, этот момент я пока не доделал:

Я действительно ценю ваши усилия по этому вопросу… Я всё ещё обдумываю это и считаю, что вы предложили мне рабочее решение. У меня есть шаблонный компонент, который я написал, и это заставляет меня думать, что я смогу реализовать что-то подобное…

Допустим, я представляю компонент «foobar». Я мог бы написать тему, добавив такие DIV-элементы:

<div data-custom="foobar" data-foobar="<groupname>">
</div>
<div data-custom="foobar" data-foobar="!<groupname>">
</div>

Затем компонент удаляет из DOM один из этих DIV-элементов в зависимости от группы, к которой принадлежит просматривающий пользователь.

Мне это кажется более надёжным, чем CSS display: none;, который легко переключить обратно через любые инструменты инспекции DOM в браузере. Чтобы обойти это, кто-то должен был бы изменить JavaScript, который выполняется при загрузке страницы — это возможно, но гораздо сложнее.

Зачем мне это нужно?

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

Это действительно интересная тема. Первый
абзац действительно увлекателен.

<div data-custom="foobar" data-foobar="<groupname>">
Вот остальная часть контента.
</div>

<div data-custom="foobar" data-foobar="!<groupname>">
Привет, извините за прерывание!
Здесь есть больше контента для наших платных участников...
хотите узнать, как стать одним из них?
</div>

Пользователи, входящие в группу, видят всю тему целиком. Никаких признаков платного доступа.

Пользователи, не входящие в группу, видят только начальную часть (не входящую ни в один из вышеуказанных DIV-элементов) и сообщение о платном доступе.

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

Наконец-то собрал это, так как https://github.com/Umbrella-CAST/discourse-umbrella-groupswitchdisplay. Всё очень просто: скрипт удаляет целевой DIV из DOM в зависимости от того, состоит ли текущий пользователь в группе с именем «foobar» или не состоит (обозначается как «!foobar»). Это позволяет легко переключать отображение контента, как на изображении ниже.

Конечно, если компонент отключён, то отображается весь контент (поскольку без компонента DOM не обрезается). Но этого достаточно для моих задач.

Вы решили одну из моих очень похожих проблем.