Discourse Events

In der Konsole treten keine Fehler auf. Ich habe jedoch zur Referenz ein Video aufgenommen.
Dies tritt unter Chrome, Firefox und Safari auf. Auf Mobile Safari passiert es nicht.

1 „Gefällt mir“

Dein Videolink ist defekt!

Entschuldigung, ich habe es tatsächlich nicht richtig verstanden. Du hast recht: Wenn man im Kalender auf ein Datum klickt, öffnet sich das Modal zur Ereigniserstellung, aber mit der Schaltfläche „Möchten Sie abbrechen?“. Ja, es gibt tatsächlich einen kleinen Fehler :sweat_smile:

2 „Gefällt mir“

Zu Ihrer Information: Ich habe für meine Benutzer, die nicht daran denken, auf den Titel zu klicken, um Zugriff auf das Thema zu erhalten, einen „Mehr Infos“-Button hinzugefügt. Ich habe die Idee von @nathank für seinen „Zum Kalender hinzufügen“-Button übernommen.

Fügen Sie das Skript in einem Theme-Komponenten im allgemeinen /head-Bereich ein

<script>
(() => {
    const eventInfoSelector = ".event-header .event-info";
    const eventCardSelector = ".fc-popover, .event-preview, .discourse-post-event";
    // Sauberer, an Discourse-Themen (Hell/Dunkel) angepasster CSS-Einbau
    const style = document.createElement("style");
    style.innerHTML = `
    .custom-topic-info-btn {
        display: flex !important;
        align-items: center;
        justify-content: center;
        width: 40%; /* Nimmt die gesamte Breite ein für ein sauberes Erscheinungsbild unter dem Titel */
        box-sizing: border-box;
        margin: 12px 0 6px 0;
        padding: 10px 16px;
        
        /* Nutzung nativer Discourse-Variablen */
        background-color: var(--tertiary) !important; /* Akzentfarbe (z. B. Blau) */
        color: var(--secondary) !important;          /* Kontrastreiche Textfarbe */
        
        border-radius: 8px;
        font-weight: 700;
        text-decoration: none !important;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
        transition: background-color 0.2s ease, transform 0.1s ease;
    }
    /* Hover-Effekt */
    .custom-topic-info-btn:hover {
        background-color: var(--tertiary-hover) !important;
        color: var(--secondary) !important;
        transform: translateY(-1px);
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
    }
    /* Klick-Effekt */
    .custom-topic-info-btn:active {
        transform: translateY(0);
    }
    /* Stil des SVG-Symbols */
    .custom-topic-info-btn .btn-icon-svg {
        margin-right: 8px;
        width: 16px;
        height: 16px;
        fill: currentColor;
    }
    `;
    document.head.appendChild(style);
    const findTopicLink = (container) => {
        if (!container) return null;
        const links = [...container.querySelectorAll('a[href*="/t/"]')];
        if (links.length) return links[0].href;
        return null;
    };
    const createTopicInfoButton = () => {
        const eventInfo = document.querySelector(eventInfoSelector);
        if (!eventInfo || eventInfo.querySelector(".custom-topic-info-btn")) return;
        const card = eventInfo.closest(eventCardSelector) || document;
        const topicUrl = findTopicLink(card);
        if (!topicUrl) return;
        const button = document.createElement("a");
        button.className = "btn custom-topic-info-btn";
        button.title = "Vollständiges Thema ansehen";
        button.href = topicUrl;
        
        // Hinzufügen eines harmonisierten SVG-Infosymbols
        button.innerHTML = `
            <svg class="btn-icon-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V240h-24c-13.3 0-24-10.7-24-24s10.7-24 24-24h40c13.3 0 24 10.7 24 24v120h24c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144a32 32 0 1 1 0-64 32 32 0 1 1 0 64z"/>
            </svg>
            <span class="d-button-label">Mehr Infos</span>
        `;
        if (eventInfo.firstElementChild) {
            eventInfo.insertBefore(button, eventInfo.firstElementChild.nextSibling);
        } else {
            eventInfo.appendChild(button);
        }
    };
    const observer = new MutationObserver(() => createTopicInfoButton());
    observer.observe(document.body, { childList: true, subtree: true });
    createTopicInfoButton();
})();
</script>

