カテゴリとトピックテンプレート付きの新しいトピック作成ボタン

以下のテーマを参考にしています。

私の目的は、特定のグループのメンバーにのみ表示される「新しいトピック作成」ボタンをサブとして追加する方法を見つけることです。このグループはフォーラム内のプライベートエリアにアクセス可能であり、現在のページに関係なく、そのボタンを押すとそのプライベートエリアに新しいトピックが作成されるようにしたいと考えています。また、このボタンでトピックを作成する際に、トピックテンプレートや同様のボイラープレート機能を使用したいと考えています。ボディーのプライマリーグループクラスに基づいてボタンを条件付きで追加する方法はわかりましたが、このサブボタンで開始された新しいトピックにボイラープレートテキスト(またはトピックテンプレート)を挿入する方法については、現時点ではまだ十分には把握できていません。何かヒントがあれば教えてください。

「いいね!」 4

これは可能です。まず、カテゴリをトピックテンプレートで準備する必要があります。使用したいカテゴリに移動し、以下のようにそのトピックテンプレートを編集してください。


次に、カテゴリの ID を確認します。your.site.com/categories.json にアクセスすることで確認できます。

Meta での例は以下の通りです。

categoryId を見つけるより良い方法もあるかもしれませんが、ここではこれで問題なく動作します。

さて、bug カテゴリを使いたいとします。/categories.json に基づくと、その ID は "1" になります。

#feature の場合は "2"、といった具合です。


ID を取得し、カテゴリにトピックテンプレートが設定されていれば、テーマからコードをコピーし、いくつか修正を加えて、別のテーマコンポーネントに追加できます。

ここでは修正済みなので、これをコピーして必要に応じて値を変更するだけで使えます。

<script type="text/discourse-plugin" version="0.8.18">
api.decorateWidget("header-buttons:after", helper => {
  if (api.getCurrentUser()) {
      
    // これら 2 つをお好みに合わせて編集してください
    var $ntb_text = "button text",
      $ntb_icon = "plus",
      
      // これらは編集する必要はありません
      $ntb_icon_class = ".fa-" + $ntb_icon,
      $ntb_button_class = "btn btn-default btn btn-icon-text",
      $ntb_button_helper = "button#new-create-topic-custom",
      $ntb_icon_helper =
        "i.fa" + $ntb_icon_class + ".d-icon .d-icon-" + $ntb_icon,
      $ntb_label_helper = "span.d-button-label";

    const createTopicCustom = function() {
      const container = Discourse.__container__;
      const Composer = require("discourse/models/composer").default;
      const controller = container.lookup("controller:navigation/category");
      const composerController = container.lookup("controller:composer");

      composerController.open({
        action: Composer.CREATE_TOPIC,
        draftKey: Composer.DRAFT,

        // 以下にカテゴリ ID を設定してください
        // site.com/categories.json を参照
        categoryId: 3
      });
    };

    return helper.h(
      $ntb_button_helper,
      {
        className: $ntb_button_class,
        title: $ntb_text,
        onclick: createTopicCustom
      },
      [helper.h($ntb_icon_helper), helper.h($ntb_label_helper, $ntb_text)]
    );
  }
});

</script>

これは「Common」セクションの <head> 内に配置します。


完了すると、以下のようになります(CSS で余白を追加しています)。

新しいボタンをクリックすると、選択したカテゴリでコンポーザーが開き、そのカテゴリのトピックテンプレートも表示されます。

以下の内容に基づくと、これで必要なものはすべて揃ったと想定されます。

「いいね!」 16

Thanks Joe. I’ve already found a use for your instructions above. Very helpful.

Do you know how to create a PM, rather than posting into a category?

eg: Is there a CategoryID specifically for PM messages?

「いいね!」 1

For a PM you’d need to set a few of the composer options differently.

Something like this:

(Same as above, in a theme component in the </head> section)

<script type="text/discourse-plugin" version="0.8.18">
api.decorateWidget("header-buttons:after", helper => {
  if (Discourse.User.current()) {
    
    // edit these two to your liking
    var $ntb_text = "New Personal Message",
      $ntb_icon = "heart",
        
      // no need to edit these
      $ntb_icon_class = ".fa-" + $ntb_icon,
      $ntb_button_class = "btn btn-default btn btn-icon-text",
      $ntb_button_helper = "button#new-create-topic-custom",
      $ntb_icon_helper =
        "i.fa" + $ntb_icon_class + ".d-icon .d-icon-" + $ntb_icon,
      $ntb_label_helper = "span.d-button-label";

    const createPM = function() {
      const container = Discourse.__container__,
        Composer = require("discourse/models/composer").default,
        composerController = container.lookup("controller:composer");

      composerController.open({
        action: Composer.PRIVATE_MESSAGE,

        // 1- set recipients (Case Sensitive) or comment the line below
        usernames: "discobot,john,mike",

        // 2- set title or comment the line below
        topicTitle: "Title",

        // 3- uncomment the line below to set a "template" for PM.
        // Not really recommended will
        // override any drafts everytime the 
        // button is pressed 
        
        // topicBody: "placeholder content",

        // no need to change these
        archetypeId: "private_message",
        draftKey: Composer.NEW_PRIVATE_MESSAGE_KEY,

      });
    };

    return helper.h(
      $ntb_button_helper,
      {
        className: $ntb_button_class,
        title: $ntb_text,
        onclick: createPM
      },
      [helper.h($ntb_icon_helper), helper.h($ntb_label_helper, $ntb_text)]
    );
  }
});
</script>

Obviously, if you plan on using all three buttons you can reduce the size of the code quite drastically because most of it is shared by all three, but I kept things separate because some might just want to use one and not all three.

