Display different content within a topic based on user's groups membership?

I’m working in discourse.org’s hosting, so plugins are not possible for me in this case. Imagine I have a topic posted where anyone can see it.

If someone is in group “A” then I want them to see this content. If NOT, then I want them to see this other content. And some of the topic everyone should see. Schematically like this…

This is content everyone sees.

{wishful thinking: only for ppl in group A}
Hey thanks for being in the special group!
{/wishful}

{wishful thinking: only for ppl NOT in group A}
Hey we have a special group you can join. [Read more about that](…)
{/wishful}

I feel confident (but forget exactly how to do it) that this can be done with a theme component to set CSS classes on the content I want to “toggle” display of. I’ll do this if this is the best I can figure out.

But CSS display: none is weak sauce. I’d like to disappear from the DOM what they shouldn’t see. Disappeared server-side if possible, but I’d settle for at least j/s based disappeared browser-side. (That requires a much higher clever-level to get around than display: none does in CSS.)

bump! nobody? :~(

why can’t we tag @team :wink:

I don’t have too much time to dive into it right now but this theme component may help you because it’ll list all of the current user’s groups in, I think, the body tag. Then you could probably use CSS selectors to show/hide based on whether certain group class names exist in the body tag.

And combine that with some info from this post on how which HTML elements you can use in the composer and how to wrap composer text in classes, and it may work:

Yup, just tested it here and it should work if you use that component combined with something like:

<span data-group-a>Text only for group A</span>
<span data-group-b>Text only for group B</span>

And then have css selectors that do something like:

span[data-group-a] {display: none;}
body.group-a span[data-group-a] {display: block;}

Or something like that…

Sorry for all the edits. Just tested it on one of my instances and it works.

But as you mentioned, maybe that’s not what you wanted :slight_smile:

This might be possible with a theme javascript, adding something in the <head> section to select the elements and remove it. Still may require the span and wrapping as above, but remove it through that.

2 Likes

Ok I realized I may need this as well so I dove more deeply into it :slight_smile:

This code doesn’t yet work and is not that pretty, but I think it’s almost good enough to go in the </head> part of the theme, just needs to have the right way to select the elements using JS:

<script type="text/discourse-plugin" version="0.8.42">

  api.decorateCookedElement(
    element => {
      var hasGroupA = document.body.classList.contains('group-a');

      const group_a_spans = element.querySelectorAll("span[data-group-a]");

      if (!group_a_spans.length) {
        return;
      }

      if (!hasGroupA) {
        group_a_spans.forEach(function (el) {
           el.innerHTML = "";
        });
      }

      },
      { id: "THEME-ID", onlyStream: true }
   );
</script>

CAVEAT: I think it may be hard to hide all the info from search and things like that, so while this may be better than just hiding it via CSS, I don’t think it’ll completely prevent people from seeing the info.

EDIT: Fixed it so the CSS selectors should work. Repeat the code for as many groups as you want to use. Change THEME-ID to a unique name. I think this should work :slight_smile:

Oops, didn’t get this part yet:

3 Likes

I really appreciate your efforts on this… I’m still thinking about this and I think you’ve started me on a workable solution. I’ve a template component I wrote, which makes me think I could make something like this work…

Supposing I imagine a component “foobar”. I could write a topic, adding some DIVs like this…

<div data-custom="foobar" data-foobar="<groupname>">
</div>
<div data-custom="foobar" data-foobar="!<groupname>">
</div>

The component then deletes from the DOM, one DIV or the other, based on the viewing user’s group.

This strikes me as stronger than a CSS display: none; which is trivial to flip back on via any web browser’s DOM inspection features. To get around this, someone would have to alter the j/s that is running when the page loads—possible, but much harder.

why do I want this?

So I can do a partial reveal of content for people who are NOT in the group. (Because getting into the group requires a paying subscription.)

This is a really cool topic. This first
paragraph is really interesting.

<div data-custom="foobar" data-foobar="<groupname>">
Here's the rest of the content.
</div>

<div data-custom="foobar" data-foobar="!<groupname>">
Hi, sorry to interrupt!
There's more conent here for our paying members...
would you like to read about becoming one?
</div>

People in the group simply see the entire topic. There’s no sign of any paywalling.

People not in the group see the initial portion, not in either DIV above, and a paywall.

So I can use this in a completely public area so people can see what they get if they signup, login and become a paying member.

Finally got around to knocking this together as, https://github.com/Umbrella-CAST/discourse-umbrella-groupswitchdisplay Super simple, just removes the targeted DIV from the DOM based on is the current user in a group name “foobar” or not in the group via “!foobar”. That lets me have a simple toggle display of content like the below image.

Of course, if the component is disabled, then all of the content shows (since sans component the DOM doesn’t get trimmed down.) But this is good enough for what I want to do.

2 Likes

You solved out one of mine very similar headache.

1 Like

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