Como parte de nuestro esfuerzo continuo por mejorar la base de código de Discourse, estamos eliminando el uso del sistema de renderizado heredado de “widget” y reemplazándolo con componentes Glimmer.
Recientemente, modernizamos el menú de publicaciones, y ahora está disponible en Discourse mediante la configuración glimmer_post_menu_mode.
Esta configuración acepta tres valores posibles:
disabled: utiliza el sistema heredado de “widget”.auto: detectará la compatibilidad de tus plugins y temas actuales. Si alguno no es compatible, se utilizará el sistema heredado; de lo contrario, se utilizará el nuevo menú.enabled: utilizará el nuevo menú. Si tienes algún plugin o tema incompatible, es posible que tu sitio deje de funcionar.
Ya hemos actualizado nuestros plugins oficiales para que sean compatibles con el nuevo menú, pero si aún tienes algún plugin, tema o componente de tema de terceros incompatible con el nuevo menú, será necesario actualizarlos.
Se imprimirán advertencias en la consola del navegador que identificarán el origen de la incompatibilidad.
Cronograma de implementación
Estas son estimaciones aproximadas sujetas a cambios
Q4 2024:
implementación central finalizada
plugins oficiales actualizados
habilitado en Meta
glimmer_post_menu_modeconfigurado por defecto enauto; mensajes de obsolescencia en consola habilitados
publicado consejo de actualización
Q1 2025:
los plugins y temas de terceros deberían estar actualizados
los mensajes de obsolescencia comenzarán, activando un banner de advertencia para administradores para cualquier problema restante
el nuevo menú de publicaciones se habilitará por defecto
Q2 2025
1 de abril - eliminación de la configuración de la bandera de función y del código heredado
¿Qué significa esto para mí?
Si tu plugin o tema utiliza alguna API de “widget” para personalizar el menú de publicaciones, deberá actualizarse para ser compatible con la nueva versión.
¿Cómo puedo probar el nuevo menú de publicaciones?
En la última versión de Discourse, el nuevo menú de publicaciones se habilitará si no tienes ningún plugin o tema incompatible.
Si tienes extensiones incompatibles instaladas, como administrador, aún puedes cambiar la configuración a enabled para forzar el uso del nuevo menú. Usa esto con precaución, ya que tu sitio podría dejar de funcionar dependiendo de las personalizaciones que tengas instaladas.
En el improbable caso de que este sistema automático no funcione como se espera, puedes anular temporalmente esta “bandera de función automática” utilizando la configuración anterior. Si necesitas hacerlo, por favor avísanos en este tema.
¿Necesito actualizar mi plugin o tema?
Necesitarás actualizar tus plugins o temas si realizan alguna de las personalizaciones siguientes:
-
Utilizan
decorateWidget,changeWidgetSetting,reopenWidgetoattachWidgetActionen estos widgets:post-menupost-user-tip-shimsmall-user-list
-
Utilizan cualquiera de los siguientes métodos de la API:
addPostMenuButtonremovePostMenuButtonreplacePostMenuButton
En caso de que tengas extensiones que realicen una de las personalizaciones anteriores, se imprimirá una advertencia en la consola que identificará el plugin o componente que necesita ser actualizado al acceder a una página de tema.
El ID de obsolescencia es:
discourse.post-menu-widget-overrides
Si utilizas más de un tema en tu instancia, asegúrate de revisar todos ellos, ya que las advertencias solo se imprimirán para los plugins activos y los temas y componentes de tema actualmente en uso.
¿Cuáles son las alternativas?
Hemos introducido el transformador de valores post-menu-buttons como la nueva API para personalizar el menú de publicaciones.
El transformador de valores proporciona un objeto DAG que permite agregar, reemplazar, eliminar o reordenar los botones. También proporciona información contextual, como la publicación asociada con el menú, el estado de la publicación mostrada y las claves de los botones para facilitar la colocación de los elementos.
Las APIs de DAG esperan recibir componentes Ember si la API necesita una nueva definición de botón, como .add y .replace.
Cada personalización es diferente, pero aquí hay algunas orientaciones para los casos de uso más comunes:
addPostMenuButton
Antes:
withPluginApi("1.34.0", (api) => {
api.addPostMenuButton("solved", (attrs) => {
if (attrs.can_accept_answer) {
const isOp = currentUser?.id === attrs.topicCreatedById;
return {
action: "acceptAnswer",
icon: "far-check-square",
className: "unaccepted",
title: "solved.accept_answer",
label: isOp ? "solved.solution" : null,
position: attrs.topic_accepted_answer ? "second-last-hidden" : "first",
};
}
});
});
Después:
Los ejemplos a continuación utilizan el Formato de etiqueta de plantilla (gjs) de Ember.
// components/solved-accept-answer-button.gjs
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import DButton from "discourse/components/d_button";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default class SolvedAcceptAnswerButton extends Component {
// indica si el botón se mostrará inmediatamente o se ocultará detrás del botón "mostrar más"
static hidden(args) {
return args.post.topic_accepted_answer;
}
...
<template>
<DButton
class="post-action-menu__solved-unaccepted unaccepted"
...attributes
@action={{this.acceptAnswer}}
@icon="far-check-square"
@label={{if this.showLabel "solved.solution"}}
@title="solved.accept_answer"
/>
</template>
}
// initializer.js
import SolvedAcceptAnswerButton from "../components/solved-accept-answer-button";
...
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({
value: dag,
context: {
post,
firstButtonKey, // clave del primer botón
secondLastHiddenButtonKey, // clave del penúltimo botón oculto
lastHiddenButtonKey, // clave del último botón oculto
},
}) => {
dag.add(
"solved",
SolvedAcceptAnswerButton,
post.topic_accepted_answer
? {
before: lastHiddenButtonKey,
after: secondLastHiddenButtonKey,
}
: {
before: [
"assign", // botón agregado por el plugin assign
firstButtonKey,
],
}
);
}
);
});
Estilizando tus botones
Se recomienda incluir
...attributescomo se muestra en el ejemplo anterior en tu componente.Al combinarse con el uso de los componentes
DButtonoDMenu, esto se encargará de las clases de plantilla y asegurará que tu botón siga el formato de los demás botones del menú de publicaciones.El formato adicional se puede especificar utilizando tus clases personalizadas.
replacePostMenuButton
- Antes:
withPluginApi("1.34.0", (api) => {
api.replacePostMenuButton("like", {
name: "discourse-reactions-actions",
buildAttrs: (widget) => {
return { post: widget.findAncestorModel() };
},
shouldRender: (widget) => {
const post = widget.findAncestorModel();
return post && !post.deleted_at;
},
});
});
- Después:
import ReactionsActionButton from "../components/discourse-reactions-actions-button";
...
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { buttonKeys } }) => {
// ReactionsActionButton es el nuevo componente de botón
dag.replace(buttonKeys.LIKE, ReactionsActionButton);
}
);
});
removePostMenuButton
- Antes:
withPluginApi("1.34.0", (api) => {
api.removePostMenuButton('like', (attrs, state, siteSettings, settings, currentUser) => {
if (attrs.post_number === 1) {
return true;
}
});
});
- Después:
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { post, buttonKeys } }) => {
if (post.post_number === 1) {
dag.delete(buttonKeys.LIKE);
}
}
);
});
¿Qué pasa con otras personalizaciones?
Si tu personalización no puede lograrse utilizando la nueva API que hemos introducido, por favor avísanos creando un nuevo tema de desarrollo para discutirlo.
Soy autor de un plugin/tema. ¿Cómo actualizo un tema/plugin para que sea compatible con el menú de publicaciones antiguo y nuevo durante la transición?
Hemos utilizado el siguiente patrón para soportar tanto la versión antigua como la nueva del menú de publicaciones en nuestros plugins:
function customizePostMenu(api) {
const transformerRegistered = api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context }) => {
// personalizaciones del nuevo menú de publicaciones
...
}
);
const silencedKey =
transformerRegistered && "discourse.post-menu-widget-overrides";
withSilencedDeprecations(silencedKey, () => customizeWidgetPostMenu(api));
}
function customizeWidgetPostMenu(api) {
// código de personalización antiguo de "widget" aquí
...
}
export default {
name: "my-plugin",
initialize(container) {
withPluginApi("1.34.0", customizePostMenu);
}
};
Más ejemplos
Puedes consultar nuestros plugins oficiales para ver ejemplos de cómo utilizar la nueva API: