Se vuoi aggiungere contenuto a una pagina specifica, la tua migliore opzione è un plugin-outlet. In poche parole, i plugin-outlet sono spazi riservati nei template di Discourse che puoi utilizzare per aggiungere nuovo contenuto.
La prima cosa da fare è verificare se esiste un plugin-outlet sulla pagina che vuoi targettare. Esiste un componente tema che puoi installare per aiutarti in questo.
(deprecated) Plugin outlet locations theme component
Una volta installato quel componente, attivalo, vai sulla pagina che vuoi targettare e controlla cosa hai a disposizione. Nel tuo caso, un tale plugin-outlet esiste (evidenziato in verde)
Quindi, quello che ci interessa è above-user-profile
Supponiamo che non esistesse… e allora? In tal caso, la migliore opzione è chiedere che venga aggiunto o inviare una PR per inserirlo nel core. Nella maggior parte dei casi verrà accettato se il tuo caso d’uso ha senso.
Comunque, come ho detto, in questo caso esiste già. Quindi, vediamo come puoi aggiungere markup ad esso. Per il resto di questa guida non avrai più bisogno del componente sopra, quindi puoi disattivarlo ora che hai già il nome del plugin outlet.
Tutto quello che devi fare è aggiungere qualcosa di simile nella scheda header del tuo tema.
<script type="text/x-handlebars" data-template-name="/connectors/NOME_OUTLET/NOME_QUALSIA">
Il tuo markup va qui...
</script>
Devi cambiare NOME_OUTLET con il nome dell’outlet che vuoi targettare. Poi cambia NOME_QUALSIA con il nome che vuoi dare a questa personalizzazione. Il nome può essere qualsiasi cosa, ma cerca di essere descrittivo se possibile. È una buona pratica. Quindi, arriviamo a questo.
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
Il tuo markup va qui... come
<h1>Ciao Mondo!!</h1>
</script>
Proviamo e vediamo cosa succede… ricorda, il frammento sopra va nella scheda common > header del tuo tema.
e…
Fin qui tutto bene, ma approfondiamo.
Non vuoi che i tuoi video appaiano su ogni profilo, ma solo in base a una certa condizione. Quindi, come si fa? Beh, avrai bisogno di due cose: alcuni dati da consumare e un po’ di Javascript.
Troviamo i dati. Ricordi quando ho detto che i plugin-outlet sono spazi riservati? Beh, qual è lo scopo di averli senza contesto? Ecco perché Discourse passa i bit rilevanti di contesto a ogni plugin outlet… ma prima, facciamo un passo indietro. Quando aggiungi questo
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
Il tuo markup va qui, come...
<h1>Ciao Mondo!!</h1>
</script>
Sembra HTML - e i tag script lo sono - ma ciò che c’è al loro interno viene trattato come codice handlebars.
Ciò significa che puoi fare qualcosa di simile invece
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
{{log this}}
</script>
e controllare la console del browser. Vedrai questo ogni volta che l’outlet viene renderizzato; cioè, quando sei su una pagina utente.
Ora, è utile tutto questo? Sì… ma non al momento. Torneremo su questo. Facciamo un altro passo indietro e vediamo come Discourse passa il contesto all’outlet. Se cerchi il nome dell’outlet su Github - o localmente - otterrai questo.
Repository search results · GitHub
Apriamo quel file. La prima cosa che vedi è questa riga
Guarda l’ultima parte di quella riga
args=(hash model=model)
Vedrai che Discourse passa model come argomento all’outlet. Per tutti gli scopi pratici e per mantenere le cose semplici, model = data.
Quindi, uno degli argomenti per il nostro outlet è model, ed è lì che si troveranno i dati che vogliamo. Quindi, torniamo al nostro frammento.
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
{{log this}}
</script>
e cambiamolo in questo
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
- {{log this}}
+ {{log args}}
</script>
Ora otteniamo questo nella console.
Puoi navigare in quei dati e vedere se contengono ciò di cui hai bisogno. Dovrebbe essere così, dato che contiene tutti i dati sull’utente utilizzati in altri elementi di quella pagina. È il “model” per la pagina utente di quell’utente specifico.
Una delle proprietà disponibili lì è… tamburo
… i gruppi a cui l’utente appartiene.
Quindi, se fai
{{log args.model.groups}}
otterrai tutti i gruppi a cui l’utente appartiene nella console.
Bene, ora abbiamo i dati di cui abbiamo bisogno, quindi l’unica cosa che resta è aggiungere una o più condizioni basate su di essi.
Potresti essere tentato di pensare che possiamo farlo nello stesso frammento, ma, purtroppo, non possiamo. Handlebars è un linguaggio di templating. Ha un supporto molto, molto basilare per la logica - niente oltre a semplici condizioni vero/falso e cicli. Non puoi fare confronti e altre cose del genere.
Quindi dove esattamente puoi farlo? In una classe connector, suona sofisticato… lo so.
In poche parole, una classe connector è essenzialmente un pezzetto di Javascript attaccato all’outlet. È molto più sfumato di così, ma è tutto quello che devi sapere per ora.
Quindi, creiamone una. Lo facciamo così
<script type="text/discourse-plugin" version="0.8">
api.registerConnectorClass('NOME_OUTLET', 'NOME_QUALSIA', {
});
</script>
NOME_OUTLET e NOME_QUALSIA qui devono essere gli stessi che abbiamo usato sopra. Quindi cambiamoli
<script type="text/discourse-plugin" version="0.8">
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
});
</script>
Questo frammento va anche nella scheda common > header del tuo tema. Quindi ora dovresti avere qualcosa che assomiglia a questo
<script type="text/x-handlebars" data-template-name="/connectors/above-user-profile/add-profile-videos">
{{log args.model.groups}}
</script>
<script type="text/discourse-plugin" version="0.8">
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
});
</script>
All’interno della nostra classe connector possiamo fare del lavoro… ma… dobbiamo essere consapevoli che non è come un qualsiasi file javaScript. Per mancanza di una descrizione migliore… pensala come un componente Ember a dieta. Espandere questo è un po’ al di fuori dello scopo qui, quindi procediamo.
Ci sono quattro metodi collegati ad essa di default
actions ti permette di definire azioni così
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
actions: {
myAction() {
// fai qualcosa
}
}
});
Puoi quindi chiamare quell’azione dall’interno dell’outlet, ad esempio quando viene premuto un pulsante. Non ne avremo bisogno qui, quindi procediamo.
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
shouldRender(args, component) {
// restituisci true o false qui
}
});
Non useremo nemmeno questo poiché l’outlet viene renderizzato solo sulle pagine dei profili e al momento non abbiamo altri requisiti. Tuttavia, puoi usarlo per aggiungere qualsiasi condizione desideri testare prima che l’outlet venga renderizzato. Ad esempio, il livello di fiducia dell’utente corrente o cose del genere. Procediamo…
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
setupComponent(args, component) {
// fai qualcosa
}
});
Questa è quella su cui vogliamo concentrarci. Qualsiasi condizione javaScript o variabile che desideri impostare va qui. Prima di approfondire ulteriormente, copriamo l’ultimo metodo per completezza
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
teardownComponent(args, component) {
// fai qualcosa
}
});
questo si attiva quando l’outlet sta per essere rimosso. Quindi, ti permette di fare qualsiasi pulizia necessaria, come rimuovere gli ascoltatori di eventi e così via.
Ok, torniamo a setupComponent
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
setupComponent(args, component) {
// fai qualcosa
}
});
Puoi vedere che gli vengono passati due elementi. Prima c’è args e poi c’è component.
args qui è la stessa cosa che abbiamo esaminato prima. Sono i dati di contesto che Discourse ha passato all’outlet. Quindi, se fai
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
setupComponent(args, component) {
console.log(args.model.groups);
}
});
vedrai le stesse informazioni nella console del browser che abbiamo visto prima. I gruppi a cui appartiene il proprietario del profilo. Qui inizia il divertimento, ora hai i dati e hai il hook corretto. Quindi puoi fare tutto ciò che vuoi qui. Quindi, se voglio che il video appaia solo sui profili dei membri che appartengono a un certo gruppo, posso fare questo
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
setupComponent(args, component) {
const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
const showVideo = inGroup.length ? true : false;
console.log(showVideo);
}
});
Se provi questo su una pagina del profilo che appartiene a un utente nel gruppo staff, stamperà true nella console. Quindi, ora l’unica cosa che ci resta da fare è passare questo al template dell’outlet. Ecco come puoi farlo.
component passato a setupComponent qui è condiviso tra il connector e l’outlet. Puoi passare cose all’outlet impostandole come proprietà sul componente così
const TARGET_GROUP = "staff"
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
setupComponent(args, component) {
const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
const showVideo = inGroup.length ? true : false;
- console.log(showVideo);
+ component.setProperties({showVideo})
}
});
Ora, se torniamo al template e facciamo qualcosa come
{{log showVideo}}
stamperà lo stesso risultato. Quindi ora lo mettiamo in una condizione Handlebars e aggiungiamo il tuo markup all’interno così
<script
type="text/x-handlebars"
data-template-name="/connectors/above-user-profile/add-profile-videos"
>
{{#if showVideo}}
<video playsinline autoplay muted loop id="myVideo" poster="[INSERISCI LINK]">
<source src="[INSERISCI LINK]" type="video/webm">
<source src="[INSERISCI LINK]" type="video/mp4">
</video>
{{/if}}
</script>
poi controlla una pagina del profilo per un utente staff. Vedrai che carica il video.
Una volta che ti sposti dal profilo del membro dello staff, il video scomparirà. Il video non apparirà sui profili degli utenti che non sono nel gruppo staff.
Quindi, mettiamo tutto insieme. Questo è lo stesso contenuto di prima.
Ecco il CSS che ho usato. Scheda common > css
#myVideo {
position: fixed;
top: var(--header-offset);
min-height: 100vh;
left: 0;
z-index: -1;
}
.user-content {
background: none;
}
.user-main {
padding: 0.5em;
background: rgba(var(--secondary-rgb), 0.8);
}
// se vuoi che appaia anche su mobile
.mobile-view {
body[class*="user-"] {
background: none;
.user-main,
.user-content {
padding: 0.5em;
background: rgba(var(--secondary-rgb), 0.8);
}
}
}
HTML / javaScript / Handlebars. Questo va nella scheda common > header del tuo tema
<script
type="text/x-handlebars"
data-template-name="/connectors/above-user-profile/add-profile-videos"
>
{{#if showVideo}}
<video playsinline autoplay muted loop id="myVideo" poster="[INSERISCI LINK]">
<source src="[INSERISCI LINK]" type="video/webm">
<source src="[INSERISCI LINK]" type="video/mp4">
</video>
{{/if}}
</script>
<script type="text/discourse-plugin" version="0.8">
const TARGET_GROUP = "staff"
api.registerConnectorClass('above-user-profile', 'add-profile-videos', {
setupComponent(args, component) {
const inGroup = [...args.model.groups].filter(g => g.name === TARGET_GROUP)
const showVideo = inGroup.length ? true : false;
component.setProperties({showVideo})
}
});
</script>
Cambia TARGET_GROUP con il nome del gruppo che vuoi targettare e aggiungi gli attributi src per i tuoi video.
Questo post è stato un po’ lungo… non lasciarti scoraggiare da questo. Una volta compreso il concetto, tutto ciò che abbiamo fatto sopra può essere fatto in meno di 3-5 minuti.
La cosa bella qui è che tutto ciò di cui abbiamo parlato è praticamente lo stesso per qualsiasi plugin outlet. L’unica cosa che cambia è il nome. Quindi, questo si applica a qualsiasi modifica a plugin-outlet che vorrai fare in futuro.
- trova il nome dell’outlet
- ottieni i dati
- elabora i dati in un connector
- passa le proprietà indietro al template




