Discourse 日历(与事件)

如果您想直接显示作曲家中的“创建事件”按钮,如下所示,请在主题的 header 中使用以下代码。admin > appearance > theme > edit > edit code > head(确保将其放置在 <head> 标签之间)

在台式机 Firefox 的 discourse 3.5.0.beta9-dev 上测试

 <!-- Custom Create Event Button (Icon-based, Language-proof) -->
<script>
(() => {
  const composerSelector = ".d-editor-button-bar";
  const menuTriggerSelector = ".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 modalSelector = ".d-modal.fk-d-menu-modal";

  // Function to find the calendar icon button within the composer
  const findCalendarButton = (composer) => {
    const calendarIcon = composer.querySelector('svg use[href="#calendar-day"]');
    return calendarIcon ? calendarIcon.closest("button") : null;
  };

  // Function to wait for an element to appear and return it
  const waitForElement = (parentElement, selectorFn, timeout = 4000) => {
    return 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);
    });
  };

  // Function to wait for the modal to appear
  const waitForModal = (timeout = 4000) => {
    const observer = new MutationObserver(() => {
      if (document.querySelector(modalSelector)) {
        observer.disconnect();
      }
    });
    observer.observe(document.body, { childList: true, subtree: true });
    setTimeout(() => {
      observer.disconnect();
    }, timeout);
  };

  // Function to create and append the custom button
  const createAndAppendButton = (composer) => {
    if (composer.querySelector(".custom-create-event-btn")) return;

    const newButton = document.createElement("button");
    newButton.className = "btn no-text btn-icon toolbar__button link custom-create-event-btn";
    newButton.title = "Create event"; // Consider translating this title
    newButton.innerHTML = `
      <svg class="fa d-icon d-icon-calendar-day svg-icon">
        <use href="#calendar-day"></use>
      </svg>
    `;
    composer.appendChild(newButton);

    newButton.addEventListener("click", async () => {
      const trigger = document.querySelector(menuTriggerSelector);
      if (!trigger) return;

      trigger.click();

      let menuContent = document.querySelector(menuContentSelector);
      if (!menuContent) {
        // Wait for the menu content to appear
        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 {
        // Click the actual "Create Event" option within the menu
        await waitForElement(menuContent, findCalendarButton);
        await waitForElement(menuContent, findCalendarButton).click();
        waitForModal(); // Wait for the modal to appear after clicking
      } catch (error) {
        console.error("Error clicking create event:", error);
      }
    });
  };

  // Observe the body for the composer to appear
  const composerObserver = new MutationObserver(() => {
    const composer = document.querySelector(composerSelector);
    if (composer) {
      createAndAppendButton(composer);
    }
  });
  composerObserver.observe(document.body, { childList: true, subtree: true });

  // If the composer is already present, create the button
  const initialComposer = document.querySelector(composerSelector);
  if (initialComposer) {
    createAndAppendButton(initialComposer);
  }
})();
</script>