What this will do is add a button to the header like so:

Clicking the button will open the composer and the fields will be pre-filled with whatever you chose:

I already left a comment in the code about setting any placeholder content in the body for PMs using this method. It’s not recommended unless you have a very specific template. This will override any previously saved PM drafts everytime you use the button.

That’s why it’s “off” by default in the code above.

I’ve tested this a bit and have not seen any problems. If you encounter anything let me know.

「いいね!」 11

Love it. Worked perfectly. Thanks Joe, you’re awesome!

I noticed the user names are case sensitive. If a username’s case is wrong, the name appears in the recipient list, but the PM won’t send. Suggest you add this to your comments: -

    // 1- set recipients (Case Sensitive) or comment the line below 
    usernames: "discobot,john,mike",
「いいね!」 3

Hi @Johani - thank you, I have implemented this, but a bit too successfully!

Would it be possible to make a new personal message header button appear only selectively for those who have access to personal messaging? New users by default don’t have access to PM so should not see this button…

We have set the site setting (for our TL0, TL1 and TL2 users (who therefor are restricted from personal messaging))

Thanks again,

「いいね!」 1

Hi @jerry0

Yes, that is possible!

One way to do this is to look up the current user’s trust level and use that as a base to determine whether or not to create the PM button.

You would use something like this:

<script type="text/discourse-plugin" version="0.8.18">
// no need to edit these
const container = Discourse.__container__,
  controller = container.lookup("controller:application"),
  trust = controller.get("currentUser.trust_level");

api.decorateWidget("header-buttons:after", helper => {
  // change desired trust level here
  if (Discourse.User.current() && trust >= "2") {
    // edit these two to your liking
    var $ntb_text = "New Personal Message",
      $ntb_icon = "heart",
      // no need to edit these
      $ntb_icon_class = ".fa-" + $ntb_icon,
      $ntb_button_class = "btn btn-default btn btn-icon-text",
      $ntb_button_helper = "button#new-create-topic-custom",
      $ntb_icon_helper =
        "i.fa" + $ntb_icon_class + ".d-icon .d-icon-" + $ntb_icon,
      $ntb_label_helper = "span.d-button-label";

    const createPM = function() {
      const Composer = require("discourse/models/composer").default,
        composerController = container.lookup("controller:composer");

      composerController.open({
        action: Composer.PRIVATE_MESSAGE,

        // 1- set recipients (Case Sensitive) or comment the line below
        usernames: "discobot,john,mike",

        // 2- set title or comment the line below
        topicTitle: "Title",

        // 3- uncomment the line below to set a "template" for PM.
        // Not really recommended will
        // override any drafts everytime the
        // button is pressed

        // topicBody: "placeholder content",

        // no need to change these
        archetypeId: "private_message",
        draftKey: Composer.NEW_PRIVATE_MESSAGE_KEY
      });
    };

    return helper.h(
      $ntb_button_helper,
      {
        className: $ntb_button_class,
        title: $ntb_text,
        onclick: createPM
      },
      [helper.h($ntb_icon_helper), helper.h($ntb_label_helper, $ntb_text)]
    );
  }
});
</script>
「いいね!」 4

Well that is fab. I will have to wait to get back from my travels tomorrow but will try it out then. Thanks!

「いいね!」 2

I’ve now tried it out and it works well. Many thanks.

「いいね!」 1

Is it only possible to do this if u are able to code?

Um, no - I really can’t :grinning:… just followed the instructions above…

Would it be possible to change the button text for the default + New Topic button based on which category you’re browsing?

「いいね!」 2

Yes, that would also be possible as well. You can use something like this in the header section of a theme component

<script type="text/discourse-plugin" version="0.8">
const i18nTopicLable = I18n.lookup("topic.create");
api.modifyClass("component:create-topic-button", {
  didInsertElement: function() {
    var button = $(this),
      category = button[0].parentView.get("category"),
      label = button[0].label,
      newTopicLabel = "topic.create",
      buttonText = "";

    if (category) {
      categoryName = category.name;

      if (label != newTopicLabel) {
        return;
      } else {
        switch (categoryName) {
          case "category1": // category name
            buttonText = "category1 text"; // button text
            break;
          // repeat
          case "category2":
            buttonText = "category2 text";
            break;
          // add more above this line
          default:
            buttonText = i18nTopicLable;
        }
        $("#create-topic .d-button-label").text(buttonText);
      }
    }
  }
});
</script>

To add new categories, you only need to add this above where it says default

case "category":
  buttonText = "text";
  break;

If you have a pending draft and the button says “open draft” the script won’t fire.

I’ve created a small preview on theme creator and changed the text for the movies, tech, school, videos and gaming categories

Edit:
@dax informed me that I had missed something in the snippet I posted previously and so I updated it and the preview so be sure to use the latest one @tophee

「いいね!」 13

動作しなくなりました。カテゴリに応じてボタン名を変更する新しい方法がこちらに投稿されています:

手順:

  1. GitHub - VaperinaDEV/category-btn-name · GitHub からテーマコンポーネントをクローンするか、ダウンロードして解凍します。
  2. category-btn-name/locales/en.yml ファイルを編集し、使用したい各種ボタンのテキストを入力します。例:
en:
  new_event: New Event
  new_deadline: New Deadline
  1. category-btn-name/javascripts/discourse/api-initializers/initialize-btn-names.js ファイルを編集して、どのカテゴリにどのボタンのテキストを使用するかを定義します:
const TRANSLATION_KEYS = {
  "Events": "new_event",
  "Calendar": "new_event",
  "Deadlines": "new_dealine",
};
  1. テーマコンポーネントをインストールします。
「いいね!」 2