Utiliser Ember.PromiseProxyMixin dans un thème

Récemment, Ember.PromiseProxyMixin a été ajouté aux modules Ember dans le noyau de Discourse.

C’est un mixin Ember très utile qui vous permet d’effectuer des requêtes asynchrones et de travailler facilement avec les Promesses à l’intérieur des composants Ember. Pensez-y comme à React Suspense, mais pour Ember. Le potentiel est énorme pour le développement de thèmes et de plugins dans Discourse.

Voici la documentation officielle d’Ember pour Ember.PromiseProxyMixin.

Et vous pouvez trouver ici un exemple détaillé hors Discourse sur l’utilisation de Ember.PromiseProxyMixin.

Je vais donner un exemple simple montrant comment ce mixin peut être utilisé dans un thème Discourse. Disons que, pour une raison quelconque, dans le composant topic-list-item, vous souhaitez styliser l’avatar de l’auteur si celui-ci est un membre du personnel ; l’avatar doit alors avoir une bordure différente.

Quelque part dans topic-list-item.js(.es6), vous devrez :

  • Importer EmberObject et PromiseProxyMixin, puis étendre EmberObject avec PromiseProxyMixin
import EmberObject from "@ember/object";
import PromiseProxyMixin from "@ember/object/promise-proxy-mixin";

const PromiseObject = EmberObject.extend(PromiseProxyMixin);

// Vous pouvez utiliser une fonction de mémorisation personnalisée pour éviter plusieurs requêtes pour le même utilisateur
const getUser = memoize(username => ajax(`/u/${username}`).then(data => data));
  • Ensuite, vous devrez créer ces propriétés calculées
  // Promesse calculée
  @discourseComputed("topic")
  posterPromise(topic) {
    const { user } = topic.posters[0];
    return getUser(user.username);
  },

 // Cette propriété calculée enveloppe la promesse avec `PromiseObject`
  @discourseComputed("posterPromise")
  posterProxy() {
    const promise = this.get("posterPromise");
    return promise && PromiseObject.create({ promise });
  },

  posterData: reads("posterProxy.content.user"),

  @discourseComputed("posterData")
  isStaff() {
    const posterData = this.get("posterData");
    if (!posterData) return false;
    const { groups = [] } = posterData;
    // Pour vérifier si l'utilisateur est un membre du personnel, nous devons vérifier
    // si l'utilisateur appartient à un groupe de personnel
    return groups.some(({ name }) => name === "staff");
  }

Et dans le template topic-list-item.hb(r|s), vous auriez quelque chose comme ceci :

  {{#if posterProxy.isFulfilled}}
    {{#if isStaff}}
      // effectuez votre personnalisation
    {{/if}}
  {{/if}}

Vous pouvez utiliser isPending pour afficher peut-être un indicateur de chargement.

J’espère que cet exemple pas très utile vous aidera à comprendre comment fonctionne le mixin et peut-être vous aidera à trouver une façon de l’utiliser dans le développement de votre thème/plugin.

:wave:

4 « J'aime »

Bonjour @zcuric,

merci pour cette excellente analyse et pour la première PR. Il y a assurément des choses à explorer ici, tant dans les plugins et les thèmes que dans la base de code de Discourse. Nous verrons comment appliquer ce modèle et peut-être le simplifier à l’avenir :+1:

5 « J'aime »