Ricarica/Aggiorna un widget al refresh di un altro widget

Ciao a tutti,

Abbiamo creato un widget “topic-timeline-bookmark” che visualizza il pulsante Segnaposto a livello di argomento dopo il widget topic-timeline.

Ora, ogni volta che facciamo clic sul pulsante Segnaposto topic-timeline, viene visualizzata una finestra modale per impostare il segnaposto. Quando salviamo il segnaposto, vengono aggiornati i pulsanti Segnaposto sotto i pulsanti first-post-menu e topic-footer-button, ma il pulsante del widget stesso non viene aggiornato finché il widget topic-timeline non viene ricaricato (cioè finché non scorriamo), e viceversa.

first-post-menu

image


topic-footer-button

image

Ho notato che ogni volta che un Segnaposto viene impostato o rimosso, il widget post-stream viene ricaricato, quindi i pulsanti Segnaposto di post-menu e topic-footer-button funzionano in sincronia.

Quindi, come posso ricaricare il mio widget “topic-timeline-bookmark” ogni volta che un Segnaposto viene impostato o rimosso, o ogni volta che il widget post-stream viene ricaricato? Di seguito il mio codice:

<script type="text/discourse-plugin" version="0.8">
  const { h } = require('virtual-dom');
  const { getOwner } = require("discourse-common/lib/get-owner");
  const topicController = getOwner(this).lookup("controller:topic");

  api.createWidget("topic-timeline-bookmark", {  
      tagName: 'div.discourse-bookmark-button-wrapper',
      buildKey: () => `topic-timeline-bookmark`,
      toggleBookmark() {
        topicController.send('toggleBookmark');
      },
      html(attrs, state) { 
        let contents = [];
        const user = api.getCurrentUser();
        if (user) {
            let tooltip = 'bookmarked.help.bookmark';
            let label = 'bookmarked.title';
            let buttonClass = 'btn btn-default bookmark';
            let icon = "bookmark";  
            let bookmarkedPosts = topicController.model.bookmarked_posts;
            let bookmarkCount = 0;

            if(bookmarkedPosts && bookmarkedPosts.length > 0){
              bookmarkCount =  bookmarkedPosts.length;
              
              //Icon
              if (bookmarkedPosts.some((bookmark) => bookmark.reminder_at))
                icon = "discourse-bookmark-clock";
              else
                icon = "bookmark";

              //Label
              if (bookmarkCount === 0)               
                  label = "bookmarked.title";          
              else if (bookmarkCount === 1)
                  label = "bookmarked.edit_bookmark"; 
              else 
                  label = "bookmarked.clear_bookmarks";

              //Tooltip
              if (bookmarkedPosts.length === 1)
                  tooltip = 'bookmarked.help.edit_bookmark';
              else if (bookmarkedPosts.find((x) => x.reminder_at))
                  tooltip = 'bookmarked.help.unbookmark_with_reminder';
              
              //Append CSS class if bookmark is set
              if (bookmarkCount > 0) { buttonClass += ' bookmarked' }
            }
    
            contents.push(
            this.attach('button', {
              action: 'toggleBookmark',
              title: tooltip,
              label: label,
              icon: icon,
              className: buttonClass
            })
          );
        }
        return contents;
      }, 
    });
 
  api.decorateWidget('topic-timeline:after', function(helper) {
    return helper.attach('topic-timeline-bookmark');
  });
</script>

Grazie per averci contattato. Uno dei nostri sviluppatori esaminerà la questione e ti fornirà informazioni utili.

Ciao,

Non l’ho provato in locale, ma potrebbe funzionare qualcosa del genere:

Nel tuo script principale, aggiungi questa chiamata API:

api.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');

Nel codice del tuo widget, dichiara questa funzione:

api.createWidget("topic-timeline-bookmark", {  
  // codice omesso

  // potresti riuscire a chiamarlo schedule-rerender 
  // direttamente nella chiamata API invece di force-refresh
  // ed evitare di avere questa funzione
  forceRefresh() {
    this.scheduleRerender();
  }
});

Penso che questo dovrebbe funzionare; se non funziona, fammelo sapere e proverò a costruire un esempio funzionante in locale.

Grazie, @joffreyjaffeux, per la risposta.

Abbiamo provato il codice suggerito da te, ma non funziona.

  1. Abbiamo aggiunto la seguente chiamata API:
    api.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');
    E poi abbiamo aggiunto il metodo forceRefresh() nel widget “topic-timeline-bookmark”.
    Ma non funziona.

  2. Ho anche provato a rinominare il secondo parametro del metodo dispatchWidgetAppEvent in “schedule-rerender” e ho rimosso la funzione forceRefresh dal widget. Anche questo non funziona.

Ho esaminato l’implementazione del metodo api.dispatchWidgetAppEvent, che accetta 3 argomenti, dove il secondo è widgetKey. Penso che dovrebbe essere il valore restituito dalla funzione buildKey() del widget.
Il terzo argomento è l’appEvent, che viene convertito in camelCase e utilizzato come nome del metodo per noi.

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.js#L1448

Stiamo dimenticando qualcosa?

Proverò in locale, probabilmente ho commesso un errore.

@saurabhmasc L’ho fatto funzionare in locale, ma ho dovuto correggere un bug nel core e aggiungere anche una nuova funzionalità al core. Aggiornerò l’argomento quando tutto sarà unito.

Grazie, @j.jaffeux.

Ciao @j.jaffeux,

Hai idea di quando queste modifiche verranno unite?

Ciao, sì, l’ho appena unito (quindi dovrai prima distribuirlo): DEV: adds a topic level bookmark toggle (#14471) · discourse/discourse@20e70d0 · GitHub

Inoltre, questo è un esempio di componente che ho creato per questo:

Fammi sapere se hai domande.

Ciao @j.jaffeux,

  1. Ora abbiamo notato che in precedenza, quando salvavamo un segnalibro dai topic-footer-buttons, anche il primo post veniva contrassegnato come salvato, ma ora il primo post non viene più salvato. È corretto così?

  2. Abbiamo testato il tuo componente: tutti i casi funzionano correttamente, tranne la funzionalità “Clear bookmark” che non è sincronizzata. Per farla funzionare, abbiamo aggiunto le seguenti righe di codice e ora anche la funzionalità “Clear bookmark” funziona correttamente.

  api.dispatchWidgetAppEvent(
    "topic-timeline",
    "topic-timeline-bookmark",
    "post-stream:refresh"
  );

Grazie.

Esaminerò il primo punto. Per quanto riguarda il secondo, sì, è possibile che abbia dimenticato un caso; il principale autore dei segnalibri è assente al momento e vorrei modificare alcune cose, ma ho bisogno che torni. La tua correzione dovrebbe andare bene.

Dopo vari test, credo che questo sia il comportamento previsto (e non è correlato al componente).

Grazie, @j.jaffeux, per il tuo feedback.

Creeremo un nuovo ticket per richiedere l’applicazione di queste modifiche principali ai nostri ambienti di Staging e Produzione, così da poterle testare su Staging.