ID темы как переменная?

Общее слово — это противоположность тому, что мне нужно. Я не хочу, чтобы в результатах поиска отображались ВСЕ тикеты, мне нужен способ найти конкретный тикет. Вот почему ID темы был бы идеален. Они генерируются автоматически и уникальны.

Нет, я думаю, что код, который я использую, тоже изначально был от awesomerobot, но я больше не могу найти его источник.
Мне больше нравится расположение того, что я использую сейчас, чем тот блок под текстом.

Ну, я не могу этого сделать. Возможно, вы можете.
<голос Лиам Нисон>У меня есть определённый набор навыков. Программирование не входит в их число.</голос Лиам Нисон>

Тогда, возможно, тебе стоит переместить эту тему в Marketplace или #feature.

Вы меня неправильно поняли. Я имел в виду использование обычного слова вместе с параметром topic:id, чтобы отображались результаты только из этой темы. Обычное слово избавляет от необходимости менять такие слова, как «привет» и «здравствуйте».

@tknospdr @pfaffman Я быстро собрал компонент, который позволяет ввести ID темы и перейти к ней.

Создайте новый компонент и добавьте этот код во вкладку JS под кнопкой Изменить CSS/HTML[1]:

import { apiInitializer } from "discourse/lib/api";
import Component from '@glimmer/component';
import { action } from "@ember/object";
import Form from "discourse/components/form";
import DiscourseURL from "discourse/lib/url";

export default apiInitializer((api) => {
    api.renderBeforeWrapperOutlet("full-page-search-filters", 
        class GoToTopic extends Component {
            @action
            handleSubmit(data) {
                DiscourseURL.routeTo(`/t/${data.id}`);
            }
            
            
            <template>
                <div class="topic-id-go-to" style="margin-top: 1em;">
                    <Form @onSubmit={{this.handleSubmit}} as |form|>
                    
                      <form.Field @name="id" @title="ID темы" as |field|>
                        <field.Input @type="number" @validation="required" />
                      </form.Field>
                    
                      <form.Submit />
                    </Form>
                </div>
            </template>
        }
    );
});

Это добавляет поле ввода на страницу поиска:


Кнопка Отправить предназначена для перехода к теме[2]; она не влияет на результаты поиска.

Надеюсь, это поможет!


  1. Это мой первый опыт использования FormKit, он действительно крутой ↩︎

  2. Я не мог изменить текст кнопки, так как для этого потребовались бы локализации… что, в свою очередь, потребовало бы создания целого репозитория TC, что, возможно, излишне :person_shrugging: ↩︎

Спасибо @NateDhaliwal, я ценю ваши усилия.
Я создал компонент, вставил код во вкладку JS. Убедился, что он активен в моей теме, но безрезультатно.
Вот как выглядит моя страница поиска:

Я настроил это на своём сайте, чтобы поэкспериментировать, и, похоже, это работает, однако я получил это предупреждение, которое заставляет меня задуматься:

Есть ли ошибки в консоли браузера?

Это единственная ошибка:

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

Я отключил, а затем снова включил компонент баннера расширенного поиска, и теперь он работает.
:man_shrugging:

Итак, краткое изложение текущей ситуации:

  1. У нас есть рабочее решение. Хотя оно немного неуклюжее, оно удовлетворит мои потребности до тех пор, пока мы не сможем искать ID темы прямо в стандартном поле поиска.
  2. Предложенный @awesomerobot код, похоже, работает, но вызывает предупреждение, которое я опубликовал выше.
    2a. Когда я удалил исходный код, который использовал для отображения ID темы, это предупреждение исчезло…
  3. Когда вы выбираете решение, код для отображения ID темы появляется как в исходном сообщении, так и в решении. Есть ли способ учесть это и предотвратить его отображение там?
  4. Я немного улучшил CSS: теперь на каждом ответе в каждой теме в указанных категориях, где я это использую, отображается «пилюля». Думаю, ответ будет в том, чтобы убрать эти улучшения, но если кто-то знает другой способ, я бы предпочел оставить всё как есть — мне кажется, это выглядит приятно.

@awesomerobot
Ваш код работает отлично, но, похоже, любые CSS-декорации, кроме текста, отображаются в каждом посте после первого как пустое пространство, отформатированное в соответствии с CSS.

Если отключить inline-block, получится цветная полоса на всю ширину.
Измените цвет фона, и «пилюля» изменит цвет.
И так далее…

Судя по вашему описанию, вы указали отображать элемент только в первом посте, но это влияет только на текст. Есть ли что-то ещё, что можно сделать, чтобы скрыть этот элемент во всех остальных постах?

