Some issues configuring a theme component to integrate with pretix

Hi -

I’ve yet to get this to work via any of the means I can find, and I’d like to know if it’s just my expectations that are awry.

I’m integrating with my pretix install (for selling event tickets). This should consist of simply adding HTML to a post, and ensuring that the pretix HTML and CSS are included.

<link rel="stylesheet" type="text/css" href="https://pretix.eu/demo/democon/widget/v1.css">
<script type="text/javascript" src="https://pretix.eu/widget/v1.en.js" async></script>

<!-- elsewhere, in a post -->
<pretix-widget event="https://pretix.eu/demo/democon/"></pretix-widget>
<noscript>
   <div class="pretix-widget">
        <div class="pretix-widget-info-message">
            JavaScript is disabled in your browser. To access our ticket shop without JavaScript,
            please <a target="_blank" href="https://pretix.eu/demo/democon/">click here</a>.
        </div>
    </div>
</noscript>

Obviously, the pretix scripts scan the document for the appropriate elements by tag, and then replace them with skinnable entries (as I’m after)

I believe I can (and wish to) achieve this integration lightly, and was thinking I could simply use the custom theme components to achieve this by including the external pretix scripts/styles, and adding the widget HTML to posts (i.e., with just ‘configuration’).

I first bumped into CSP protections (good) and the allowList (also good). Likewise, I’ve added the CSP configuration, but now I seemingly can’t alter the allowList without actual code alterations - so I’m left having to insert ‘flavoured’ HTML in posts, and then try alter them after rendering.

I proceeded to try to use some light JS in the theme component spec (just as an inline script) - something like this, just using the allowList’s [data-*] exclusion

function upgradeWidgets() {
    const divsWithDataEvent = document.querySelectorAll('div[data-event]');

    divsWithDataEvent.forEach((div) => {
      const attributes = div.attributes;
    
      for (let i = 0; i < attributes.length; i++) {
        const attr = attributes[i];
        if (attr.nodeName.startsWith('data-')) {
          const newAttrName = attr.nodeName.replace('data-', '');
          const attrValue = attr.nodeValue;
    
          div.setAttribute(newAttrName, attrValue);
          div.removeAttribute(attr.nodeName);
        }
      }
    });
}

Of course, this is now subject to timing issues - I can’t hook onload (the script gets removed from the theme component?!) and every other DOM event I can trap from scripts isn’t at a point where this post HTML is reliably available in the document.

I’m sure there’s some particularly idiomatic way of doing this all in Discourse - but I was hoping that I didn’t have to be a subject matter expert to perform this light of an integration.

Happy to get some guidance here.

Search for api.onPageChange() , that will give you a good place to handle this.

3 Likes

So this took a few distinct pieces to solve, I’ll note them here for future explorers.

  • <script type="text/discourse-plugin" /> (surprising)
  • loadScripts (neat)
  • api.decorateCookedElement (not the first thing I thought to search for)
  • api.pageLoaded (useful)

And with only ‘configuration’ I managed to integrate pretix and my Discourse site.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.