Categoria che carica argomenti casuali

Ho provato a cercarlo su Google, ma non ho trovato nulla a riguardo.
Penso che alcuni argomenti possano essere molto preziosi, ma gli utenti tendono a concentrarsi maggiormente su quelli più recenti (a meno che non arrivino a un forum da una ricerca su Google, ad esempio).

È possibile, magari tramite un componente/plugin, avere una categoria o qualcosa del genere, dove carica automaticamente argomenti casuali? Questo ridarebbe vita ad alcuni vecchi post che magari 3 anni fa non avevano molto coinvolgimento, ma erano comunque preziosi, e magari ora con più utenti potrebbero avere l’attenzione che meritano.

Per essere chiari, non voglio che gli argomenti casuali siano limitati a una singola categoria, anche se anche questo potrebbe essere positivo. Stavo pensando più a una funzionalità globale in cui qualsiasi argomento da qualsiasi categoria potrebbe essere caricato in quella sezione. fondamentalmente nello stesso modo in cui quando vado alla home page di https://meta.discourse.org/ posso vedere un elenco di tutti gli argomenti più recenti, indipendentemente dalla categoria, ma nel mio caso, caricherebbe argomenti casuali anche da qualsiasi categoria, ma non focalizzati sulla data degli argomenti o anche sulle ultime risposte.

Spero abbia senso…

2 Mi Piace

Mi piace l’idea degli argomenti casuali, ma suppongo che ci debbano essere delle modifiche da apportare.
Il mio forum ha più di 20 anni e sarebbe strano avere una pagina con un sacco di argomenti casuali più vecchi di un decennio.

Se vuoi puntare ad argomenti con basso coinvolgimento, dovrebbe esserci un parametro come il numero massimo di risposte da mostrare.

Anche così, non significa che tutti questi argomenti a basso coinvolgimento siano interessanti.

Vuoi puntare ad argomenti secondo alcuni criteri, o solo… casuali?

La cosa più vicina che esiste si trova nelle impostazioni della categoria:

È stato (forse lo è ancora?) utilizzato qui su Support, poiché lo stato ideale degli argomenti di Support è risolto/chiuso. Gli argomenti aperti qui tipicamente significano che non è stata fornita una soluzione, quindi dà una possibilità agli argomenti a basso coinvolgimento di essere esaminati, anche se sono passati mesi o anni - può sempre essere prezioso.

1 Mi Piace

Casuali.

Potrebbe essere una categoria specifica, ad esempio, o anche un pulsante per la casualità.
O forse solo una sezione in fondo agli ultimi post che caricherebbe 3 o 4 vecchi post casuali?

Anche i post del tuo forum di oltre 20 anni possono essere rilevanti oggi, ma forse quando sono stati creati, nessuno ci ha prestato molta attenzione e potrebbero ricevere un po’ di “amore” ora :wink:

2 Mi Piace

Oggi ho deciso di chiedere aiuto a Claude per questo.
Ecco cosa abbiamo ideato, dopo molti test e correzioni (carica solo gli argomenti APERTI, il che ha più senso per me):

Quando si fa clic su “Load more random topics” (Carica altri argomenti casuali), vengono caricati altri 5 argomenti sotto quelli attuali. Cliccando di nuovo sul pulsante, ne vengono aggiunti altri 5, finché non ci sono più argomenti:

Per caricare gli argomenti casuali, basta visitare:
yourwebsite.com/?random


Ecco come implementarlo:

1 - Crea un componente
2 - Aggiungi questo alla scheda JS:

import { apiInitializer } from "discourse/lib/api";
// Nasconde il contenuto immediatamente se ?random è nell'URL
if (new URLSearchParams(window.location.search).has('random')) {
  const style = document.createElement('style');
  style.textContent = '#main-outlet { display: none; }';
  document.head.appendChild(style);
}

let loadedTopicIds = new Set();

