토픽 ID를 변수로 사용할 수 있나요?

공통 단어는 제가 원하는 것의 정반대입니다. 검색 결과에 모든 티켓이 나오길 원하지 않아요. 특정 티켓을 검색하는 방법을 원합니다. 그래서 토픽 ID가 이상적입니다. 그것들은 자동으로 생성되고 고유하니까요.

아니요, 제가 현재 사용 중인 코드도 원래 awesomerobot의 것이었던 것 같은데, 더 이상 그 출처를 찾을 수가 없네요.
저는 텍스트 아래에 있는 그 블록보다 현재 사용 중인 배치 방식을 더 선호합니다.

음, 저는 그걸 할 수 없어요. 아마 당신은 할 수 있을지도 모르겠네요.
<리암 니슨 목소리>저는 특정한 기술들을 가지고 있습니다. 코딩은 그중 하나가 아닙니다.</리암 니슨 목소리>

그러면 이 주제를 Marketplace 또는 #contribute:feature로 이동시키는 것이 좋겠습니다.

잘못 이해하셨네요. 제가 말한 것은 topic:id 매개변수를 포함하는 흔한 단어를 사용해서, 해당 주제에서 나온 결과만 보이게 하자는 뜻입니다. 이렇게 하면 'hi’나 ‘hello’ 같은 단어를 바꿀 필요가 없어요.

@tknospdr @pfaffman 주제 ID를 입력하고 해당 주제로 바로 이동할 수 있도록 하는 간단한 컴포넌트를 만들어 보았습니다.

새로운 컴포넌트를 만들고, CSS/HTML 편집 버튼 아래 있는 JS 탭에 아래 내용을 추가하세요.[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="Topic 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 탭 아래에 코드를 붙여넣었습니다. 테마에서 활성화되어 있는지 확인했지만, 반응이 없었습니다.
제 검색 페이지는 다음과 같습니다:

이것을 제 사이트에 설정해서 테스트해 봤는데, 작동은 하는 것 같지만, 아래 경고가 표시되어 조금 걱정됩니다:

브라우저 콘솔에 오류가 있나요?

이것이 유일한 오류입니다:

이것은 검색이 아니라 주제 ID를 표시하기 위한 JS 때문이라고 생각합니다. 해당 요소를 위해 지정해 둔 페이지를 제외하고는 표시되지 않습니다.

고급 검색 배너 구성 요소를 비활성화했다가 다시 활성화했는데, 이제 잘 작동합니다.
:man_shrugging:

자, 현재 상황의 요약을 정리하면 다음과 같습니다:

  1. 작동하는 솔루션이 있습니다. 다소 우아하지는 않지만, 표준 검색 상자에 바로 토픽 ID를 검색할 수 있을 때까지 제 용도에는 충분합니다.
  2. @awesomerobot님이 제안한 현재 코드는 작동하는 것 같지만, 위에서 게시한 경고가 발생합니다.
    2a. 토픽 ID를 표시하기 위해 사용하던 원래 코드를 제거했을 때, 이 경고가 사라졌습니다…
  3. 솔루션을 선택하면 토픽 ID를 표시하는 코드가 원래 게시글과 솔루션 양쪽에 모두 표시됩니다. 이를 고려하여 해당 위치에 표시되지 않도록 하는 방법이 있을까요?
  4. CSS를 조금 더 꾸며서, 이 기능을 사용하는 지정된 카테고리 내 모든 스레드의 모든 답글에 알약 모양(pill)이 표시됩니다. 아마도 꾸민 것을 되돌려야 할 것 같지만, 다른 방법을 아시는 분이 있다면 유지하고 싶습니다. 현재 상태가 꽤 보기 좋다고 생각하기 때문입니다.

@awesomerobot

작성하신 코드는 잘 작동하지만, 첫 번째 게시물을 제외한 나머지 게시물에서 텍스트를 제외한 모든 CSS 장식 요소가 CSS에 지정된 포맷대로 빈 공간으로 표시되는 것 같습니다.

인라인 블록을 끄면 전체 너비의 색상 막대가 표시되고,
배경색을 변경하면 필(Pill)의 색상이 변경되는 등

작성하신 내용을 보면 첫 번째 게시물에서만 표시되도록 설정한 것으로 보이지만, 이는 텍스트에만 영향을 미치는 것 같습니다. 추가 게시물들에서 해당 요소를 제거할 수 있는 다른 방법이 있을까요?

자, 말했듯이 나는 코더는 아니지만, Grok에게 질문하는 데는 꽤 능숙합니다. 여기 두 가지 문제를 모두 해결하는 코드가 있습니다.

  1. 2번부터 X번까지의 답변에서 더 이상 빈 CSS 버블이 표시되지 않습니다.
  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가 채워지는 부분입니다 -->
      Issue Tracking # is
      {{this.topicId}} 
      <!-- 위 내용을 수정할 수 있습니다 -->
    {{/if}}
  </template>
}

export default apiInitializer("0.8.40", (api) => {
  api.decorateCookedElement((element, helper) => {
```gjs
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가 채워지는 부분입니다 -->
      Issue Tracking # is
      {{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 (
    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 (
    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);
  });
});
      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);
  });
});

그리고 제 질문에 대한 답을 드리자면, 모든 코드를 새로운 테마 컴포넌트로 이동시켰는데도 여전히 정상적으로 작동합니다.