Ottieni l'ID del topic quando viene caricata la pagina di visualizzazione del topic

Nel mio tema, quando viene caricata la pagina di visualizzazione di un argomento, devo ottenere l’ID di quell’argomento (e anche il nome, se possibile, ma l’ID sarebbe sufficiente).

Successivamente, uso queste informazioni nel mio tema per effettuare una chiamata API e ottenere informazioni sull’argomento (con una chiamata a un endpoint come forum-name/t/topic-name/id.json…)

Come posso ottenere l’ID dell’argomento quando viene caricata la pagina di visualizzazione?

I metodi ovvi non sono sufficienti

La soluzione ovvia è utilizzare window.location.href o window.location.pathname per ottenere le informazioni dall’URL. Il problema è che l’URL della pagina di visualizzazione dell’argomento può assumere forme diverse. Spesso sarebbe:
forum-name/t/topic-name/topic-id

Se fosse sempre in questa forma, allora l’uso di window.location.pathname funzionerebbe bene, restituendomi “t/topic-name/topic-id”.

MA, a volte l’URL della pagina di visualizzazione dell’argomento aggiunge anche l’ordine della categoria dell’argomento, quindi l’URL diventa: forum-name/t/topic-name/topic-id/category-index

Quindi, l’uso di window.location.pathname non è sufficiente, perché non so programmaticamente se l’ultimo parametro sarà l’ID dell’argomento o l’indice della categoria.

Potrebbe esserci un modo per risolvere questo problema utilizzando le espressioni regolari, ma ciò richiede una notevole competenza nelle regex. Potrebbe anche esserci un modo per risolverlo con jQuery esaminando gli elementi nella pagina che potrebbero fornire l’ID, ma non sono ancora riuscito a farlo funzionare.

Quando/dove succede questo? Non sono riuscito a trovarlo.

Comunque, quando questo argomento viene caricato, presenta un elemento link:

<link rel="canonical" href="https://meta.discourse.org/t/get-topic-id-when-the-topic-show-page-loads/155620" />

Forse puoi recuperarlo da lì. :slight_smile:

Nel mio forum succede effettivamente la maggior parte delle volte quando si clicca su un argomento. L’ultima parte dell’URL sarà il numero dell’argomento nella categoria, se si è cliccato sull’argomento partendo dalla categoria. Forse è un’impostazione in Discourse? Non sembra succedere su meta-, ma non credo ci sia nulla di particolare che io stia facendo per causarlo nel mio forum.

Non posso però fare sempre affidamento su questo, perché se un argomento è il primo nella categoria, non viene aggiunto l’indice della categoria. Quindi, per quanto riesco a vedere, al momento non c’è un buon modo per capire se apparirà nell’indice della categoria o meno.

Ottenere l’ID da un div va bene, ma sfortunatamente è molto più lento rispetto al poterlo ottenere direttamente dall’URL o con qualche altro mezzo diretto. Nel caso non ci sia un’altra soluzione, sai qual è il comando jQuery per ottenere il valore di quell’Href?

Prova

api.onPageChange((url, title) => {
    var res = url.match(/\/t\/(.*?)\/(\w+)/);
    if (res && res[2] > 0) {
        console.log(res[2]);
    }
});
2 Mi Piace

Cosa stai cercando di ottenere?

Questo potrebbe funzionare, ma non è molto efficiente, poiché stai eseguendo un’ulteriore richiesta AJAX per ogni visualizzazione della pagina del topic da parte di ogni utente, inclusi gli anonimi. Questo creerà un carico inutile sul tuo server.

Non esattamente. L’URL di un topic ha questo aspetto

your.site.com/t/topic_title/topic_id/linked_post_number(opzionale)

In un’installazione predefinita di Discourse, non c’è l’ordine della categoria nell’URL.

Possiamo aiutarti se descrivi il problema che stai cercando di risolvere invece di descrivere le tue soluzioni per esso.

3 Mi Piace

Funziona! Grazie mille. Capisco che con il metodo match qui stai analizzando l’URL per ottenere, presumo, la terza occorrenza di “/”, dato che l’ID appare sempre dopo la terza “/” nell’URL, che ha il formato “/t/nome/id/altro”. Potresti fornirmi qualche informazione su come la tua espressione regolare fa questo? Sarebbe molto utile nel mio percorso di apprendimento delle regex.