Hier ist die Vorschau

oder alternativ

dieser Code hier

<script>
(() => {
    const eventCardSelector = ".fc-popover, .event-preview, .discourse-post-event";

    // CSS-Einbau für ein sauberes und modernes Erscheinungsbild
    const style = document.createElement("style");
    style.innerHTML = `
    .custom-topic-info-wrapper {
        margin-top: 16px;
        padding-top: 16px;
        border-top: 1px solid var(--primary-low); /* Subtile Trennlinie */
        width: 100%;
        display: flex;
        justify-content: center;
    }

    .custom-topic-info-btn {
        display: flex !important;
        align-items: center;
        justify-content: center;
        width: 100%;
        box-sizing: border-box;
        padding: 8px 16px;
        
        /* Eleganter Outline-Stil */
        background-color: transparent !important;
        color: var(--tertiary) !important;
        border: 1px solid var(--tertiary) !important;
        
        border-radius: 6px;
        font-weight: 600;
        text-decoration: none !important;
        transition: all 0.2s ease;
        cursor: pointer;
    }

    /* Hover-Effekt: Der Button füllt sich */
    .custom-topic-info-btn:hover {
        background-color: var(--tertiary) !important;
        color: var(--secondary) !important;
        border-color: var(--tertiary) !important;
    }

    /* Ausrichtung des Informationssymbols */
    .custom-topic-info-btn .btn-icon-svg {
        margin-right: 8px;
        width: 16px;
        height: 16px;
        fill: currentColor;
    }
    `;
    document.head.appendChild(style);

    const findTopicLink = (container) => {
        if (!container) return null;
        const links = [...container.querySelectorAll('a[href*="/t/"]')];
        if (links.length) return links[0].href;
        return null;
    };

    const createTopicInfoButton = () => {
        const cards = document.querySelectorAll(eventCardSelector);
        
        cards.forEach(card => {
            if (card.querySelector(".custom-topic-info-btn")) return;

            const topicUrl = findTopicLink(card);
            if (!topicUrl) return;

            const wrapper = document.createElement("div");
            wrapper.className = "custom-topic-info-wrapper";

            const button = document.createElement("a");
            button.className = "btn custom-topic-info-btn";
            button.title = "Vollständiges Thema konsultieren";
            button.href = topicUrl;
            
            // Info-Symbol „i“ + neuer, handlungsorientierter Text
            button.innerHTML = `
                <svg class="btn-icon-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                    <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V240h-24c-13.3 0-24-10.7-24-24s10.7-24 24-24h40c13.3 0 24 10.7 24 24v120h24c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144a32 32 0 1 1 0-64 32 32 0 1 1 0 64z"/>
                </svg>
                <span class="d-button-label">Thema konsultieren</span>
            `;

            wrapper.appendChild(button);

            /* Positionierung über den Antwortoptionen (Teilnehmen, etc.) */
            const actionsContainer = card.querySelector(".status-and-options, .event-actions");
            const infoContainer = card.querySelector(".event-info");
            
            if (actionsContainer && actionsContainer.parentNode) {
                actionsContainer.parentNode.insertBefore(wrapper, actionsContainer);
            } else if (infoContainer) {
                infoContainer.appendChild(wrapper);
            } else {
                card.appendChild(wrapper);
            }
        });
    };

    const observer = new MutationObserver(() => createTopicInfoButton());
    observer.observe(document.body, { childList: true, subtree: true });

    createTopicInfoButton();
})();
</script>

Vorschau des Ergebnisses

Sie haben die Wahl :rofl:

4 „Gefällt mir“

Sie haben die Erstellung eines Ereignisses seit den letzten Updates wirklich vereinfacht :+1:

Ich wollte jedoch wissen, ob es eine Einstellung gibt, die verhindert, dass ein Ereignis erstellt wird, wenn ein Benutzer im Kalender klickt. Manchmal klickt der Benutzer versehentlich neben das Ereignis, wodurch ein Modal zur Erstellung eines neuen Ereignisses geöffnet wird :sweat_smile:

Vielen Dank.

2 „Gefällt mir“

