기본 템플릿에 사용자 지정 변경 사항 적용하기

현재 주제 목록 페이지에서는 각 주제의 주요 참여자들의 아바타와 해당 사용자의 프로필 페이지로 연결되는 링크가 표시됩니다. 아래에서 확인할 수 있습니다:


사용자가 로그인되어 있지 않은 경우, 로그인 페이지로 리다이렉트되므로 이 링크는 클릭할 수 없습니다.

문제는 SEO 컨설턴트가 이것이 우리에게 문제가 된다고 판단하여, Google에서 해당 프로필 페이지 링크가 전혀 보이지 않도록 하기를 원한다는 점입니다.

주제 게시물 등에도 비슷한 문제가 있지만, 이 경우 모두 위젯 내부에 있었으며 api.reopenWidge() 등을 사용하여 비교적 쉽게 해결했습니다.

주제 목록 페이지는 다릅니다. 여기서는 raw-templates/list/posters-column.hbr의 내용을 변경해야 합니다!

이제 제가 시도해 본 것들을 설명하겠습니다. 이미 답을 알고 계신다면 끝부분으로 건너뛰셔도 좋습니다.

처음에는 입문자 가이드의 지시에 따라 위젯을 마운트해 보았습니다.

<script type="text/x-handlebars" data-template-name="list/posters-column">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
              {{mount-widget widget="custom-list-avatar"}}
            {{/if}}
        {{/each}}
    </td>
</script>

이것은 아무런 효과가 없었습니다. 결국 data-template-name 값에 .raw 확장자를 사용하는 테마를 발견했는데, 가이드가 단순히 구식이 된 것 같았습니다. raw 템플릿에 대한 언급이 없었기 때문입니다. .raw를 사용하면 위의 변경 사항이 렌더링되지만, 제 사용자 정의 위젯은 로드되지 않았습니다.

이것은 이상합니다. list/posters-column은 topic-list-item.hbr에 의해만 참조되며, 이 또한 raw 템플릿이고 그 가이드에서 사용된 템플릿 중 하나이기 때문입니다. 하지만… 역시 구식이 된 것일까요? 결국 어딘가에서 raw 템플릿에서는 위젯을 마운트할 수 없다는 것을 읽었습니다. 따라서 이것이 작동할 수 없었던 것 같습니다.

다음으로, 부분 템플릿(partials)을 발견하고 사용해 보았습니다. 해당 부분이 raw 템플릿이 아니므로 더 잘 작동할 것 같았습니다.

<script type="text/x-handlebars" data-template-name="components/custom-avatar">
    <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
</script>

<script type="text/x-handlebars" data-template-name="list/posters-column.raw">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
                {{partial 'components/custom-avatar'}}
            {{/if}}
        {{/each}}
    </td>
</script>

불행히도 raw 템플릿에서는 부분 템플릿도 사용할 수 없는 것 같아, 이 접근 방식도 실패했습니다.

그런 다음, 제가 필요로 하는 정보가 있을 것 같은 이 스레드를 발견했습니다. 그 접근 방식과 list/topic-list-item(이것이 list/posters-column을 호출함)이 topic-list-item 컴포넌트에서 사용된다는 점을 알고, 다음과 같은 코드를 작성했습니다:

<script type="text/x-handlebars" data-template-name="list/posters-column.raw">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
                {{#if hideFromAnonUser}}
                    <div data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</div>
                {{else}}
                    <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
                {{/if}}
            {{/if}}
        {{/each}}
    </td>
</script>

<script type="text/discourse-plugin" version="1.1.0">
    const settings = Discourse.SiteSettings;
    const user = api.getCurrentUser();
    const hideFromAnonUser = settings.hide_user_profiles_from_public && !user;
    const topicListItemComponent = require('discourse/components/topic-list-item').default;
    topicListItemComponent.reopen({
        hideFromAnonUser: function() {
            return hideFromAnonUser
        }.property()
    });
</script>

불행히도 hideFromAnonUser는 raw 템플릿에서 결코 보이지 않는 것 같습니다. 아마 hideFromAnonUser 키에 할당된 함수 내부에서 계산해야 하는 걸까요? 그렇지 않은 것 같습니다. 처음 세 줄의 const 할당을 주석 처리하고 단순히 False를 반환하도록 설정하거나, return 문 앞에 console.log() 호출을 추가해도, 그 함수가 아무것도 의해 실행되지 않는 것을 볼 수 있습니다.

이 시점에서 저는 막막합니다. 이 기술들을 이전에 사용해 본 적이 없어서, 제 능력 이상인 것 같습니다. 무언가를 놓쳤을 수도 있지만, 많은 정보가 오도하거나 구식이거나, 제가 잘못된 곳을 보고 있거나, 아니면 단순히 무언가를 오해하고 있는 것 같습니다.

주제 목록 페이지에서 아바타의 <a></a> 태그를 <div></div> 태그로 대체하는 방법은 무엇인가요? 감사합니다.

안녕하세요 @boltronics :wave:

이 코드는 list/posters-column 템플릿을 오버라이드합니다. topic-list-item 템플릿을 오버라이드하는 것보다 나은 선택일 수 있습니다.

<script type="text/x-handlebars" data-template-name="list/posters-column.hbr">
  <td class='posters topic-list-data'>
  {{#if currentUser}}
    {{#each posters as |poster|}}
      {{#if poster.moreCount}}
        <a class="posters-more-count">{{poster.moreCount}}</a>
      {{else}}
        <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
      {{/if}}
    {{/each}}
  {{else}}
    {{#each posters as |poster|}}
      <div data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</div>
    {{/each}}
  {{/if}}
  </td>
</script>

비로그인 사용자의 경우 a 태그가 아닌 div 태그를 사용해야 하므로, CSS도 추가해야 합니다.

데스크톱 / CSS

html.anon {
  .topic-list {
    .posters {
      width: 146px;
      > div {
        float: left;
        margin-right: 4px;
        &:last-of-type {
          margin-right: 0;
        }
      }
      div:first-child .avatar.latest:not(.single) {
        box-shadow: 0 0 3px 1px rgba(var(--tertiary-rgb), 0.35);
        border: 1px solid rgba(var(--tertiary-rgb), 0.5);
        position: relative;
        left: -2px;
      }
    }
  }
}

원시 템플릿(그리고 위젯!) 시스템이 곧 제거될 예정이라는 점도 주목할 만합니다. 물론 이것이 당장의 문제를 해결해 주지는 않지만요.

Glimmer Components가 이를 대체할 가능성이 높으므로, 더 많은 도구를 활용할 수 있는 리팩터링에 대비해 두시기 바랍니다:

@Don 정말 대단하시네요. 테스트해봤는데 제 문제를 완벽하게 해결해 주셨어요.

문제를 다른 방식으로 접근하신 점은 살짝 치트라고 할 수 있겠지만(거기서 currentUser 변수에 접근할 수 있다는 걸 몰랐거든요) 결과에 대해서는 뭐라 할 수가 없어요. :smile:

@merefield님, 다가오는 리팩토링에 대해 알려주셔서 감사합니다. 환경에서 잠재적인 회귀 문제를 감시하기 위해 테스트를 설정해 두겠습니다.

다들 감사합니다.

동작한다고 하니 다행이에요. 다만, 위에 올린 게시글에서 일부 수정을 했습니다. :slightly_smiling_face:
posters-more-count는 개인 메시지 주제 목록에 표시되므로 익명 사용자에게는 필요하지 않아요. 템플릿과 CSS에서도 해당 항목을 제거했습니다.

Don, 감사합니다. 처음부터 그럴 것 같았지만, 이전 시도를 통해 확인하지는 못했거든요. 알아서 다행입니다.