ホームページのみで表示されるカスタムコンテンツを追加

テーマ開発者として頻繁に遭遇する状況の一つに、コミュニティのホームページでのみ表示されるコンテンツを作成する必要があるというケースがあります。

テーマの「After Header」セクションにHTMLを追加すると、そのコンテンツはすべてのページに表示されるようになります。CSSで些細な処理(hoops)を施してホームページ以外では非表示にすることも可能ですが…ここでは、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 ゲッターが作成され、ルーターサービスの currentRouteName をチェックします。ルート名がホームページ(サイト設定によって決定される)と一致する場合、true を返します。<template>...</template> 内のテンプレートは、このゲッターを確認し、true の場合のみコンテンツを表示します。{{#if}} ブロックの間には、任意のHTMLを追加できます。

コンポーネントが作成されたので、次にDiscourseのどこかに追加する必要があります。このステップでは、使用するプラグインアウトレット(plugin outlet)を決定する必要があります。プラグインアウトレットとは、Discourse全体に配置された、開発者がフックするための小さなコード領域のことです。GithubでDiscourseを検索してこれらを見つけることも、(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: これだけです。コンポーネントを呼び出す1行だけで済みます :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のローカルインスタンスにこれらのファイルを追加するには、正しいパスは何ですか?ローカルインスタンスに新しいテーマコンポーネントを追加したいと考えています。

「いいね!」 1

テーマコンポーネントを作成し、ux を介してインストールします。

テーマまたはテーマコンポーネントのインストール

テーマの構築に役立つ Discourse Theme CLI コンソール アプリのインストール

「いいね!」 4

ホームページをカテゴリビューの上に構築した場合、ホームページのURLではない「/categories」にアクセスしても、カスタムコンテンツが表示されます。これをルートURL「/」に限定したいと考えています。以前のコードはそうしていたと思いますが、「defaultHomepage()」でそれができるのか疑問です。

「いいね!」 3

discovery.${defaultHomepage()} は、top-menu 設定でランディングルートとして設定されたルートに一致します。ルートURLの / と、/categories のような特定のルートの両方に一致します。

私の経験では、defaultHomepage() に基づいてカスタムホームページを構築する際に、2つの複雑な問題があります。

  • それが構築されるルートは、プレーンなリストビューとしてはもはや利用できません。
  • メンバーはインターフェース設定で独自のデフォルトホームページを設定できます。したがって、その機能を無効にするか、トップメニューのルートのいずれかで機能するホームページの概念を持つ必要があります。

ルートURLのみでカスタムホームページを構築するには、router.currentURL === '/' をチェックできます。デフォルトでは、これはルートURL / にのみ一致し、トップメニュー設定で設定されたランディングルートには一致しません。しかし、現在サイドバーリンクには、指定されたURLをルートに一致させるロジックがあります。そのため、デフォルトではサイドバーリンクでは機能しません。これについてはトピックを投稿しました。URLをルートに解決しないサイドバーリンクはありますか?

私の理解では、現在、トップメニューのルートをターゲットにするか、サイドバーで問題が発生するかのいずれかを除いて、ルートURLでカスタムホームページを構築するデフォルトの方法はありません。そのオプションがあると素晴らしいでしょう。

「いいね!」 4

はい、/ と対応する /route が異なるコンテンツをレンダリングできるというのは、長年のハックのようなものです。以下のようなToDoがあります。

  1. top_menu 設定とは独立してホームページを設定できるようにする
  2. 既存のルートを乗っ取ることなくカスタマイズできる、新しいスタンドアロンのホームページテンプレートを追加する

現時点ではカスタムホームページは非常に一般的なリクエストなので、ここでもっと柔軟性を持たせることは間違いなく可能です。

「いいね!」 6