At present, the Oneboxes for events are a bit meh. Basically, they are no different to regular topic Oneboxes, and don’t include the date, time, description, etc etc (unless put into the Topic Title as a workaround).
Here is an example event from our site:
Would it be possible to hook into the new (and brilliant) cards that appear on click in the calendar for events, and serve these up as oneboxes? For example:
That might not be feasible at all, but I do wonder if the metadata could be modified for event posts so that they Onebox in a way that highlights the critical event info (especially internally).
בזמן שהתעסקתי עם תפריט ההקשר הזה, אני תוהה אם “הוסף ללוח שנה” יהיה ממוקם טוב יותר ישירות על הכרטיס. כל שאר הדברים הם די אדמיניסטרטיביים, אבל זה אחד שנועד לכל המשתמשים שיכול היה להיות בולט בממשק המשתמש.
In events posts I place the “add to calendar” option in an obvious spot; you may add this to the theme javascript header reachable from the admin appearance menu :
<script>
(() => {
const eventInfoSelector = ".event-header .event-info";
const submenuButtonSelector = "button.fk-d-menu__trigger.discourse-post-event-more-menu-trigger";
const menuContentSelector = ".fk-d-menu__inner-content";
const addToCalendarSelector = "li.add-to-calendar > button";
// Add inline CSS to keep text and icon black on hover
const style = document.createElement("style");
style.innerHTML = `
.btn.btn-icon-text.custom-add-to-calendar-btn,
.btn.btn-icon-text.custom-add-to-calendar-btn:hover {
color: black !important;
}
.btn.btn-icon-text.custom-add-to-calendar-btn svg,
.btn.btn-icon-text.custom-add-to-calendar-btn:hover svg {
fill: black !important;
}
`;
document.head.appendChild(style);
// Helper to wait for an element in the DOM
const waitForElement = (selector, timeout = 3000) => {
return new Promise((resolve, reject) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const found = document.querySelector(selector);
if (found) {
observer.disconnect();
resolve(found);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
observer.disconnect();
reject();
}, timeout);
});
};
const createAddToCalendarButton = async () => {
const eventInfo = document.querySelector(eventInfoSelector);
if (!eventInfo || eventInfo.querySelector(".custom-add-to-calendar-btn")) return;
const button = document.createElement("button");
button.className = "btn btn-icon-text custom-add-to-calendar-btn";
button.title = "Add to calendar";
button.innerHTML = `
<svg class="fa d-icon d-icon-file svg-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<use href="#file"></use>
</svg>
<span class="d-button-label">Add to calendar</span>
`;
// Inline styles for left alignment
button.style.display = "inline-flex";
button.style.justifyContent = "flex-start";
button.style.marginLeft = "0";
button.style.marginBottom = "4px";
button.style.backgroundColor = "#f0f0f0";
button.style.borderRadius = "6px";
button.style.transition = "transform 0.2s";
button.style.cursor = "pointer";
// Click logic: open menu and trigger original Add to Calendar
button.addEventListener("click", async () => {
const submenuButton = document.querySelector(submenuButtonSelector);
if (!submenuButton) return;
submenuButton.click(); // open menu
let menuContent;
try {
menuContent = await waitForElement(menuContentSelector, 2000);
} catch {
return;
}
const originalButton = menuContent.querySelector(addToCalendarSelector);
originalButton?.click();
});
// Insert into event-info
if (eventInfo.firstElementChild) {
eventInfo.insertBefore(button, eventInfo.firstElementChild.nextSibling);
} else {
eventInfo.appendChild(button);
}
};
// Observe DOM changes (Ember-safe)
const observer = new MutationObserver(() => createAddToCalendarButton());
observer.observe(document.body, { childList: true, subtree: true });
// Initial attempt
createAddToCalendarButton();
})();
</script>