Grazie per le informazioni. Quindi è il “numero_post_collegato” che appare a volte e compromette la mia chiamata API. Qui lo definisci “opzionale”—c’è un modo per essere sicuri che non venga mai mostrato?

Quando un utente visita la pagina di visualizzazione dell’argomento, voglio:

  1. Sapere programmaticamente tutti i tag associati a quell’argomento. Nota che alcuni tag sono nascosti dalla vista dell’utente.
  2. Avere un pulsante sulla pagina dell’argomento che aggiunge un certo tag nascosto all’argomento quando viene cliccato (se il tag nascosto non è già presente), e rimuove il tag nascosto quando viene cliccato (se il tag nascosto è già presente).

Tutto questo è semplice da realizzare utilizzando l’API di amministrazione e javascript/jquery (supponendo di poter ottenere l’URL corretto dell’argomento da utilizzare nelle chiamate API).

Credo che l’unico altro modo per fare questo tipo di cose sarebbe creare un plugin in cui dovrei addentrarmi profondamente in: 1. Ember, 2. Rails e 3. il codice sorgente di Discourse. Ho esaminato i post chiave e la documentazione di Discourse su come farlo, ma ho trovato il processo piuttosto lento perché è necessario comprendere bene questi tre elementi. Quindi per ora mi sono concentrato sull’approccio basato sull’API.

Sarei interessato a sapere se esiste un altro modo per fare questo che riduca il carico sul server.

Avrei senz’altro potuto aiutarti con il codice se si fosse trattato di una soluzione in un solo passaggio, ma sono coinvolti più passaggi. Se hai bisogno di aiuto sotto forma di consulenza per portare a termine il lavoro o per imparare a scrivere tu stesso i componenti del tema, pubblica sul marketplace e ti contatterò.

Grazie, ma è utile ricevere indicazioni su ogni passaggio. Ad esempio, oltre all’uso dell’API, come posso conoscere tutti i tag associati a un argomento?

1 Mi Piace

Un oggetto topic completo viene caricato lato client quando carichi la pagina del topic. Ora, se vuoi utilizzarlo, devi aggiungere il tuo codice al template per usare quei dati, oppure riaprire le classi per sfruttare i dati caricati (cioè, essenzialmente creare le tue computed props e utilizzarle nel template). Contiene la maggior parte dei dati di cui hai bisogno (probabilmente più di quelli necessari) già caricati lato client senza chiamate API aggiuntive. Hai inoltre bisogno di plugin-outlet per inserire il tuo markup nei template esistenti.

Sarebbe utile se esaminassi il codice o i metadati per i termini che ho usato sopra. Sarò felice di aiutarti qui se ti blocchi, entro i limiti del mio tempo disponibile. Saluti.

Grazie. Conosco già alcune delle basi che menzioni, ma c’è un punto che mi blocca (e scommetto che questo tipo di cosa blocca molte persone):

Nella pagina di visualizzazione dell’argomento, viene caricato il template /templates/components/topic-category.hbs. È questo che mostra la categoria e anche il tag sotto il titolo dell’argomento.

In topic-category, viene elencato topic.tags. Quindi questa è la parte chiave di informazioni di cui ho bisogno per far funzionare tutto.

Ecco dove mi trovo bloccato: Come posso ottenere quelle informazioni topic.tags nel mio JavaScript?

Ad esempio, se volessi semplicemente eseguire console.log sul contenuto di topic.tags, come farei?


So come sovrascrivere i template. Ad esempio, in un tema, potrei creare un file in discourse/templates/components/topic-category.hbs e riscrivere il template lì, apportando le modifiche che volevo alla visualizzazione. (Sto usando la struttura di file separata descritta qui).

Nel mio tema, so anche come inserire JavaScript in theme/initializers/initializer-file.js.es6.

E posso far interagire i due con un po’ di jQuery. Ad esempio, potrei inserire topic.tags in un div nel template e accedervi nel mio inizializzatore con jQuery, ottenendo il contenuto di quel div.

Ma è una soluzione indiretta. Come posso ottenere direttamente le informazioni topic.tags in modo da poterle analizzare e manipolare?

1 Mi Piace

Farei console.log dell’intero topic per individuare la chiave necessaria. Le interazioni con jQuery devono essere eseguite all’interno dei componenti e dovrebbero esserlo. didInsertElement è il hook del componente utile in questo caso.