Ich weiß, dass ich lästig bin, aber ich habe eine weitere Frage bzw. Verbesserungsvorschlag zu abgelaufenen Ereignissen. Diese könnten automatisch gelöscht werden, da sie meiner Meinung nach keinen Zweck mehr erfüllen. Ich glaube, das Plugin „Events“ hat das automatisch gemacht.

Derzeit mache ich das manuell, also wäre es schön, wenn es eine Möglichkeit gäbe, Zeit zu sparen :sweat_smile:

Vielen Dank an das Team

1 „Gefällt mir“

Gibt es eine Möglichkeit, dass der Ort in der Veranstaltung eine Suchfunktion wie bei Google Kalender oder Facebook-Events durchführt, a) um dem Benutzer bei der Auswahl des Ortes zu helfen, und b) damit der Ort auf eine Kartenanwendung klickbar ist?

(Ich konnte durch Suchen keine Lösung finden, aber vielleicht waren meine Suchbegriffe nicht gut)

2 „Gefällt mir“

Das Locations Plugin 🌍 bietet zwar eine solche Funktionalität, ist jedoch nur mit dem alternativen Events Plugin 📅 integriert.

Der Entwickler (@merefield) könnte offen für eine Integration mit dem offiziellen Plugin sein, aber ich vermute, dass dies erhebliche Arbeit zur Einrichtung und Wartung erfordert – daher wäre eine Sponsierung der Arbeit definitiv erforderlich, damit dies möglich wird.

3 „Gefällt mir“

Ich habe versucht, das Events-Plugin zu prüfen, bin aber stecken geblieben bei

da die Seite seit Monaten offline ist.

1 „Gefällt mir“

Es könnte sich lohnen, eine formale Feature-Anfrage in Contribute > Feature (mit dem Tag calendar-and-events) zur Prüfung einzureichen. Ich kann mir gut vorstellen, dass dies machbar ist – und es hat das Potenzial, für viele einen hohen Mehrwert zu bieten.


später…
@lou hat dies hier tatsächlich getan:

3 „Gefällt mir“

Ein Beitrag wurde in ein bestehendes Thema verschoben: Unterstützung für Standortkarten von Veranstaltungen

Ich plane, die öffentlichen Events mit einem WordPress-Plugin auf eine WordPress-Website zu exportieren, das den ICS-Feed von /discourse-post-event/events.ics lesen kann. Soweit, so gut.

Auf dieser Website gibt es einige Seiten, die jeweils eine Teilmenge dieser Events anzeigen möchten. Jede Seite soll eine andere Teilmenge anzeigen.

Ich hatte gehofft, dass ich die Events mit einem Tag versehen kann, der jeder Seite zugeordnet ist, sodass dieser in der CATEGORIES-Zeile der ICS-Datei erscheint und das Filtern nach dem Zielsystem ermöglicht. Das scheint jedoch nicht zu funktionieren.

Ich wäre bereit, ?tag=[tag] in der URL zu verwenden und den verschiedenen Seiten unterschiedliche URLs zuzuweisen, obwohl ich bei meinen Recherchen keine entsprechende Funktion gefunden habe.

Habe ich etwas übersehen?

Nein, du lässt nichts übersehen (soweit ich weiß).

Die Möglichkeit, den Kalender-ICS-Feed nach Kategorie und/oder Tag zu filtern, wäre jedoch eine lohnenswerte #contribute:Feature-Anfrage!

1 „Gefällt mir“

Ich baue am Ende meinen eigenen Tag-Filter, aber ich glaube, ich habe gelernt, dass “abgelaufene” Events nicht über /discourse-post-event/events.ics heruntergeladen werden. Ich sehe auch keine Möglichkeit zu steuern, wann ein Event “abläuft”. Ich werde vielleicht eine Data-Explorer-Abfrage machen müssen, anstatt /…/events.ics zu verwenden.

[obwohl ich glaube, ich habe einen besseren Weg dafür mit /discourse-post-event/event gefunden]

1 „Gefällt mir“

Hi, ich suche nach Feedback zu einem Aspekt der Integration von Events mit Audio und Livestreams. Sieh dir die letzte Antwort hier an → https://meta.discourse.org/t/discourse-desktop-mac-app/406912/10?u=nicolsdennis

