Discourse 日历(与事件)

:partying_face: 此插件现已作为 Bundling more popular plugins with Discourse core 的一部分,与 Discourse 核心捆绑在一起。如果您是自托管用户并使用了此插件,则需要在下次升级前将其从 app.yml 中删除。

2 个赞

当然——这是你英文帖子的修改版,语气更友好、更开放:


我们需要能够限制活动参与者数量的功能,因为我们的许多活动都容量有限

目前,活动系统不允许我们:

  • 设置最大参与者数量,
  • 查看谁最先报名(没有注册时间戳),
  • 管理候补名单或在有名额空出时通知人们。

我们认为以下功能将非常有帮助:

  1. 参与者限制(上限),一旦满员就阻止更多用户报名。
  2. 候补名单,供活动满员后仍想参加的人员使用。
  3. 名额空出时自动通知
  4. 可选的时间戳,用于查看报名顺序(有助于公平排序)。

这对于举办线下或容量有限活动的社区来说将极其有用。

是否有任何类似的功能已在计划或开发中?
或者是否有针对这种情况的已知变通方法?

提前非常感谢!

4 个赞

感谢 Aurora — 很高兴听到原生日历功能已重新激活!

我们还想提出一项在社区讨论中多次被提及的高影响力请求:iCal Feed 同步。

这已在此处分解为一个专门的主题:

能够订阅外部 .ics Feed(例如学校时间表、市政日历或组织活动)并将其反映在 Discourse 主题日历中,将使此功能对许多实际部署更有用。没有它,我们被迫手动复制事件,这容易出错且难以维护。

我们非常感谢 Discourse 团队对该提案的任何评论——例如单向 iCal 同步、Feed 刷新间隔设置或可选事件标记——是否在即将实施的范围内。

无论如何,再次感谢您为 Discourse Calendar 注入新的活力——我们期待着未来的发展!

4 个赞

如果您想直接显示作曲家中的“创建事件”按钮,如下所示,请在主题的 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>

我尝试了脚本,创建事件按钮已成功创建,但当我单击它时,我得到了与“加号”按钮相同的上下文菜单。我可能操作失误了。

1 个赞

更新后有所改善,至少只显示“创建事件”

截图是德语,抱歉。

您好,

这在最新版本 3.5.0.beta9-dev 上运行正常,我不知道您的版本?

这是 JavaScript,所以当您在浏览器中按 F12 时,您应该提供 JS 错误控制台信息。

我使用的是相同的版本 3.5.0.beta9-dev
这是控制台消息


我一定做错了什么 :sweat_smile:

我不使用 Edge,你能用我刚在原帖更新的脚本再试一次吗?我发现了一些错误并已更正。如果它不起作用,我将在安装 Edge 后稍后更新。

我已经更新了脚本以提高移动兼容性,现在应该可以正常工作了,请从原始帖子中复制粘贴脚本

我确认更新后的代码在edge浏览器中运行正常。如果你有类似ublock的插件,你可以随时为你的discourse页面禁用它,但我不认为这有关联。

抱歉,我仍然遇到同样的问题,我一定做错了什么

但我确实在这里粘贴了你的脚本

1 个赞

好的,多亏了 Gilles 的情况,我能够根据图标唯一的 .svg 类来设置选择器,而不是使用会因语言而异的 title 属性。脚本现在也经过了最小化和 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=>{"use strict";const t=e.querySelector('svg use[href="#calendar-day"]');return t?t.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(()=>{"use strict";c.disconnect(),t()},2e3)}));try{(await r(o,c)).click(),l()}catch{}})},u=new MutationObserver(()=>{const t=document.querySelector(e);t&&(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 插件。
目前,当用户加入(回复)一个活动时,该主题会自动设置为“关注”,这意味着活动主题的每个新回复都会触发所有参与者的通知。

我们希望在用户加入活动后,默认将通知级别保留为“正常”

我已经检查了站点设置,但找不到适用的选项。
有没有办法禁用或更改用户回复活动时的自动“关注”行为?

我认为不行。但这将是一个有用的功能请求。

一个有用的解决方法可能是关闭主题以停止回复,但为其关联一个聊天频道(这些默认情况下不会通知)。

“Today”按钮上的标签可能具有误导性。

该按钮实际上并不能导航到当前日期,而是导航到活动时间范围选项卡(日/周/月/年)的当前视图。在日、周和月视图中,这确实会将当前日期显示在视图中。但在年视图中,它仅导航到当前年份(始终从一月开始)。

它可能应该:

  • 重命名以更准确地描述其功能,例如“Current”(当前)。
  • 或者,也许更好的是,不仅导航到当前年份,而且在年份列表中滚动到当前日期。
1 个赞