홈페이지에서만 표시되는 사용자 지정 콘텐츠 추가

테마 개발자로 활동하다 보면 커뮤니티의 홈페이지에서만 표시되는 콘텐츠를 생성해야 하는 상황에 자주 직면하게 됩니다.

테마의 “After Header” 섹션에 일부 HTML을 추가하면 해당 콘텐츠가 모든 페이지에 표시됩니다. 홈페이지를 제외한 모든 곳에서 이를 숨기려면 CSS에서 여러 가지 우회 방법을 사용할 수 있지만, 대신 Discourse 테마를 사용하여 홈페이지에서만 표시되는 콘텐츠가 포함된 컴포넌트를 만들어 보겠습니다.

Discourse 테마에 익숙하지 않다면 Beginner's guide to using Discourse Themes 과 Structure of themes and theme components 을 확인해 보세요.

Discourse 테마에서 다음 디렉터리 구조를 설정해야 합니다:

:file_folder: javascripts/discourse/components/
:file_folder: javascripts/discourse/connectors/

이제 Ember 컴포넌트를 생성할 것입니다. Ember 컴포넌트에 대한 자세한 내용은 공식 문서에서 확인할 수 있습니다: Ember.js Guides - Guides and Tutorials - Ember Guides

하지만 당장은 로직과 템플릿이 모두 포함된 단일 .gjs 파일로 작성된 간단한 컴포넌트가 될 것입니다.

:page_facing_up: javascripts/discourse/components/custom-homepage-content.gjs

import Component from "@glimmer/component";
import { service } from "@ember/service";
import { defaultHomepage } from "discourse/lib/utilities";

export default class CustomHomepageContent extends Component {
  @service router;

  get isHomepage() {
    const { currentRouteName } = this.router;
    return currentRouteName === `discovery.${defaultHomepage()}`;
  }