Hat jemand Erfahrung damit, VDO.Ninja in die Livestreaming-Übertragung von Events zu integrieren? Ich sehe die Zoom-Integration und denke, dass es vielleicht einen Weg gibt, das stattdessen mit VDO.Ninja zu realisieren, anstatt Zoom zu nutzen :thinking:

3 Beiträge wurden in ein neues Thema verschoben: Fragen zur Zoom-Livestream-Integration

Die Discourse Calendar / Events Upcoming Events-Routen scheinen alle Open Graph- und Twitter-Card-Metadaten aus der initialen serverseitig gerenderten HTML-Antwort auszublenden.

Dies lässt sich auf einer gehosteten Discourse-Instanz reproduzieren, auf der normale Seiten korrekt Social-Metadaten ausgeben und ein gültiges site-OpenGraph-Bild konfiguriert ist.

Beispiel für eine betroffene Route:

https://www.mbacommons.com/upcoming-events/month/2026/8/1

Schritte zur Reproduktion

  1. Konfiguriere ein gültiges site-OpenGraph-Bild.
  2. Bestätige, dass die Startseite oder ein normales Thema normale Open Graph-Metadaten im rohen HTML ausgibt.
  3. Öffne /upcoming-events/month/2026/8/1.
  4. Prüfe den rohen view-source:-Code bzw. die initiale Serverantwort, nicht das nach dem JavaScript-Laden generierte DOM.

Tatsächliches Ergebnis

Die Upcoming Events-Route gibt HTTP 200 zurück, aber das rohe HTML enthält:

  • kein og:image
  • kein og:title
  • kein og:description
  • kein og:url
  • kein twitter:card
  • kein twitter:image

Ich habe auch mit LinkedInBot/1.0 getestet; das Ergebnis ist identisch.

Eine Produktionsprüfung des rohen HTMLs auf derselben Instanz ergab:

  • Startseite: 11 Social-Metadaten-Tags
  • Normales Thema: 14
  • Upcoming Events: 0

Die Startseite und normale Themen verwenden korrekt das konfigurierte site-OpenGraph-Bild, sodass die site-weite Branding-Konfiguration selbst funktioniert.

Erwartetes Ergebnis

Upcoming Events-Routen sollten crawler-sichtbare, serverseitig gerenderte Social-Metadaten ausgeben, einschließlich mindestens:

  • og:title
  • og:description
  • og:url
  • og:image, mit Fallback auf das konfigurierte site-OpenGraph-Bild
  • Entsprechende Twitter-Card-Metadaten

Dies muss im initialen HTML enthalten sein, da LinkedIn und ähnliche Social-Crawler nicht auf clientseitiges Theme-JavaScript vertrauen können.

Der LinkedIn Post Inspector meldet derzeit:

Fügen Sie dem Seite ein og:image-Tag hinzu, um die Bildanzeige des Inhalts auf LinkedIn zu steuern.

Eine globale Theme-head_tag-Injektion scheint nicht angebracht, da normale Seiten bereits korrekte Metadaten haben und dies zu doppelnden oder widersprüchlichen Tags führen könnte. Dies erfordert offenbar eine route-spezifische serverseitige Behandlung für Upcoming Events oder die Nutzung des normalen Social-Metadaten-Rendering-Pfads von Discourse.

2 „Gefällt mir“

Peertube Live mit Discourse-Kalender und -Events

Das hat letzten Sommer (2025) mit Peertube noch einwandfrei funktioniert. Dabei wurde die Chat-Oberfläche zusammen mit dem Thema bereitgestellt (unter Verwendung der /embed/xxx-Video-URL zur Anzeige des Live-Videos und unter Berücksichtigung der ~30s Verzögerung aufgrund von P2P in Peertube), wenn mit #livestream getaggt wurde.

Aber als ich es heute erneut versucht habe, scheint der Chat nicht mehr wie früher in das Layout eingebettet zu sein (zumindest meiner Erinnerung nach). Außerdem gibt es auf der Event-Oberfläche keinen „Livestream-Button“. Ist das normal?

2 „Gefällt mir“

Hast du die kürzlich aktualisierten Anweisungen gesehen? Ich denke, die Benutzeroberfläche hat sich ein wenig geändert, als alles in dieses Plugin integriert wurde.

1 „Gefällt mir“