Улучшенная навигация для (структурированных) тегов

Всем привет,

Я пытаюсь обеспечить более структурированную видимость тегов в навигации, особенно для тех из нас, кто полагается на иерархию Родитель > Дети. У нас чуть более 40 тегов, поэтому структурированная навигация для тегов (что, предупреждаю, крайне недоиспользуется многими форумами, тогда как Discourse в этом преуспевает!) является весьма важной.

Поскольку добавлять несколько меню поверх нативной навигации Discourse — это глупо, моя идея (я думаю?) не предполагает ничего слишком драматичного. Я сделал грубый макет в качестве примера…

Если что-то подобное уже существует, я не могу этого найти. Компонент от @Johani ближе всего, но, к сожалению, не структурирован.

В любом случае, буду рад любым отзывам, даже если это будет «Это не имеет смысла» или «Мне потребовалось 10 секунд, чтобы найти это на GitHub, новичок».

Спасибо!

2 лайка

Учитывая количество тегов вида parent > child, которые могут быть на некоторых сайтах, не все из них поместятся там.

Например, посмотрите на теги на Meta:

https://meta.discourse.org/tags

2 лайка

Согласен с этим — я бы сказал, что пример [tip-toeing] meta не является лучшим способом использования тегов, хотя явных лучших практик в этом отношении нет. Но даже просто как опция для тех из нас, кто использует контролируемую лексику тегов и сильно полагается на них (гораздо больше, чем на категории), это может быть полезно. Мой пример был именно таким… Подозреваю, что у других могут быть лучшие идеи!

2 лайка

Почему бы просто не использовать страницу тегов? Вы можете выделить ссылку на эту страницу различными способами. Сама страница по умолчанию поддерживает структурирование по группам.

Затем вы можете добавить пользовательские стили, либо для тегов:

Либо стилизовать макет всей страницы, чтобы получить более специфичное представление.

2 лайка

Да, мне нравится страница тегов — и гибкость, которую она предоставляет. Это отлично. Но страница тегов не везде доступна, тогда как меню обеспечит динамическую, повсеместную навигацию, как это происходит с категориями.

Я подозреваю, что, как и я, есть среди нас те, кто полагается на теги гораздо больше, чем на категории. Это может показаться нелогичным, но в определённых контекстах это имеет смысл. Даже пример с автомобилями, использованный в посте Теги, выиграл бы от чего-то подобного. Если, например, это для автолюбителей, им может быть интереснее переключаться между тегами (“Ford против Ferrari”), а не категориями.

С другой стороны, возможно, вы пока не готовы к этому. Но ваши дети будут в восторге. :wink:

1 лайк

Я был бы рад, если бы вы нашли более динамичное решение! Но, думаю, это потребовало бы значительного объема кода, если вы хотите что-то, что не нужно поддерживать вручную. До тех пор я бы просто сделал ссылку на страницу тегов более заметной :wink:

Скриншот от 2021-10-22 21-57-26

Другой аспект, который, по моему опыту, делает теги гораздо более удобными для пользователей, — это правильные баннеры тегов. Я создал простой компонент как дополнение к компоненту tag-banners, который позволяет добавлять описания к тегам: https://github.com/nolosb/discourse-tag-banners-descriptions

3 лайка

Немного иное направление: я изменил отображение тегов на темах и в списках тем так, чтобы иерархия показывалась в виде хлебных крошек: «родитель > дочерний» вместо «дочерний, родитель».

Мое решение было несколько специфичным для сайта и довольно хаковским, но конечный результат мне нравится.

Главное препятствие для того, что я сделал, и для того, что вы хотите сделать, заключается в том, что Discourse не предзагружает группы тегов, поэтому они недоступны в нужный момент без выполнения API-запроса. Я считаю, что это должно быть реализовано так же, как и предзагрузка структуры категорий.

3 лайка

Проблема здесь заключается в ограниченном пространстве, а не в технических ограничениях.

как отмечено здесь

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

Вы будете перегружены, мягко говоря. Особенно учитывая, что в этом меню нет функции поиска, которая помогла бы вам сузить результаты.

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

Итак, как это реализовать?

Вот код:

<script type="text/discourse-plugin" version="0.8">
const MAX_TAGS_TO_SHOW = 20;
const Category = require("discourse/models/category").default;
const siteSettings = api.container.lookup("site-settings:main");
const tagStyle = siteSettings.tag_style;

const getNumberOfTags = (tags, categoryTagsGroups) => {
  let count = 0;
  count = tags.length;
  for (const categoryTagsGroup of categoryTagsGroups) {
    count = count + categoryTagsGroup.tags.length;
  }
  return count;
};

