Discourseカレンダー(およびイベント)

:partying_face: このプラグインは、Bundling more popular plugins with Discourse core の一部として、Discourse コアにバンドルされるようになりました。セルフホストでこのプラグインを使用している場合は、次回のアップグレード前に app.yml から削除する必要があります。

「いいね!」 2

Gerne – hier ist die überarbeitete, etwas freundlichere und offenere Version für deinen Beitrag auf Englisch:


We really need the ability to limit the number of participants for events, as many of our events have limited capacity.

Currently, the event system does not allow us to:

  • set a maximum number of participants,
  • see who signed up first (no registration timestamps),
  • manage a waitlist or notify people when a spot opens up.

We would find the following features very helpful:

  1. A participant limit (cap) that prevents more users from signing up once full.
  2. A waitlist for those who still want to attend after the event is full.
  3. Automatic notifications when a spot becomes available.
  4. Optional timestamps to see the order of sign-ups (useful for fair prioritization).

This would be incredibly useful for communities running in-person or capacity-limited events.

Is anything like this already planned or in development?
Or are there any known workarounds for this use case?

Thanks so much in advance!

「いいね!」 4

ありがとうございます、Aurora — ネイティブカレンダーの作業が再びアクティブになったと聞いて、本当に興奮しています!

また、コミュニティでの多くの議論で提起された、影響の大きい追加のリクエストを1つ紹介したいと思います。それはiCalフィード同期です。

これは、次の専用トピックに分割されました。

外部の.icsフィード(学校の時間割、市民カレンダー、組織のイベントなど)を購読し、それをDiscourseトピックカレンダーに反映させる機能は、多くの実際のデプロイメントでこの機能をはるかに役立つものにするでしょう。それがなければ、手動でイベントをコピーする必要があり、エラーが発生しやすく、維持が困難です。

Discourseチームから、提案の一部(一方向のiCal同期、フィード更新間隔の設定、オプションのイベントタグ付けなど)が今後の実装の範囲内にあるかどうかについて、コメントをいただけると大変助かります。

いずれにしても、Discourse Calendarに新しい命を吹き込んでいただき、改めて感謝いたします。今後の展開を楽しみにしています!

「いいね!」 4

Composer から直接イベント作成ボタンを表示したい場合は、以下のようにテーマのヘッダーにコードを追加してください。管理者 > 外観 > テーマ > 編集 > コードを編集 > head (タグの間に配置されていることを確認してください)

Discourse 3.5.0.beta9-dev (デスクトップ、Firefox) でテスト済み

