Impossibile compilare il js nel mio componente SyntaxError: Private field must be used in an enclosing class

Alla fine della giornata ho bisogno di un pulsante “nuovo argomento” nel corpo dell’elenco degli argomenti nel tema centrale di Discourse. Ogni ingegnere si lamenta del fatto che non gli piace il pulsante “avvia nuova conversazione” posizionato solo in fondo all’elenco degli argomenti all’interno di ciascuna categoria. Non vogliono usare la scelta del menu “nuovo argomento” in alto perché ciò non avvia l’argomento nella categoria in cui si trovano attualmente.

Ho eseguito questo tramite llama 3.1 405B e gpt4 tramite ask.discourse.com, ma non riesco a ottenere una versione di JavaScript che compili. Ricevo continuamente un errore di compilazione: SyntaxError: Private field must be used in an enclosing class.

Ricevo anche un errore nel registro dei widget, ma ciò è dovuto al fatto che il widget personalizzato non viene mai creato a causa dell’errore di compilazione JS.

Sto usando il tema Discourse Central.

Dato questo blocco Header:
"<script type=\"text/discourse-plugin\" version=\"0.8.18\">
  api.createWidget('custom-new-topic-button', {
    tagName: 'div.custom-new-topic-button',

    buildKey: () => `custom-new-topic-button`,

    html() {
      return [
        this.attach('button', {
          className: 'btn btn-primary',
          action: 'createNewTopic',
          contents: 'New Topic'
        })
      ];
    },

    click() {
      const composerController = this.container.lookup("controller:composer");
      const currentCategory = this.container.lookup("controller:navigation/category").get("model.id");

      composerController.open({
        action: require("discourse/models/composer").default.CREATE_TOPIC,
        draftKey: require("discourse/models/composer").default.DRAFT,
        categoryId: currentCategory,
      });

      return false;
    },
  });

  api.decorateWidget('topic-list:before', (helper) => {
    if (api.getCurrentUser()) {
      helper.appendChild(helper.createWidget('custom-new-topic-button'));
    }
  });
</script>"

con questo blocco Head:

"<script>
    {{#if currentUser}}
     <div>class="topic-list-body-new-topic">
      {{custom-new-topic-button}}
     </div>
   {{/if}}
</script>"

e questo CSS:

".topic-list-body::before {
    content: "";
    display: block;
    position: relative; /* Important to allow absolute positioning within */
  }
  
  .topic-list-body-new-topic {
    position: absolute;
    top: 0;
    left: 0;
    padding: 10px;
    background: #f2f3f5;
    border-bottom: 1px solid #ccc;
  }
  .custom-new-topic-button .btn.btn-primary {
    background-color: #007bff;
    border-color: #007bff;
    color: #fff;
  }"

Questo era il mio codice originale, la raccomandazione più recente è:

<script type="text/discourse-plugin" version="0.8.18">
  api.createWidget('custom-new-topic-button', {
    tagName: 'div.custom-new-topic-button',

    buildKey() {
      return 'custom-new-topic-button';
    },

    defaultState() {
      return {};
    },

    html() {
      return [
        this.attach('button', {
          className: 'btn btn-primary',
          action: 'createNewTopic',
          contents: 'New Topic'
        })
      ];
    },

    createNewTopic() {
      const composerController = this.container.lookup("controller:composer");
      const currentCategory = this.container.lookup("controller:navigation/category").get("model.id");
      const Composer = require("discourse/models/composer").default;

      composerController.open({
        action: Composer.CREATE_TOPIC,
        draftKey: Composer.DRAFT,
        categoryId: currentCategory,
      });

      return false;
    },
  });

  api.decorateWidget('topic-list:before', (helper) => {
    if (api.getCurrentUser()) {
      helper.appendChild(helper.createWidget('custom-new-topic-button'));
    }
  });
</script>

@steven.webster @vasanth.mohan

Ce l’ho fatta. @sam Ho esaurito le mie chiamate giornaliere per chiedere… mi dispiace. E poi sono corso al nostro LLAMA 405 B e dopo un sacco di tira e molla ho ottenuto codice funzionante. Non riesco a immaginare quanti soldi mi sarebbe costato. Potrei sentire da altre persone nel forum “ehi idiota c’era un’impostazione per fare questo là in quella posizione”. Ma questo è stato un divertente esercizio di revisione continua dei prompt per ottenere codice funzionante.

Alcune delle chiavi sono dire (tenete presente che alcune di queste potrebbero essere imprecise perché sono stato uno sviluppatore JavaScript e uno sviluppatore Discourse per circa 2 giorni in totale.)

Questo è un forum ospitato da Discourse e non ho accesso al sistema operativo
Questo è un plugin, quindi non puoi fare riferimento direttamente a Discourse.
Non puoi fare riferimento direttamente a Ember
Se hai intenzione di usarlo, assicurati di legarlo a self

E poi vai nei tratti funzionali che desideri.

<script type="text/discourse-plugin" version="1.24.0">
  api.modifyClass('component:topic-list', {
    pluginId: 'your-plugin-id',

    didRender: function() {
      const category = this.get('category');
      if (!category) {
        console.error('Categoria non trovata');
        return;
      }

      const currentUser = this.currentUser;
      if (!currentUser) {
        console.error('Utente corrente non trovato');
        return;
      }

      const canCreateTopic = currentUser.can_create_topic;
      if (canCreateTopic === undefined) {
        console.error('Can create topic non definito');
        return;
      }

      console.log('categoria:', category);
      console.log('canCreateTopic:', canCreateTopic);

      if (category && canCreateTopic) {
        const topicListBody = document.querySelector('.topic-list-body');
        const listContainer = document.querySelector('.list-container');
        const topicList = document.querySelector('.topic-list');

        let container = topicListBody || listContainer || topicList;

        if (!container) {
          container = this.element; // Usa l'elemento del componente come contenitore
        }

        console.log('contenitore:', container);

        const existingButton = container.querySelector('.new-topic-button');
        if (!existingButton) {
          const newTopicButton = document.createElement('a');
          newTopicButton.href = '#';
          newTopicButton.className = 'new-topic-button';
          newTopicButton.setAttribute('data-category-id', category.id);
          newTopicButton.textContent = 'Nuovo Argomento';

          const self = this; // Memorizza il contesto del componente
          newTopicButton.onclick = (e) => {
            e.preventDefault();
            const router = api.container.lookup('router:main');
            const url = router.generate('new-topic', { queryParams: { category: category.slug } });
            router.transitionTo(url);
          };


          container.prepend(newTopicButton);
          console.log('pulsante aggiunto');
        }
      }
    }
  });
</script>

Ho parlato troppo presto, quella versione aveva un problema di didRender che non voleva pubblicare in nessuna categoria diversa dalla prima. Llama l’ha risolto.

<script type="text/discourse-plugin" version="1.24.0">
  api.modifyClass('component:topic-list', {
    pluginId: 'your-plugin-id',

    didRender: function() {
      const category = this.get('category');
      if (!category) {
        console.error('Categoria non trovata');
        return;
      }

      const currentUser = this.currentUser;
      if (!currentUser) {
        console.error('Utente corrente non trovato');
        return;
      }

      const canCreateTopic = currentUser.can_create_topic;
      if (canCreateTopic === undefined) {
        console.error('Can create topic non definito');
        return;
      }

      console.log('categoria:', category);
      console.log('canCreateTopic:', canCreateTopic);

      if (category && canCreateTopic) {
        const topicListBody = document.querySelector('.topic-list-body');
        const listContainer = document.querySelector('.list-container');
        const topicList = document.querySelector('.topic-list');

        let container = topicListBody || listContainer || topicList;

        if (!container) {
          container = this.element; // Usa l'elemento del componente come contenitore
        }

        console.log('contenitore:', container);

        let newTopicButton = container.querySelector('.new-topic-button');
        if (!newTopicButton) {
          newTopicButton = document.createElement('a');
          newTopicButton.href = '#';
          newTopicButton.className = 'new-topic-button';
          container.prepend(newTopicButton);
          console.log('pulsante aggiunto');
        }

        newTopicButton.setAttribute('data-category-id', category.id);
        newTopicButton.textContent = 'Nuovo argomento';

        const self = this; // Memorizza il contesto del componente
        newTopicButton.onclick = (e) => {
          e.preventDefault();
          const router = api.container.lookup('router:main');
          const url = router.generate('new-topic', { queryParams: { category: category.slug } });
          router.transitionTo(url);
        };
      }
    }
  });
</script>

Sembra che tu abbia risolto il tuo problema, come spesso accade quando compongo richieste di aiuto.

New Topic Header Button - #67 by patrickemin fornirebbe un esempio e potrebbe essere esattamente quello che stai cercando.

Inoltre, dì ai tuoi ingegneri che possono premere il tasto c per comporre un messaggio.

3 Mi Piace

In Central, il pulsante per avviare una nuova conversazione si trova in fondo all’elenco degli argomenti. Tutti volevano un pulsante in alto. Potrei cambiarlo in un piccolo più, ma questi due screenshot lo mostrano.


1 Mi Piace

@pfaffman Ho provato il nuovo pulsante di intestazione dell’argomento come primo tentativo. Tuttavia, questo non si integra bene con il nuovo tema di Discourse Central.

I widget stanno scomparendo. Non è una buona idea usare l’API dei widget.

Usa i componenti Glimmer.

2 Mi Piace

Dovremo anche rimuovere un sacco di vecchi contenuti dai “rag” dell’IA, oltre ad attendere che i modelli dei widget post-vendita vengano perfezionati. Anche ask.discourse.com si è orientato verso la strada dei widget. Cosa sostituirà i widget? Vedrò se riesco a far generare a un modello del codice che tenga conto di ciò. A proposito, la maggior parte del mio esercizio è vedere se riesco a far fare a un modello questo lavoro dato che non so quasi nulla di js :slight_smile:

Conosco la sensazione.

Componenti Glimmer. Da qualche parte c’è un buon argomento che li descrive.

Ma ecco un esempio per creare il componente:

Ed ecco un modo javascript per inserirlo:

L’altro modo per inserirlo è il modo che sta diventando “vecchia scuola” di creare un connettore che poi inserisce il componente, ma il vantaggio del modo initializer è che puoi quindi passare il plugin outlet desiderato all’initializer in modo da poter avere un’impostazione che cambia dove viene visualizzato.

Penso che tu voglia trovare un esempio di qualcosa che chiama shouldDisplay (o qualcosa di simile) se vuoi che venga visualizzato solo a volte (ad esempio, se sono loggati).

4 Mi Piace

Il mio codice finale che ho ottenuto da Llama ieri sera non usava widget ma non usava nemmeno glimmer. Sperimenterò con glimmer più tardi oggi.

<script type="text/discourse-plugin" version="1.24.0">
  api.modifyClass('component:topic-list', {
    pluginId: 'your-plugin-id',

    didRender: function() {
      const category = this.get('category');
      if (!category) {
        console.error('Categoria non trovata');
        return;
      }

      const currentUser = this.currentUser;
      if (!currentUser) {
        console.error('Utente corrente non trovato');
        return;
      }

      const canCreateTopic = currentUser.can_create_topic;
      if (canCreateTopic === undefined) {
        console.error('Impossibile creare l\'argomento non definito');
        return;
      }

      console.log('categoria:', category);
      console.log('canCreateTopic:', canCreateTopic);

      if (category && canCreateTopic) {
        const topicListBody = document.querySelector('.topic-list-body');
        const listContainer = document.querySelector('.list-container');
        const topicList = document.querySelector('.topic-list');

        let container = topicListBody || listContainer || topicList;

        if (!container) {
          container = this.element; // Usa l'elemento del componente come contenitore
        }

        console.log('contenitore:', container);

        let newTopicButton = container.querySelector('.new-topic-button');
        if (!newTopicButton) {
          newTopicButton = document.createElement('a');
          newTopicButton.href = '#';
          newTopicButton.className = 'new-topic-button';
          container.prepend(newTopicButton);
          console.log('pulsante aggiunto');
        }

        newTopicButton.setAttribute('data-category-id', category.id);
        newTopicButton.textContent = 'Nuovo argomento';

        const self = this; // Memorizza il contesto del componente
        newTopicButton.onclick = (e) => {
          e.preventDefault();
          const router = api.container.lookup('router:main');
          const url = router.generate('new-topic', { queryParams: { category: category.slug } });
          router.transitionTo(url);
        };
      }
    }
  });

</script>

Caveat: L’elenco degli argomenti non è attualmente convertito in Glimmer.

Tuttavia, se stai allegando Componenti a Plugin Outlets, dovresti usare Glimmer.

Se devi allegare a un widget, puoi usare RenderGlimmer per ottenerlo.

Esempio qui:

Ti imploro di non fare troppo affidamento sugli LLM senza aver prima imparato le basi da solo, poiché devi essere l’ultimo controllo di qualità su ciò che l’LLM sta producendo.

Devi anche progettare correttamente la soluzione.

Leggi di più su EmberJS qui:

3 Mi Piace

Grazie. Studierò sicuramente di più dato che sono nuovo a discourse e js.

Lavoro per un’azienda di intelligenza artificiale, quindi questo è stato anche un esercizio di prompt engineering.

3 Mi Piace

Fantastico, quindi avrai una buona idea dei loro punti di forza e di debolezza.

Ho scritto il primo AI Bot per Discourse chiamato Chatbot, quindi ho anche qualche informazione.

2 Mi Piace

Aggiungeremo una guida speciale al prompt di sistema per garantire che “ask” non raccomandi mai l’uso di widget

5 Mi Piace