Хорошо, как я уже говорил, я не программист, но отлично умею задавать вопросы Grok. Вот код, который решает обе проблемы:

  1. Больше никаких пустых CSS-пузырей в ответах со 2-го по X-й.
  2. Больше никакого дублирования ID темы в цитируемых решениях.

Возможно, никому больше на планете это не важно, но это кажется хорошим способом отслеживать темы для тех из нас, кто использует Discourse как систему тикетов.

import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";

class TopicIdentifier extends Component {
  get topicId() {
    return this.args.post?.topic?.id;
  }

  get shouldShow() {
    const firstPost = this.args.post?.post_number === 1; // первое сообщение в теме
    const desiredCategories = [9, 23]; // список ID категорий, в которых должно отображаться (через запятую)
    const isInCategory = desiredCategories.includes(
      this.args.post?.topic.category.id
    );

    return firstPost && isInCategory;
  }

  <template>
    {{#if this.shouldShow}}
      <!-- ниже можно редактировать содержимое, {{this.topicId}} — место, куда будет подставлен ID темы -->
      Номер отслеживания задачи: 
      {{this.topicId}} 
      <!-- выше можно редактировать содержимое -->
    {{/if}}
  </template>
}

export default apiInitializer("0.8.40", (api) => {
  api.decorateCookedElement((element, helper) => {
    // Продолжать только если это первое сообщение и оно не внутри цитаты решения
    // Продолжать только если это первое сообщение, не в цитате и в нужной категории
    const post = helper?.model;
    const desiredCategories = [9, 23]; // Соответствует категориям из TopicIdentifier
    if (
      helper?.model?.post_number !== 1 ||
      !post ||
      post.post_number !== 1 ||
      !desiredCategories.includes(post.topic?.category?.id) || // Проверка категории
      element.classList.contains("post__contents-cooked-quote") || // Проверка, является ли сам элемент содержимым цитаты
      element.closest("aside.accepted-answer") || // Проверка обёртки решения/цитаты
      element.closest(".quote") // Дополнительная проверка для обычных цитат
    ) {
      return;
    }

    const wrapper = document.createElement("div");
    wrapper.className = "tracking-id";

    helper?.renderGlimmer(
      wrapper,
      <template><TopicIdentifier @post={{helper.model}} /></template>
    );

    element.appendChild(wrapper);
  });
});

Раньше я не смог к этому вернуться, но я рад, что вы сами всё разобрали! Это выглядит как разумное решение.

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

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

import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";

class TopicIdentifier extends Component {
  get topicId() {
    return this.args.post?.topic?.id;
  }

  get shouldShow() {
    const firstPost = this.args.post?.post_number === 1; // первое сообщение в теме
    const desiredCategories = [9, 23]; // список ID категорий, разделённый запятыми, в которых должно отображаться это
    const isInCategory = desiredCategories.includes(
      this.args.post?.topic.category.id
    );

    return firstPost && isInCategory;
  }

  <template>
    {{#if this.shouldShow}}
      <!-- ниже можно редактировать контент, {{this.topicId}} — здесь будет подставлен ID темы -->
      Номер отслеживания: #
      {{this.topicId}} 
      <!-- выше можно редактировать контент -->
    {{/if}}
  </template>
}

export default apiInitializer("0.8.40", (api) => {
  api.decorateCookedElement((element, helper) => {
    // Продолжать только если это первое сообщение и оно не внутри цитаты с решением
    // Продолжать только если это первое сообщение, не в цитате и в нужной категории
    const post = helper?.model;
    const desiredCategories = [9, 23]; // Соответствует категориям из TopicIdentifier
    if (
      helper?.model?.post_number !== 1 ||
      !post ||
      post.post_number !== 1 ||
      !desiredCategories.includes(post.topic?.category?.id) || // Проверка категории
      element.classList.contains("post__contents-cooked-quote") || // Проверка, является ли сам элемент содержимым цитаты
      element.closest("aside.accepted-answer") || // Проверка на обёртку решения/цитаты
      element.closest(".quote") // Дополнительная проверка для обычных цитат
    ) {
      return;
    }

    const wrapper = document.createElement("div");
    wrapper.className = "tracking-id";

    helper?.renderGlimmer(
      wrapper,
      <template><TopicIdentifier @post={{helper.model}} /></template>
    );

    element.appendChild(wrapper);
  });
});

И чтобы ответить на свой собственный вопрос: я перенёс весь код в новый компонент темы, и всё продолжает работать нормально.