“New topic” button working incorrectly

AI-generated summary

Users reported that the “New topic” button on https://discussions.scouting.org/ behaves incorrectly: instead of immediately opening the topic form, it only appears after selecting an existing thread. The issue was traced to a custom CSS and JavaScript snippet that adds a closed-topic class to the body under certain conditions (logged-in, non-admin, trust level 4 users), even when no topic is loaded. This class hides reply controls, including the “New topic” button, due to overly broad CSS selectors. awesomerobot identified the root cause: the script applies closed-topic class unconditionally outside of topic contexts, which was likely intended to restrict replies on closed topics but mistakenly affects topic creation too. The fix involves wrapping the class addition inside an if (model) check. Calion confirmed this resolved their issue, and humorously speculated they may have triggered the original restriction by exploiting the bug to reply in closed topics.

When I hit the “New topic” button it does not immediately bring up the new topic form. Instead, the form is displayed after I select one of the threads in the forum. It still appears that it is creating a new topic, but in the background. Once you open any existing topic, the new topic you were trying to create appears (completely correct; i.e. for the forum you intended to post in, even if the topic you entered is in a different forum).

This is only happening on one site (https://discussions.scouting.org/), so I presume it’s something they have configured incorrectly. I’ve brought this issue up there, to no avail.

Does this occur in safe mode?

This is not reproducible in safe mode. There is a custom theme / css that is causing this issue.

The admins have added a CSS customization that looks like this:

body:not([class*="category-council-"]):not(.staff).closed-topic .reply, 
body:not([class*="category-council-"]):not(.staff).closed-topic #topic-footer-buttons .create, 
body:not([class*="category-council-"]):not(.staff).closed-topic .timeline-container .create, 
body:not([class*="category-council-"]):not(.staff).closed-topic #reply-control {
  display: none !important;
}

This appears to be ok at initial glance, but then I can see body.closed-topic is applied to the topic list… which really doesn’t make sense.

This class isn’t in Discourse by default, so tracking down another customization that adds that…

<script type="text/discourse-plugin" version="0.8">
const container = Discourse.__container__;
const controller = container.lookup("controller:topic");
const currentUser = api.getCurrentUser();

api.onPageChange(() => {

  if (!currentUser || currentUser.admin || currentUser.moderator || currentUser.trust_level != 4 ) {
    return;
  } else {
    let model = controller.get("model");
    
    document.querySelector("body").classList.add("closed-topic");
    
    if (model) {
      if (!model.closed) {
        document.querySelector("body").classList.remove("closed-topic");
      }
    }
  }

});
</script>

So here, if you’re logged in, not an admin, not a moderator, and are trust level 4… then it adds the closed-topic class to the page body.

This class is only removed if model.closed is false, which means… if it’s not a closed topic (or even if it’s not a topic at all) the closed-topic class will be applied.

This line:

document.querySelector("body").classList.add("closed-topic");

should probably be within if (model) because otherwise it’s applied even when there’s no model present (e.g., when you’re not within a topic)…

It seems the intention was to prevent trust level 4 users from replying to closed topics, but it’s applied too broadly.

Thanks much, this is what I was looking for.

Heheh I wonder if I’m the reason for that change. I discovered that bug and exploited it liberally. I never grasped the reason to require people to start a new thread when you’ve got additional information to add to an old one.