<!-- カスタムイベント作成ボタン (アイコンベース、言語非依存) -->
<script>
(() => {
  const composerSelector = ".d-editor-button-bar";
  const calendarButtonSelector = ".btn.no-text.fk-d-menu__trigger.toolbar-menu__options-trigger.toolbar__button.options.toolbar-popup-menu-options";
  const menuContentSelector = ".fk-d-menu__inner-content";
  const menuModalSelector = ".d-modal.fk-d-menu-modal";

  // カレンダーアイコンを持つボタンを探す関数
  const findCalendarButton = (container) => {
    const svgUse = container.querySelector('svg use[href="#calendar-day"]');
    return svgUse ? svgUse.closest("button") : null;
  };

  // 要素が表示されるまで待機する関数
  const waitForElement = (parentElement, selectorFn, timeout = 4000) =>
    new Promise((resolve, reject) => {
      const element = selectorFn(parentElement);
      if (element) return resolve(element);

      const observer = new MutationObserver(() => {
        const foundElement = selectorFn(parentElement);
        if (foundElement) {
          observer.disconnect();
          resolve(foundElement);
        }
      });
      observer.observe(parentElement, { childList: true, subtree: true });
      setTimeout(() => {
        observer.disconnect();
        reject(new Error("Element not found within timeout"));
      }, timeout);
    });

  // メニューモーダルが表示されるまで待機する関数
  const waitForMenuModal = (timeout = 4000) => {
    const observer = new MutationObserver(() => {
      if (document.querySelector(menuModalSelector)) {
        observer.disconnect();
      }
    });
    observer.observe(document.body, { childList: true, subtree: true });
    setTimeout(() => observer.disconnect(), timeout);
  };

  // カスタムボタンを作成して追加する関数
  const addCustomCreateEventButton = (container) => {
    if (container.querySelector(".custom-create-event-btn")) return;

    const button = document.createElement("button");
    button.className = "btn no-text btn-icon toolbar__button link custom-create-event-btn";
    button.title = "Create event"; // 言語非依存のタイトル
    button.innerHTML = `<svg class="fa d-icon d-icon-calendar-day svg-icon"><use href="#calendar-day"></use></svg>`;
    container.appendChild(button);

    button.addEventListener("click", async () => {
      const calendarButton = document.querySelector(calendarButtonSelector);
      if (!calendarButton) return;

      calendarButton.click();

      let menuContent = document.querySelector(menuContentSelector);
      if (!menuContent) {
        // メニューコンテンツが表示されるまで待機
        await new Promise((resolve, reject) => {
          const observer = new MutationObserver(() => {
            menuContent = document.querySelector(menuContentSelector);
            if (menuContent) {
              observer.disconnect();
              resolve();
            }
          });
          observer.observe(document.body, { childList: true, subtree: true });
          setTimeout(() => {
            observer.disconnect();
            reject(new Error("Menu content not found within timeout"));
          }, 2000);
        });
      }

      try {
        // イベント作成ボタンが表示されるまで待機し、クリック
        await waitForElement(menuContent, (el) => findCalendarButton(el));
        const createEventButton = findCalendarButton(menuContent);
        if (createEventButton) {
          createEventButton.click();
          waitForMenuModal(); // メニューモーダルが表示されるのを待つ
        }
      } catch (error) {
        console.error("Error clicking create event button:", error);
      }
    });
  };

  // コンポーザーが表示されたときにカスタムボタンを追加するオブザーバー
  const observer = new MutationObserver(() => {
    const composer = document.querySelector(composerSelector);
    if (composer) {
      addCustomCreateEventButton(composer);
    }
  });
  observer.observe(document.body, { childList: true, subtree: true });

  // 初期ロード時にコンポーザーが存在する場合にボタンを追加
  const initialComposer = document.querySelector(composerSelector);
  if (initialComposer) {
    addCustomCreateEventButton(initialComposer);
  }
})();
</script>

スクリプトを試しましたが、イベント作成ボタンは正常に作成されました。しかし、それをクリックすると、プラスボタンと同じコンテキストメニューが表示されます。私の操作が悪かったのかもしれません。

「いいね!」 1

アップデート後、少なくとも「イベントを作成」のみが表示されるようになり、改善されました。

スクリーンショットはドイツ語です。申し訳ありません。

こんにちは。

これは3.5.0.beta9-devの最新バージョンで動作します。お使いのバージョンはわかりません。

これはJavaScriptなので、ブラウザでF12を押したときにコンソールに表示されるJSエラーを提供してください。

バージョン3.5.0.beta9-devは同じです。
コンソールメッセージは以下の通りです。


何か間違っているに違いありません :sweat_smile:

Edgeは使用していません。元の投稿で更新したスクリプトで再度試していただけますか。間違いを見つけて修正しました。それでも動作しない場合は、Edgeをインストールした後に更新します。

スクリプトをモバイル互換性のあるものに更新しました。これで動作するはずです。元の投稿からスクリプトをコピー&ペーストしてください。

更新されたコードがエッジで正常に動作することを確認しました。ublockのようなものがある場合は、ディスコースページで無効にすることができますが、それに関連しているとは思いません。

申し訳ありませんが、私にはまだ同じ問題があります。何か間違っているのだと思います。

それでも、あなたのスクリプトをここに貼り付けています。

「いいね!」 1

Gillesの状況のおかげで、言語によって異なるタイトル属性ではなく、アイコンの一意の.svgクラスに基づいたセレクターを設定できました。スクリプトはミニファイされ、IIFEでラップされています。

更新されたスクリプトは Discourse Calendar (and Event) - #535 by opcourdis で見つけることができます。

「いいね!」 1

お手伝いいただきありがとうございます :+1:

「いいね!」 1

スクリプトを#theme-componentとしてラップし、適用されるカテゴリを選択できるようにしていただけると非常に役立ちます。

私が考えているユースケースは、「イベント」カテゴリで、イベント投稿を非常にわかりやすくしたいと考えています。

「いいね!」 1

以下を使用し、カテゴリを指定するために最初の条件を変更できます。ボタンをより見やすくするために、CSS で次のように設定します。.btn.no-text.btn-icon.toolbar__button.link.custom-create-event-btn {
order: -1;
}