  <template>
    {{#if this.isHomepage}}
      <h1>This is my homepage HTML content</h1>
    {{/if}}
  </template>
}

이것은 isHomepage getter를 생성하며, 라우터 서비스의 currentRouteName을 확인합니다. 라우트 이름이 홈페이지(사이트 설정에 의해 결정됨)와 일치하면 true를 반환합니다. <template>...</template> 내부의 템플릿은 해당 getter를 확인하고 true일 때만 콘텐츠를 표시합니다. {{#if}} 블록 사이에 원하는 HTML을 자유롭게 추가할 수 있습니다.

이제 컴포넌트가 생성되었으므로, 이를 Discourse의 어딘가에 추가해야 합니다. 이 단계에서는 어떤 플러그인 아웃렛(plugin outlet)을 사용할지 결정해야 합니다. 플러그인 아웃렛은 개발자가 코드를 연결할 수 있도록 Discourse 곳곳에 추가된 영역입니다. Github에서 이를 검색하거나 (deprecated) Plugin outlet locations theme component 에서 찾아볼 수 있습니다.

커스텀 홈페이지의 경우 above-main-container가 일반적인 선택지이므로, 이를 사용하겠습니다.

정확한 디렉터리에서 커넥터 파일을 생성해야 합니다:

:page_facing_up: javascripts/discourse/connectors/above-main-container/custom-homepage-connector.gjs

import CustomHomepageContent from "../../components/custom-homepage-content";

<template><CustomHomepageContent /></template>

:point_up: 그리고 이것이 전부입니다. 컴포넌트를 호출하는 한 줄만 필요할 뿐입니다 :tada:


이 문서는 버전 관리가 적용됩니다. 변경 사항을 github에서 제안해 주세요.

47개의 좋아요

@awesomerobot님,

설명해 주셔서 감사합니다. 제안해 주신 단계를 시도해 보았지만, 구현한 after_header가 여전히 게시글 상세 페이지에 표시됩니다. 이 문제를 어떻게 해결해야 할까요? 메인 페이지에만 표시되도록 수정하는 방법을 추천해 주실 수 있을까요?

1개의 좋아요

@Cornelius님, 코드 보는 거 괜찮을까요?

2개의 좋아요

모든 것을 헤더 태그에 넣는 대신, 파일 시스템을 현대적으로 활용하도록 이 내용을 다시 작성하면 좋겠습니다.

테마에 관한 이러한 오래된 가이드 중 대부분은 현재 작업 방식과 맞지 않아 시대에 뒤처져 있습니다.

7개의 좋아요

네, 꽤 오래된 내용이었습니다! 원격 테마 구조와 최신 Ember 컴포넌트를 반영하도록 업데이트했습니다.

6개의 좋아요

정말 멋진데요!

그 getter가 http://ember-cli-page-object.js.org/docs/v1.11.x/api/getter.html의 그것과 같은 건가요? 위험할 정도로만 아는 상태입니다. 만약 같다면, OP에 링크를 걸도록 수정하겠습니다.

3개의 좋아요

@awesomerobot 안녕하세요, kris. 제 시스템에 discourse를 로컬로 설치했습니다. 로컬 discourse 인스턴스에 이 파일들을 추가하려면 올바른 경로는 무엇인가요? 로컬 discourse 인스턴스에 새로운 theme-component를 추가하고 싶었습니다.

1개의 좋아요

테마 컴포넌트를 생성한 후 UX를 통해 설치합니다.

테마 또는 테마 컴포넌트 설치

테마 빌딩을 돕는 Discourse Theme CLI 콘솔 앱 설치

4개의 좋아요

카테고리 뷰 위에 홈페이를 구축하면, 홈 URL이 아닌 /categories로 이동하더라도 여전히 커스텀 콘텐츠가 표시됩니다. 이는 이전 코드가 수행하던 동작으로, 이 동작을 루트 URL /로만 제한하고 싶습니다. defaultHomepage()가 이를 처리해야 하는지 궁금합니다.

3개의 좋아요

discovery.${defaultHomepage()}는 top-menu 설정으로 지정된 랜딩 라우트와 일치합니다. 이는 루트 URL /뿐 아니라 /categories와 같은 특정 라우트와도 일치합니다.

defaultHomepage()를 기반으로 커스텀 홈페이지를 구축할 때, 제 경험상 두 가지 복잡한 문제가 있습니다.

  • 해당 라우트는 더 이상 단순한 목록 보기로 사용할 수 없습니다.
  • 회원들은 인터페이스 설정에서 자체 기본 홈페이지를 설정할 수 있습니다. 따라서 이 기능을 비활성화하거나, 상단 메뉴의 모든 라우트에서 작동하는 홈페이지 개념을 실제로 갖추는 것이 필요합니다.

루트 URL에서만 커스텀 홈페이지를 구축하려면 router.currentURL === '/'를 확인하면 됩니다. 기본적으로 이는 상단 메뉴 설정으로 지정된 랜딩 라우트가 아닌 루트 URL /만 일치시킵니다. 그러나 현재 사이드바 링크에는 주어진 URL을 라우트와 일치시키도록 하는 로직이 추가되었습니다. 따라서 기본적으로 사이드바 링크에서는 작동하지 않습니다. 이 문제에 대해 방금 토픽을 게시했습니다: URL을 라우트로 해석하지 않는 사이드바 링크를 사용할 수 있을까요?

제 이해에 따르면, 현재 상단 메뉴의 라우트를 대상으로 하거나 사이드바에서 문제를 겪지 않는 한, 루트 URL에 커스텀 홈페이지를 구축하는 기본 방법은 없습니다. 이 옵션을 사용할 수 있으면 좋겠습니다.

4개의 좋아요

맞습니다. /와 해당 /route가 서로 다른 콘텐츠를 렌더링할 수 있는 것은 오래된 해킹 방식(hack)입니다. 우리는 다음을 위한 할 일(todo)을 가지고 있습니다.

  1. top_menu 설정과 독립적으로 홈페이지를 설정할 수 있도록 허용
  2. 기존 라우트를 대체하지 않고도 커스터마이징할 수 있는 새로운 독립형 홈페이지 템플릿 추가

커스텀 홈페이지는 현재 매우 일반적인 요청 사항이므로, 여기에서 더 많은 유연성이 분명히 필요합니다.

6개의 좋아요