A quanto pare, hai bisogno di una proprietà calcolata che dipenda da topic.tags e restituisca la tua manipolazione nel controller o nel componente interessato. È utilizzabile direttamente nel template. Inoltre, non arrenderti con queste cose. Ci vorrà del tempo, ma ripagherà in modi migliori di quanto potresti immaginare.

Cosa intendi per “all’interno dei componenti”—in quale file devo inserire il codice jQuery? (Nel mio tema, posso usare jQuery nel file tema/inizializzatori/file-inizializzatore.js.es6, ma questo non sembra essere “all’interno” del componente)

In quale file va inserito il codice di didInsertElement?

1 Mi Piace

A questo punto dovresti davvero consultare le guide di Ember. Un componente è un pacchetto di funzionalità che puoi distribuire e collegare ad altre cose.

2 Mi Piace

Grazie, ragazzi, queste sono tutte informazioni utili. Sto esaminando le guide e la documentazione generale. Sarebbe anche molto utile sapere il nome del file in cui inserire il codice (i) jQuery e (ii) didInsertElement. Avere questo tipo di informazioni concrete sarà di grande aiuto per guidare ulteriori revisioni.

1 Mi Piace

I componenti = componenti Ember.

Puoi reopen (riaprire) tutte le classi Ember e iniettare il tuo codice al loro interno. Dovrai cercare plugin o temi che lo fanno per avere un’idea migliore.

@JQ331 Come probabilmente sai, ho trovato delle espressioni regolari su Google e le ho provate qui! Puoi inserire delle varianti per ottenere i migliori risultati.

1 Mi Piace

A mio avviso, questo rientra nel campo dei plugin.

Se i tag sono nascosti all’utente normale, come potrebbe aiutare una chiamata aggiuntiva? In ogni caso, il serializzatore dovrebbe nascondere quei tag all’utente normale. Se non lo fa, allora stai esponendo una falla nella sicurezza dei contenuti.

Se stai affrontando tutte queste complicazioni per aggirare le limitazioni delle modifiche solo lato front-end, ti suggerirei di fare un passo avanti e valutare la creazione di un plugin, in modo da poter serializzare tutto in un’unica operazione, evitando invece una configurazione disordinata con chiamate aggiuntive.

1 Mi Piace

Ha senso. Vorrei saperne di più sull’uso del serializzatore: sebbene il serializzatore sia uno dei passaggi più importanti in un plugin di Discourse, non ho ancora trovato documentazione che illustri alcuni esempi di base del suo utilizzo. Conosci questa documentazione?

Quando dici che un serializzatore dovrebbe nascondere quei tag, potresti fornire del pseudocodice per chiarire il concetto? (va bene anche se non funziona perfettamente: sto solo cercando di capire il concetto)

Ecco:

È come la musica jazz… le migliori pratiche sono solitamente già disponibili nell’ampio panorama dei plugin open source esistenti, proprio come tutti i dischi. Non aspettarti una guida perfetta su come fare tutto; spesso devi metterti in gioco (ehm) imparando dal lavoro precedente.

Trova un plugin da #plugin che faccia qualcosa di funzionalmente simile, o una parte di ciò che vuoi realizzare, e ispeziona il codice per vedere come ottiene i risultati. Lo stesso vale per il codice sorgente di Discourse, che puoi utilizzare come fonte di “best practice” definitive, specialmente per quanto riguarda Discourse.

Clona un plugin esistente in locale e prova a modificare alcune cose, fai esperimenti.

I serializzatori si limitano a filtrare ciò che viene inviato dai Controller/Modelli e possono anche eseguire alcune manipolazioni di base.

1 Mi Piace

Ecco un esempio dalla sorgente: discourse/app/serializers/concerns/topic_tags_mixin.rb at 888e68a1637ca784a7bf51a6bbb524dcf7413b13 · discourse/discourse · GitHub

  def tags
    # Chiamare il metodo `pluck` insieme a `includes` causa query N+1
    tags = topic.tags.map(&:name)

    if scope.is_staff?
      tags
    else
      tags - scope.hidden_tag_names
    end
  end

Come puoi vedere, qui vengono esclusi i tag nascosti per gli utenti non staff.

2 Mi Piace