Arranging Categories in order of number of Topics

AI-generated summary

Tris20 proposed automatically sorting categories on the main page by number of topics, suggesting a hysteresis mechanism to reduce frequent reordering. Arkshine offered to create a free theme component to implement this feature, targeting only the /categories page for compatibility. The script dynamically sorts categories based on topic counts, supporting different desktop category page styles (e.g., ‘categories’ or ‘subcategories_with_featured_topics’), though it doesn’t work with ‘boxes’ style due to lack of visible counts. Tris20 appreciated the offer but noted it wasn’t a priority for their team to purchase, while still seeing value in integrating such a feature into Discourse core as a middle ground between fixed order and overly dynamic sorting. Arkshine clarified the component is free and provided the JavaScript code for installation via a theme component, inviting feedback on its functionality.

I’m wondering if it’s ever been on radar to also sort the order of the categories on the main page in order of number of topics?

Example

Category A has 100 topics
Category B has 50 topics
Category C has 20 topics.

Order on main page would be ABC. If C suddenly changes to 120 topics, order would be CAB.

Would it be reasonably achievable? Would a Hysteresis even be possible such that the Categories don’t move around too often?

1 Like

Hi,

I can make a small component if you are interested. To be sure, you are talking about the categories page (/categories), right?

That’s a kind offer. However from our side this isn’t necessary enough to purchase as a theme component. I think it would still be a nice feature to have in Discourse generally. I feel like it would be a nice balance between the existing order by latest(which changes the order too often) and a completely fixed layout.

1 Like

No, no, for free :slight_smile:.

EDIT:

You can install this script in a theme component.

It arranges the items of the categories list only on the page itself.
This doesn’t affect any template or internal to keep better compatibility.
Depending on your theme, it might require adjustments.

Let me know if it works for you.

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

api.onPageChange((url, title) => {
    const { defaultHomepage } = require('discourse/lib/utilities');

    if (url !== '/categories' && (url !== '/' || defaultHomepage() !== 'categories')) {
        return;
    }
    
    const desktop_category_page_style = api.container.lookup('service:site-settings').desktop_category_page_style;
    
    const sort = ({parent, nodes, selector}) => {
        if (!parent || !nodes.length) {
            return
        }

        Array.from(nodes).sort((a, b) => {
            const valueA = a.querySelector(selector).textContent;
            const valueB = b.querySelector(selector).textContent;
            
            return valueB - valueA;
            
        })
        .forEach(row => parent.appendChild(row));
    }
    
    if (desktop_category_page_style.startsWith('categories')) {
        const parent = document.querySelector('.category-list tbody[aria-labelledby="categories-only-category"]');
        
        sort({
            parent: parent, 
            nodes: parent?.querySelectorAll('tr'), 
            selector: 'td.topics span.value'
        })
    }
    else if (desktop_category_page_style === 'subcategories_with_featured_topics') {
        const childs = document.querySelectorAll('table.category-list');
        
        sort({
            parent: childs[0]?.parentElement, 
            nodes: childs, 
            selector: 'th.parent-category span.value'
        })

    } else {
        // boxes doesn't have a count displayed
    }
});
</script>
1 Like