Renderizar una publicación encima del Outlet discovery-list-container-top

Soy un novato en esto, lo siento

Usé ask discourse para preguntar:
en un tema quiero renderizar la primera publicación de dos temas por encima de la lista de temas en el outlet discovery-list-container-top

Me dio varias versiones que a mi parecer deberían funcionar. Todas están arrojando un error en la vista previa. Le pregunto a discourse:
¿Cómo pondría el código de ejemplo en la pestaña JS en lugar de en archivos?

Me dio esta versión

import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";

class FirstPosts extends Component {
  @tracked posts = [];

  constructor() {
    super(...arguments);
    this.loadPosts();
  }

  async loadPosts() {
    let topicIds = [123, 456]; // cambia a tus IDs de tema
    let posts = [];
    for (let id of topicIds) {
      let res = await fetch(`/t/${id}.json`);
      let data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }
    this.posts = posts;
  }

  static template = <template>
    {{#each this.posts as |post|}}
      <div class="first-post-preview">
        <h4>{{post.topic_title}}</h4>
        {{{post.cooked}}}
      </div>
    {{/each}}
  </template>;
}

export default apiInitializer("0.11.1", api => {
  api.renderInOutlet("discovery-list-container-top", FirstPosts);
});

y cuando pegué el código de error en ask discourse me dio esta versión

import { apiInitializer } from "discourse/lib/api";

// Almacén de datos global (tramposo, pero funciona para la pestaña JS)
window.firstPostsData = [];

fetch("/t/123.json")
  .then(r => r.json())
  .then(data => window.firstPostsData.push(data.post_stream.posts[0]));

fetch("/t/456.json")
  .then(r => r.json())
  .then(data => window.firstPostsData.push(data.post_stream.posts[0]));

export default apiInitializer(api => {
  api.renderInOutlet("discovery-list-container-top", 
    <template>
      {{#each (theme-prefix "firstPostsData" window=true) as |post|}}
        <div class="first-post-preview">
          <h4>{{post.topic_title}}</h4>
          {{{post.cooked}}}
        </div>
      {{/each}}
    </template>
  );
});

¿Alguien puede decirme qué estoy haciendo mal?

El error en la consola fue:

Error de compilación: SyntaxError: /theme-4/discourse/api-initializers/theme-initializer.gjs:

esto es lo que se mostró en la vista previa

Gracias

1 me gusta

Lo he ajustado y esto parece funcionar:

import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";

class FirstPosts extends Component {
  @tracked posts = [];

  constructor() {
    super(...arguments);
    this.loadPosts();
  }

  async loadPosts() {
    let topicIds = [123, 456]; // cambia a tus IDs de tema
    let posts = [];
    for (let id of topicIds) {
      const res = await fetch(`/t/${id}.json`);
      const data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }
    this.posts = posts;
  }

  <template>
    {{#each this.posts as |post|}}
      <div class="first-post-preview">
        <h4>{{post.topic_title}}</h4>
        {{{post.cooked}}}
      </div>
    {{/each}}
  </template>;
}

export default apiInitializer((api) => {
  api.renderInOutlet("discovery-list-container-top", FirstPosts);
});

1 me gusta

¡Gracias Nate! Estoy tratando de averiguar qué cambiaste

Tu código parece coincidir con mi primera versión

Reemplazaste let con const en el bucle for

¿Es eso correcto?

La versión de ask discourse arroja un error

for (let id of topicIds) {
      let res = await fetch(`/t/${id}.json`);
      let data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }

La versión de Nate funciona

for (let id of topicIds) {
      const res = await fetch(`/t/${id}.json`);
      const data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }

¿Alguien puede explicar qué está mal? ¿Por qué let no funcionaría y const sí?

Gracias de nuevo Nate

1 me gusta

Intenté con let y el resultado fue el mismo. Es solo que normalmente usaría const al usar fetch() o ajax().

Creo que el error proviene de la línea static template = . Con ella, obtengo:

[THEME 10283 'Pokemon Theme'] Error: connector component has no associated template. Ensure the template is colocated or authored with gjs.
    at h (plugin-connectors.js:35:11)
    at eY.renderInOutlet (plugin-api.gjs:1116:5)
    at todo.gjs:43:7
    at eH (plugin-api.gjs:3363:10)
    at Object.initialize (api.js:21:14)
    at i.initialize (app.js:265:28)
    at index.js:379:19
    at e.each (index.js:183:7)
    at e.walk (index.js:112:10)
    at e.each (index.js:59:20)
    at e.topsort (index.js:65:10)
    at iL._runInitializer (index.js:392:11)
    at iL.runInstanceInitializers (index.js:377:10)
    at l._bootSync (instance.js:116:22)
    at iL.didBecomeReady (index.js:784:18)
    at invoke (index.js:262:14)
    at m.flush (index.js:180:11)
    at g.flush (index.js:334:19)
    at z._end (index.js:762:32)
    at _boundAutorunEnd (index.js:499:12)

Y si solo uso <template> directamente, no hay error. No creo que usar static template sea válido aquí, por lo que usar la etiqueta de plantilla directamente funciona.

3 Me gusta

Borré por tonto la versión que estaba probando y ahora no puedo hacer que se ejecute su versión más reciente

theme-initializer.gjs:18 Uncaught (in promise) ReferenceError: constid is not defined
    at n.loadPosts (theme-initializer.gjs:18:10)
    at new n (theme-initializer.gjs:12:10)
    at h.createComponent (index.js:259:12)
    at $.create (index.js:419:28)
    at Object.evaluate (index.js:985:23)
    at Object.evaluate (index.js:103:106)
    at tr.evaluateSyscall (index.js:2873:20)
    at tr.evaluateInner (index.js:2852:64)
    at tr.evaluateOuter (index.js:2849:10)
    at tH.next (index.js:4167:45)
    at tH._execute (index.js:4157:21)
    at tH.execute (index.js:4133:41)
    at tq.sync (index.js:4194:120)
    at tz.render (index-BCp6wOJU.js:4636:43)
    at index-BCp6wOJU.js:4934:16
    at eX (index.js:2414:7)
    at tG._renderRoots (index-BCp6wOJU.js:4914:7)
    at tG._renderRootsTransaction (index-BCp6wOJU.js:4962:12)
    at tG._renderRoot (index-BCp6wOJU.js:4904:10)
    at tG._appendDefinition (index-BCp6wOJU.js:4828:10)
    at tG.appendOutletView (index-BCp6wOJU.js:4818:10)
    at invoke (index.js:264:14)
    at m.flush (index.js:180:11)
    at g.flush (index.js:334:19)
    at z._end (index.js:762:32)
    at _boundAutorunEnd (index.js:499:12)

Por favor, ayúdenme a arreglarlo.

Sí, let y const son efectivamente idénticos aquí, así que ese no es el problema.

Creo que solo puedes incluir plantillas con esa sintaxis en un archivo .gjs independiente, ya que ese sufijo indica al intérprete que lo precompile.

Moverlo a GitHub es en cualquier caso una muy buena idea.

2 Me gusta

Gracias por ese consejo, estoy intentando hacerlo ahora. Haber llegado tan lejos me ha dado ánimo. El código de Nate de arriba realmente funciona y pone los dos temas en la parte superior. Iniciar un nuevo tema con mi idea de tema e intentar documentar lo que aprenda. ¡ask.discourse.org es absolutamente increíble!

2 Me gusta