fetch("/tags.json")
  .then(response => response.json())
  .then(data => {
    try {
      const tags = data.tags;
      const hasCategoryTagGroups = data.extras?.categories;

      if (hasCategoryTagGroups) {
        const categoryTagsGroups = data.extras.categories;
        let moreCount = getNumberOfTags(tags, categoryTagsGroups);
        let visibleCount = 0;

        const content = [];
        for (const categoryTagsGroup of categoryTagsGroups) {
          const category = Category.findById(categoryTagsGroup.id);
          const name = category.name;
          const childTags = categoryTagsGroup.tags;
          const childTagNodes = [];

          childTags.forEach((tag, index) => {
            if (visibleCount <= MAX_TAGS_TO_SHOW) {
              childTagNodes.push(
                api.h(
                  "li.tag-link-item",
                  api.h(
                    `a.discourse-tag.tag-link.${tagStyle}`,
                    { href: `/tag/${tag.text}` },
                    tag.text
                  )
                )
              );
              moreCount--;
              visibleCount++;
            }
          });

          if (childTagNodes.length) {
            content.push([
              api.h("li.heading", api.h("span", name)),
              childTagNodes
            ]);
          }
        }

        api.decorateWidget("menu-links:after", helper => {
          if (helper.attrs.name !== "general-links") return;
          return api.h("div.clearfix", [
            api.h("ul.tag-links", [
              api.h("a.categories-link", { href: "/tags" }, [
                "Теги ",
                moreCount ? `(${moreCount} ещё)...` : ""
              ]),
              content
            ]),
            api.h("hr")
          ]);
        });
      }
    } catch (error) {
      console.error("В компоненте темы с тегами в гамбургер-меню возникла проблема");
      console.error(error);
    }
  })
  .catch(console.error);

</script>

Этот код следует разместить во вкладке header вашей темы. Вы можете изменить

const MAX_TAGS_TO_SHOW = 20;

в начале на количество тегов, которое хотите отображать.

Затем вам нужно добавить немного CSS для стилизации ссылок. Вот базовый пример, с которого можно начать.

.tag-links {
  .heading {
    padding: 0.25em 0.5em;
  }
  .tag-link-item {
    background-color: transparent;
    display: inline-flex;
    align-items: center;
    padding: 0.25em 0.5em;
    width: 50%;
    box-sizing: border-box;
    .tag-link {
      display: inline-flex;
      width: 100%;
      &:hover {
        color: var(--primary);
      }
    }
  }
}

Обратите внимание, что приведённый выше JavaScript будет учитывать стиль тегов, установленный в настройках вашего сайта. Кроме того, если ваш сайт сильно полагается на теги, возможно, вам не нужно отображать категории в этом меню. Их скрытие поможет снизить путаницу у пользователей.

Также, если вы добавите расширенный раздел с тегами, эта ссылка станет избыточной.

Поэтому давайте скроем их с помощью чего-то вроде этого.

.panel-body {
  .category-links,
  .categories-separator,
  .widget-link[href="/tags"] {
    display: none;
  }
}

Наконец, как отмечено здесь:

Эти данные по умолчанию не передаются клиенту, если вы не посетите /tags, поэтому код выше добавляет дополнительный запрос на главной странице (выполняется только один раз за посещение). Discourse старается сохранять всё максимально простым, поэтому, если данные не нужны, они не загружаются по умолчанию.

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

7 лайков

Спасибо, Джо, это великолепно!

Несколько быстрых вопросов… Я заметил, что ваш первоначальный ответ подтягивал теги по группе тегов (а не по дочерним тегам). Есть ли для этого причина? Мне не удалось вывести дочерние теги, но сработал ваш первоначальный ответ с использованием группы тегов.

Единственная проблема заключается в том, что теги не видны пользователям, не авторизовавшимся в системе. Я предполагаю, что это связано с API? Есть ли способ обойти это?

В остальном это просто подарок судьбы — я точно вижу, что другие тоже будут использовать этот код. Большое спасибо!

2 лайка

Я создал компонент темы, который должен немного упростить это. Вы можете выбрать между:

  1. вложенными группами тегов
  2. вложенными разрешёнными тегами категорий
  3. плоскими верхними тегами

Подробнее здесь:

1 лайк

Я выдвигаю Джо на звание Святого покровителя Discourse.

1 лайк

ха-ха-ха, я тоже как раз занимался созданием одного для своего учебного курса.

черт.

всё равно спасибо

2 лайка