<script>(()=>{if(!(document.body.classList.contains("category-events")||document.body.classList.contains("category-event2")||document.body.classList.contains("category-event3")))return;const e=".d-editor-button-bar",t=".btn.no-text.fk-d-menu__trigger.toolbar-menu__options-trigger.toolbar__button.options.toolbar-popup-menu-options",n=".fk-d-menu__inner-content",o=".d-modal.fk-d-menu-modal",c=e=>e.querySelector('svg use[href="#calendar-day"]')?e.querySelector('svg use[href="#calendar-day"]').closest("button"):null,r=(e,t,n=4e3)=>new Promise((o,c)=>{const r=t(e);if(r)return o(r);const l=new MutationObserver(()=>{const n=t(e);n&&(l.disconnect(),o(n))});l.observe(e,{childList:!0,subtree:!0}),setTimeout(()=>{l.disconnect(),c()},n)}),l=(e=4e3)=>{const t=new MutationObserver(()=>{document.querySelector(o)&&t.disconnect()});t.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>t.disconnect(),e)},s=e=>{if(e.querySelector(".custom-create-event-btn"))return;const o=document.createElement("button");o.className="btn no-text btn-icon toolbar__button link custom-create-event-btn",o.title="Create event",o.innerHTML='<svg class="fa d-icon d-icon-calendar-day svg-icon"><use href="#calendar-day"></use></svg>',e.appendChild(o),o.addEventListener("click",async()=>{const e=document.querySelector(t);if(!e)return;e.click();let o=document.querySelector(n);o||(await new Promise((e,t)=>{const c=new MutationObserver(()=>{o=document.querySelector(n)&&c.disconnect(),e()});c.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>c.disconnect(),t)},2e3)}));try{(await r(o,c)).click(),l()}catch{}})},u=new MutationObserver(()=>{const t=document.querySelector(e);t&&(u.disconnect(),s(t))});u.observe(document.body,{childList:!0,subtree:!0});const d=document.querySelector(e);d&&s(d)})();</script>


ご提案ありがとうございます。Discourseはまだ慣れていないので、テーマコンポーネントを確認します。ボタンの配置は確かに改善されましたが、イベント参加者制限に関する他のスクリプトは、FEATURE: introduce max attendees for events by SamSaffron · Pull Request #34313 · discourse/discourse · GitHub により不要になるかもしれません。

「いいね!」 4

Discourse の最新バージョンと discourse-calendar プラグインにアップグレードした後、管理者として次の警告が表示されます。

⚠️ 一部の投稿コンテンツデコレーターでエラーが発生したため、投稿が正しく表示されない可能性があります。
プラグイン 'discourse-calendar' によって引き起こされました
(このメッセージはサイト管理者にのみ表示されます)
  • カレンダープラグインが機能しなくなりました。トピックにカレンダーのコンテンツやイベントが表示されません。
  • プラグインは最近のアップグレード前は正常に機能していました。
  • 私の Discourse サイトとすべての公式プラグインは現在最新の状態です。

フォーラムで Discourse Post Event プラグインを使用しています。
現在、ユーザーがイベントに**参加(RSVP)すると、トピックは自動的に「Watching」**に設定されます。これは、イベントトピックへの新しい返信ごとに、すべての参加者に通知がトリガーされることを意味します。

イベントに参加した後も、デフォルトの通知レベルを**「Normal」に維持したい**と考えています。

サイト設定を確認しましたが、該当するオプションは見つかりませんでした。
ユーザーがイベントにRSVPした際の自動「Watching」動作を無効化または変更する方法はありますか?

いいえ、できないと思います。しかし、これは便利な機能リクエストになるでしょう。

便利な回避策としては、トピックを返信不可にすることですが、それに関連付けられたチャットチャンネル(デフォルトでは通知されません)を持つことができます。

「今日」ボタンのラベルは誤解を招く可能性があります。

このボタンは実際には現在の日付に移動するのではなく、アクティブなタイムフレームタブ(日/週/月/年)の現在のビューに移動します。日、週、月では、現在の日が表示されます。しかし、年では、現在の年にのみ移動します(常に1月に始まります)。

おそらく、

  • 機能により正確に説明するように、「現在」のような名前に変更する必要があります。
  • または、おそらくより良いのは、現在の年に移動するだけでなく、年のリストで現在の日までスクロールすることです。
「いいね!」 1