function addRandomTopics(listDiv, button) {
  // Nasconde il pulsante e mostra il caricamento
  button.style.display = 'none';
  const loadingDiv = document.createElement('div');
  loadingDiv.className = 'loading-more';
  loadingDiv.textContent = 'Loading...';
  listDiv.appendChild(loadingDiv);
  
  const query = `status:open`;
  
  fetch(`/search.json?q=${encodeURIComponent(query)}`)
    .then((response) => response.json())
    .then((data) => {
      loadingDiv.remove();
      
      if (!data || !data.topics || data.topics.length === 0) {
        button.remove();
        const noMoreDiv = document.createElement('div');
        noMoreDiv.className = 'no-more-topics';
        noMoreDiv.textContent = 'No more topics to load';
        listDiv.appendChild(noMoreDiv);
        return;
      }
      
      // Filtra gli argomenti già caricati
      const unloadedTopics = data.topics.filter(topic => !loadedTopicIds.has(topic.id));
      
      if (unloadedTopics.length === 0) {
        button.remove();
        const noMoreDiv = document.createElement('div');
        noMoreDiv.className = 'no-more-topics';
        noMoreDiv.textContent = 'No more topics to load';
        listDiv.appendChild(noMoreDiv);
        return;
      }
      
      // Mescola e seleziona fino a 5 argomenti casuali
      const shuffled = unloadedTopics.sort(() => 0.5 - Math.random());
      const selected = shuffled.slice(0, Math.min(5, unloadedTopics.length));
      
      // Ottieni la categoria dai dati del sito Discourse
      const site = Discourse.__container__.lookup('site:main');
      
      selected.forEach(topic => {
        loadedTopicIds.add(topic.id);
        
        const date = new Date(topic.created_at);
        const formattedDate = date.toLocaleDateString('en-US', { 
          year: 'numeric', 
          month: 'short', 
          day: 'numeric' 
        });
        
        const itemDiv = document.createElement('div');
        itemDiv.className = 'random-topic-item';
        
        const linkDiv = document.createElement('div');
        linkDiv.className = 'random-topic-link';
        
        const link = document.createElement('a');
        link.href = `/t/${topic.slug}/${topic.id}`;
        link.textContent = topic.unicode_title || topic.title;
        
        linkDiv.appendChild(link);
        
        const metaDiv = document.createElement('div');
        metaDiv.className = 'random-topic-meta';
        
        const category = site.categories.find(cat => cat.id === topic.category_id);
        const categoryName = category?.name || 'Uncategorized';
        
        metaDiv.textContent = `${categoryName} • ${formattedDate}`;
        
        itemDiv.appendChild(linkDiv);
        itemDiv.appendChild(metaDiv);
        
        // Inserisci prima del pulsante
        listDiv.insertBefore(itemDiv, button);
      });
      
      // Controlla se abbiamo caricato tutti gli argomenti disponibili
      if (selected.length < 5 || loadedTopicIds.size >= data.topics.length) {
        button.remove();
        const noMoreDiv = document.createElement('div');
        noMoreDiv.className = 'no-more-topics';
        noMoreDiv.textContent = 'No more topics to load';
        listDiv.appendChild(noMoreDiv);
      } else {
        button.style.display = 'block';
      }
    })
    .catch((err) => {
      console.error("Fetch error:", err);
      loadingDiv.remove();
      button.style.display = 'block';
    });
}

