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

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>