Neues Thema erstellen-Button mit Kategorie- und Themenvorlage

Ich betrachte folgendes Theme als Referenz:

Mein Ziel ist es, einen sekundären „Neues Thema"-Button zu implementieren, der nur für Mitglieder einer bestimmten Gruppe angezeigt wird. Diese Gruppe hat Zugriff auf einen privaten Bereich im Forum, und ich möchte, dass dieser Button unabhängig von der aktuellen Seite ein neues Thema in diesem Bereich startet. Zudem möchte ich für diesen Button eine Vorlage für Themen (Topic Template) oder eine ähnliche Boilerplate-Funktionalität verwenden. Ich habe zwar herausgefunden, wie ich den Button basierend auf der primären Gruppenklasse im <body>-Tag selektiv einblenden kann, bin mir aber derzeit noch nicht sicher, wie ich Boilerplate-Texte (oder eine Topic-Vorlage) in die mit diesem sekundären Button erstellten neuen Themen einfügen kann. Hat jemand dazu Tipps?

4 „Gefällt mir“

Das ist möglich. Du musst deine Kategorie zunächst mit einem Themen-Template vorbereiten. Gehe zur gewünschten Kategorie und bearbeite deren Themen-Template wie folgt:


Finde dann die ID der Kategorie heraus. Das kannst du tun, indem du zu your.site.com/categories.json gehst.

Hier auf Meta sieht das so aus:

Es gibt wahrscheinlich einen besseren Weg, die Kategorie-ID zu finden, aber diese Methode funktioniert hier wie benötigt.

Nehmen wir an, ich möchte die Kategorie bug verwenden. Die ID dafür wäre basierend auf /categories.json "1".

Für #feature wäre es "2" und so weiter.


Sobald du die ID hast und die Kategorie über ein Themen-Template verfügt, kannst du den Code aus dem Theme kopieren, einige Anpassungen vornehmen und ihn in eine separate Theme-Komponente einfügen.

Ich habe die Anpassungen hier bereits vorgenommen, sodass du diesen Code einfach kopieren und die Werte bei Bedarf ändern kannst:

<script type="text/discourse-plugin" version="0.8.18">
api.decorateWidget("header-buttons:after", helper => {
  if (api.getCurrentUser()) {
      
    // Passe diese beiden Werte nach Belieben an
    var $ntb_text = "Button-Text",
      $ntb_icon = "plus",
      
      // Diese Werte müssen nicht angepasst werden
      $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,

        // Setze unten die Kategorie-ID
        // Siehe site.com/categories.json
        // zur Referenz
        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>

Dies wird im <head>-Bereich unter „Allgemein“ eingefügt.


Sobald du fertig bist, solltest du etwas wie Folgendes haben: (Ich habe Ränder mit CSS hinzugefügt)

Wenn du auf den neuen Button klickst, öffnet sich der Composer mit der ausgewählten Kategorie, und das Themen-Template der Kategorie wird ebenfalls angezeigt.

Ich gehe davon aus, dass dies alles ist, was du brauchst, basierend auf:

16 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

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

2 „Gefällt mir“

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

1 „Gefällt mir“

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 „Gefällt mir“

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 „Gefällt mir“

Dies funktioniert nicht mehr. Eine neue Möglichkeit, den Button je nach Kategorie umzubenennen, wurde hier veröffentlicht:

So geht’s:

  1. Klonen oder laden Sie das Theme-Component von GitHub - VaperinaDEV/category-btn-name · GitHub herunter und entpacken Sie es.
  2. Bearbeiten Sie die Datei category-btn-name/locales/en.yml und geben Sie die gewünschten Button-Texte ein, z. B.:
en:
  new_event: Neuer Termin
  new_deadline: Neue Frist
  1. Bearbeiten Sie die Datei category-btn-name/javascripts/discourse/api-initializers/initialize-btn-names.js, um festzulegen, welcher Button-Text für welche Kategorien verwendet werden soll:
const TRANSLATION_KEYS = {
  "Events": "new_event",
  "Calendar": "new_event",
  "Deadlines": "new_dealine",
};
  1. Installieren Sie das Theme-Component.
2 „Gefällt mir“