function loadRandomTopics(container) {
  // Resetta gli argomenti caricati
  loadedTopicIds = new Set();
  
  container.innerHTML = '<div class="spinner"></div>';
  
  const query = `status:open`;
  
  fetch(`/search.json?q=${encodeURIComponent(query)}`)
    .then((response) => response.json())
    .then((data) => {
      if (!data || !data.topics || data.topics.length === 0) {
        container.innerHTML = '<p>No topics found</p>';
        return;
      }
      
      // Mescola e seleziona 5 argomenti casuali
      const shuffled = data.topics.sort(() => 0.5 - Math.random());
      const selected = shuffled.slice(0, 5);
      
      // Costruisci l'HTML
      const listDiv = document.createElement('div');
      listDiv.className = 'random-topics-list';
      
      const heading = document.createElement('h2');
      heading.textContent = 'Random Open Topics';
      listDiv.appendChild(heading);
      
      // Ottieni la categoria dai dati del sito Discourse
      const site = Discourse.__container__.lookup('site:main');
      
      selected.forEach(topic => {
        loadedTopicIds.add(topic.id);
        
        const date = new Date(topic.created_at);
        const formattedDate = date.toLocaleDateString('en-US', { 
          year: 'numeric', 
          month: 'short', 
          day: 'numeric' 
        });
        
        const itemDiv = document.createElement('div');
        itemDiv.className = 'random-topic-item';
        
        const linkDiv = document.createElement('div');
        linkDiv.className = 'random-topic-link';
        
        const link = document.createElement('a');
        link.href = `/t/${topic.slug}/${topic.id}`;
        link.textContent = topic.unicode_title || topic.title;
        
        linkDiv.appendChild(link);
        
        const metaDiv = document.createElement('div');
        metaDiv.className = 'random-topic-meta';
        
        const category = site.categories.find(cat => cat.id === topic.category_id);
        const categoryName = category?.name || 'Uncategorized';
        
        metaDiv.textContent = `${categoryName} • ${formattedDate}`;
        
        itemDiv.appendChild(linkDiv);
        itemDiv.appendChild(metaDiv);
        listDiv.appendChild(itemDiv);
      });
      
      const button = document.createElement('button');
      button.className = 'btn btn-primary load-more-random';
      button.textContent = 'Load more random topics';
      button.addEventListener('click', () => {
        addRandomTopics(listDiv, button);
      });
      
      listDiv.appendChild(button);
      container.innerHTML = '';
      container.appendChild(listDiv);
    })
    .catch((err) => {
      console.error("Fetch error:", err);
      container.innerHTML = '<p>Error loading topics</p>';
    });
}

export default apiInitializer("1.8.0", (api) => {
  let wasOnRandomPage = new URLSearchParams(window.location.search).has('random');
  
  api.onPageChange(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const isOnRandomPage = urlParams.has('random');
    
    // Se eravamo sulla pagina random ma ora non lo siamo più, forza il ricaricamento
    if (wasOnRandomPage && !isOnRandomPage) {
      window.location.reload();
      return;
    }
    
    wasOnRandomPage = isOnRandomPage;
    
    if (!isOnRandomPage) {
      return;
    }
    
    // Mostra e sostituisci il contenuto
    const mainContent = document.querySelector('#main-outlet');
    if (mainContent) {
      mainContent.style.display = 'block';
      mainContent.innerHTML = '<div id="random-topics-container"></div>';
      
      const container = document.querySelector('#random-topics-container');
      loadRandomTopics(container);
    }
  });
});

3 - Aggiungi questo alla scheda CSS:

.random-topics-list {
  max-width: 800px;
  margin: 40px auto;
  padding: 20px;
}

.random-topics-list h2 {
  margin-bottom: 30px;
  font-size: 2em;
}

.random-topic-item {
  margin-bottom: 25px;
}

.random-topic-link a {
  color: #E9E9E9;
  text-decoration: underline;
  font-size: 1.1em;
}

.random-topic-link a:hover {
  color: #229ED7;
}

.random-topic-meta {
  color: #808080;
  font-size: 0.85em;
  margin-top: 4px;
}

.load-more-random {
  margin-top: 30px;
}

.loading-more {
  text-align: center;
  margin-top: 20px;
  color: #808080;
}

.no-more-topics {
  text-align: center;
  margin-top: 30px;
  color: #808080;
  font-style: italic;
}

.spinner {
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 1s linear infinite;
  margin: 100px auto;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

Se qualcuno sa come usare la normale visualizzazione di Discourse invece di usare una pagina personalizzata HTML, sarebbe fantastico! Sono soddisfatto della funzionalità in sé, ma avere il layout predefinito sarebbe meglio, se qualcuno può condividere come fare?