Creando interfaces de administrador consistentes

Estas directrices tienen como objetivo crear una interfaz de administración cohesiva, centrándose en la usabilidad, la accesibilidad y un diseño estructurado. Consulte el índice para ver qué se incluye y navegar fácilmente a cada sección.

Nota: La terminología utilizada aquí se define en el glosario de la interfaz de administración.

0. Prefacio - Estructura de la página de configuración y enlaces de la barra lateral

Al agregar nuevas páginas de configuración en la interfaz de administración, cada página necesitará un enlace para la barra lateral, y cada página necesitará tanto un título como una descripción de encabezado. Esto es para que seamos consistentes en todas partes, y las mejoras futuras a la búsqueda de administración puedan mostrar todo el diseño de la interfaz de administración.

Generalmente, la estructura de la interfaz de administración se ve así:

  • Interfaz de administración
    • Página de configuración (mostrada en la barra lateral)
      • Pestaña de configuración
      • Otras pestañas de tercer nivel opcionales
        • Página de tercer nivel Editar/Nuevo para recursos

Eventualmente, se insertará un “resumen de sección” entre la interfaz raíz y las páginas de configuración.

Enlaces de la barra lateral

Todas las páginas de administración deben agregarse al ADMIN_NAV_MAP en discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub . Cada elemento debe tener al menos estas claves:

  • name - Un identificador único para el enlace, debe ser snake_case
  • route O href - El route es un identificador de ruta de Ember, como adminUsers. Para administradores, estos se definen en el mapa de rutas de administración . Se puede usar un href en su lugar, pero se prefiere route.
  • label O text - La etiqueta es una clave de I18n, que generalmente debe ser admin.config.page_name.title (ver sección de traducciones a continuación). Si se usa text, será texto ya traducido.

También se pueden proporcionar estas claves opcionales:

  • description - Se recomienda que también proporcione esto. Es una clave de I18n, generalmente debe ser admin.config.page_name.header_description.
  • icon - También recomendado, esto se muestra junto al enlace en la barra lateral.
  • routeModels - Matriz de datos de URL para el caso de parámetros de ruta. Por ejemplo, adminCustomizeThemes tiene un parámetro de ruta :type, por lo que puede pasar routeModels: ["components"]. Los elementos de la matriz se utilizan en el mismo orden en que aparecen los parámetros de ruta.
  • moderator: Establezca esto en true si los moderadores deben ver esta página en la barra lateral.
  • keywords: Una clave de I18n, con una lista de palabras clave separadas por | para el enlace de la barra lateral, utilizada para “juice” de búsqueda adicional al filtrar/buscar páginas.
  • links: Una lista de rutas de 3er nivel que están debajo de la página en la barra lateral. Estos no se muestran en la barra lateral en sí. Esto se utilizará para funciones futuras de búsqueda de administración.
  • settings_area y settings_category: Si la página muestra solo una lista de configuraciones del sitio filtradas, entonces uno de estos debe completarse. Si la configuración del sitio tiene un area definido, que se usa en AdminAreaSettings, entonces se debe usar settings_area. Si se muestra una categoría completa de configuraciones en la página, y también se usa en AdminAreaSettings, entonces se debe usar settings_category.
  • multi_tabbed: Si la página tiene una pestaña de configuración y otras pestañas, entonces esto debe establecerse en true. Ayuda a generar enlaces para el sistema de búsqueda de administración.

Traducciones

El título y la descripción del encabezado para cada página de configuración deben estar bajo:

  • admin
    • config
      • page_name
        • title: “Título de la página”
        • header_description: “Esta página es para xyz”

Puede ver ejemplos de esto aquí:

1. Migas de pan (Breadcrumbs)

Las migas de pan sirven como una herramienta de navegación, ayudando a los usuarios a comprender su ubicación actual, la estructura del contenido y la jerarquía dentro de la interfaz de administración.

Admin > Migas de pan > Rastro
Título de la página

:art: Diseño

Estructura

  1. Admin: prefijo fijo que aparece al principio de cada rastro de migas de pan, enlazando a /admin
  2. Enlace: abre la página en la misma ventana
  3. Separador: un icono angle-right separa cada enlace

Uso

Cuándo usar:

  • Presente en cada página de administración
  • Situado sobre el contenido (título, descripción, pestañas)
  • Mostrar la página seleccionada actualmente

Cuándo no usar:

  • Al visitar una nueva ruta o ruta de edición

Contenido

  • Cada elemento incluye un enlace a su página relacionada
  • Muestra la página seleccionada actualmente

Accesibilidad

  • Un elemento nav con aria-label="Breadcrumb" envuelve una lista ordenada para proporcionar un hito de navegación
  • Aplicar aria-current="page" en el último enlace para indicar que es la página actual
  • Para más detalles, consulte Prácticas de autoría WAI-ARIA Ejemplo de migas de pan

:hammer_and_wrench: Implementación

El componente DBreadcrumbsContainer debe colocarse en algún lugar de la página:

<DBreadcrumbsContainer />

Luego, cada elemento DBreadcrumbsItem agregado a cualquier componente en una ruta o una ruta hija se renderizará en este contenedor. Cada DBreadcrumbsItem tiene un @label y @path que deben proporcionarse:

<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
<DBreadcrumbsItem
  @path="/admin/plugins"
  @label={{i18n "admin.plugins.title"}}
/>
<DBreadcrumbsItem
  @path="/admin/plugins/{{@plugin.name}}"
  @label={{@plugin.nameTitleized}}
/>

Cómo se ve esto con un ejemplo visual, usando el plugin Discourse AI:

2. Encabezado y título de la página

La sección superior de una página de administración, que contiene el título de la página, junto con acciones y descripción opcionales.

:art: Diseño

Estructura

  • Título de la página: Título de la página

  • Descripción de la página: Introducción o descripción de lo que cubre el contenido (opcional)

  • Acción principal: Acción principal del título de la página (opcional)

  • Acción secundaria: Configuración de botón de acción secundaria del título de la página (opcional)

Uso y contenido

  • Título de la página: Utilice el nivel de encabezado 1 para explicar el tema principal de la página en caso de oración. Generalmente, la traducción de I18n debe estar bajo admin.config.your_page.title.

  • Descripción de la página: Admite nodos básicos de markdown como _itálica_, **negrita**, y [nombre del enlace](url)

  • Acción principal: Utilice btn-primary. No incluya un icono. Generalmente, la traducción de I18n debe estar bajo admin.config.your_page.header_description.

  • Acción secundaria: Utilice la configuración de botón btn-default, visible solo si existe una acción principal. No incluya un icono.

    :point_right: Sea claro con los botones de acción. Por ejemplo, use etiquetas descriptivas como “Agregar emoji” en lugar de solo “Agregar” para reducir la ambigüedad.

:hammer_and_wrench: Implementación

Se utiliza el componente DPageHeader aquí. Esto acepta argumentos para @titleLabel, @descriptionLabel, @learnMoreUrl, y @shouldDisplay. Esto usa yields nombrados en Ember para proporcionar 5 bloques nombrados para el contenido:

  1. breadcrumbs - Cualquier componente DBreadcrumbsItem adicional para la página debe colocarse aquí.
  2. actions - Se utiliza para definir los botones a la derecha del título. Esto produce un objeto llamado actions que se puede usar para renderizar botones Default, Primary, Danger, y Wrapped.
  3. title - Una alternativa a @titleLabel, permitiendo marcado personalizado dentro del encabezado.
  4. drawer - Una sección de cajón colapsable opcional, mostrada cuando @showDrawer es verdadero.
  5. tabs - Se utiliza para definir las pestañas de la página usando componentes NavItem. @hideTabs se puede usar para eliminar esta parte del encabezado si no es necesaria.

Un ejemplo completo está a continuación:

<DPageHeader
  @titleLabel={{i18n "admin.config.backups.title"}}
  @descriptionLabel={{i18n "admin.config.backups.header_description"}}
  @learnMoreUrl="https://meta.discourse.org/t/create-download-and-restore-a-backup-of-your-discourse-database/122710"
>
  <:breadcrumbs>
    <DBreadcrumbsItem
      @path="/admin/backups"
      @label={{i18n "admin.backups.title"}}
    />
  </:breadcrumbs>
  <:actions as |actions|>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
  <:tabs>
    <NavItem
      @route="admin.backups.settings"
      @label="settings"
      class="admin-backups-tabs__settings"
    />
    <NavItem
      @route="admin.backups.index"
      @label="admin.backups.menu.backup_files"
      class="admin-backups-tabs__files"
    />
    <NavItem
      @route="admin.backups.logs"
      @label="admin.backups.menu.logs"
      class="admin-backups-tabs__logs"
    />
    <PluginOutlet @name="downloader" @connectorTagName="div" />
  </:tabs>
</DPageHeader>

Los títulos de la página para la pestaña del navegador se manejan en rutas de Ember usando la funcionalidad titleToken. Cada vez que esto se usa en una ruta, agrega el token al final del título de la pestaña del navegador. Tenga en cuenta que debe usar la clase DiscourseRoute para extender su ruta, no la Route normal de ember para que esto funcione:

titleToken() {
  return i18n("admin.config.backups.title");
}

:point_right: El encabezado de la página se oculta automáticamente para las rutas /new y /edit para admitir Rutas de tercer nivel. Se puede anular usando el argumento @shouldDisplay.

3. Pestañas

Una navegación opcional que proporciona acceso a niveles más profundos de configuraciones o funciones. También nos referimos a esto como páginas o navegación de “tercer nivel”.

:art: Diseño

Estamos usando pestañas para cambiar entre diferentes vistas relacionadas dentro del mismo contexto.

Uso

  • No se usa para navegación principal
  • Solo una activa a la vez

:hammer_and_wrench: Implementación

Consulte los detalles del Encabezado de página, las pestañas se definen en el componente DPageHeader.

:white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square:

4. Página de aterrizaje de resumen/sección

Permite a los usuarios ver el contenido de una sección, especialmente cuando la barra lateral está colapsada o en móvil.

:art: Diseño

Estructura
Use un diseño de tres columnas iguales usando un sistema de cuadrícula. En pantallas pequeñas, estas columnas se apilarán verticalmente.

Diseño y uso

  • Se puede acceder a través de migas de pan (Admin > Comunidad > Resumen)
  • Cada sección debe tener una, excepto para plugins (que muestran instalados) e informes (solo una página)
  • El elemento tiene:
    • nombre - igual que el enlace de la sección
    • descripción - una descripción corta de lo que trata la página
    • icono - mismo icono usado para la barra lateral

:hammer_and_wrench: Implementación

Fragmentos de código o enlace a un tema/GitHub

5. Contenido de la página

El área principal de una página de administración donde se muestran e interactúan configuraciones, configuraciones y otros contenidos.

:art: Diseño

Estructura
Use un diseño de 2/3 + 1/3 usando un sistema de cuadrícula. La sección principal ocupa dos tercios y la sección secundaria ocupa un tercio del espacio. En pantallas pequeñas, estas columnas se apilarán verticalmente.

  • Área de configuración: Una sección específica dentro del contenido de la página dedicada a configuraciones y ajustes.
  • Ayuda/referencia/inset: Un área dentro del contenido de la página que proporciona guías, documentación o información contextual adicional. (opcional)

Diseño y uso

  • Agrupe configuraciones y acciones similares en tarjetas
  • Estructure diseños primarios/secundarios para que la sección principal (2/3) se use para configuraciones principales, y la sección secundaria (1/3) sea para información adicional o contexto útil
  • Si la sección secundaria no está disponible, mantenga el ancho de la sección principal igual

Contenido

:hammer_and_wrench: Implementación

Fragmentos de código o enlaces de GitHub

5.a. Subencabezado

Un subencabezado es un encabezado secundario utilizado para dividir el contenido bajo una sección, generalmente debajo de las pestañas.

Estructura

  • Subencabezado: Subencabezado de lo que cubre el contenido (opcional)
  • Acción principal: Acción principal del subencabezado (opcional)
  • Acción secundaria: Configuración de botón de acción secundaria del subencabezado (opcional)

Uso y contenido

  • Subencabezado: Utilice el nivel de encabezado 2 para explicar el tema principal del contenido relacionado. Incluya solo si:

    • Hay un botón de acción principal, o
    • Hay una descripción que explica la sección.
  • Acción principal: Utilice btn-primary. No incluya un icono.

  • Acción secundaria: Utilice la configuración de botón btn-default, visible solo si existe una acción principal. No incluya un icono.

    :point_right: Sea claro con los botones de acción. Por ejemplo, use etiquetas descriptivas como “Agregar emoji” en lugar de solo “Agregar” para reducir la ambigüedad.

:hammer_and_wrench: Implementación

Esto es similar a DPageHeader, hay un componente DPageSubheader. La principal diferencia es que solo hay un yield nombrado para actions.

  1. actions - Se utiliza para definir los botones a la derecha del título. Esto produce un objeto llamado actions que se puede usar para renderizar botones Default, Primary, Danger, y Wrapped.
<DPageSubheader @titleLabel="admin.config.backups.subheader.title">
  <:actions>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
</DPageSubheader>

5.b. Área de configuración

El área de configuración está compuesta por tarjetas o secciones. Las tarjetas son excelentes para agrupar información y tareas relacionadas, ayudando a los usuarios a escanear y priorizar el contenido más fácilmente.

:art: Diseño

Tarjeta

Las tarjetas se configuran con un radio de borde de 2px y usan un fondo de --secondary. También tienen un borde sólido de 1px con --primary-low y 20px de relleno alrededor del contenido.

Variación predeterminada

Variación de acordeón

Diseño y uso

  • Agrupe información relacionada
  • Muestre la información para que los administradores y moderadores vean lo más importante primero
  • Use encabezados que expliquen claramente para qué es la tarjeta
  • Divida los complicados en múltiples secciones, si es necesario

variación predeterminada

  • Limítense a una llamada a la acción principal por tarjeta
  • Coloque la llamada a la acción principal en la parte inferior de la tarjeta para los siguientes pasos

variación de acordeón

  • Use la esquina superior derecha de la tarjeta para acciones opcionales como “Ver todo”

Contenido

  • Todos los formularios deben usar los componentes ember FormKit en el núcleo descritos en la documentación

  • Los encabezados de las tarjetas deben estar en caso de oración

    :white_check_mark: Hacer :cross_mark: No hacer
    Configuraciones generales Configuraciones Generales
    Información de contacto INFORMACIÓN DE CONTACTO

:hammer_and_wrench: Implementación

Tenemos un componente AdminConfigAreaCard que debe usarse para todas estas tarjetas. Por ahora, esto solo tiene argumentos @translatedHeading y @heading, en el futuro podemos agregar acciones y hacerlas colapsables, etc.:

<AdminConfigAreaCard
  @heading="admin.config_areas.about.general_settings"
  class="admin-config-area-about__general-settings-section"
>
  <AdminConfigAreasAboutGeneralSettings
    @generalSettings={{this.generalSettings}}
    @setGlobalSavingStatus={{this.setSavingStatus}}
    @globalSavingStatus={{this.saving}}
  />
</AdminConfigAreaCard>

Configuraciones del sitio incrustadas

Esta sección está en progreso.

5.c. Inset de ayuda

Esta sección proporciona orientación adicional, documentación o contexto dentro del contenido de la página.

v1

:art: Diseño

Diseño y uso

  • Muestre documentación o guías relacionadas sobre el contenido de la página para proporcionar información útil
  • Incluya un icono en el encabezado para que sea fácilmente reconocible
  • Coloque esta sección en el área de diseño secundaria (1/3)

Contenido

  • Los encabezados deben estar en caso de oración

:hammer_and_wrench: Implementación

Fragmentos de código o enlace a un tema/GitHub

5.d. Tabla

Las tablas muestran información en una cuadrícula de celdas, columnas y filas, lo que facilita a los administradores escanear rápidamente elementos y tomar acciones.

:art: Diseño

Uso

  • Use tablas para mostrar contenido estructurado donde cada entrada comparte los mismos atributos.
  • Permita a los administradores revisar, habilitar/deshabilitar, editar y eliminar conjuntos de datos.
  • Adecuado para conjuntos de datos que continuarán creciendo con el tiempo.

Diseño

  • Use líneas horizontales entre filas para separar visualmente el contenido, incluida la última fila. Evite usar bordes o marcos alrededor de la tabla para evitar que parezca una red.
  • No aplique líneas verticales entre columnas. Las tablas sin líneas verticales son generalmente más fáciles de escanear y leer.

Acciones adicionales

  • Acciones de fila: Incluya acciones adicionales en la columna más a la derecha de cada fila de la tabla.
    • Si hay dos o más elementos interactivos, la acción principal (por ejemplo, “Editar”) debe ser un botón de texto, y todas las demás acciones de fila, incluido “Eliminar”, deben agruparse en un menú desplegable [...]. Se recomiendan iconos en los menús desplegables para romper visualmente las cosas.
    • Si solo hay una acción “Eliminar” y no hay acción principal, use un botón de texto “Eliminar” en línea estilizado como btn-default.
    • Debe envolver el texto de la columna principal (generalmente d-table__cell --overview) con un enlace que lleve al administrador directamente a la página Mostrar/Editar correspondiente a la fila para un acceso rápido.
  • Confirmación de eliminación: Todos los botones “Eliminar” deben mostrar una confirmación antes de realizar la acción.

Contenido

  • Encabezado: El encabezado de la tabla es la fila superior que identifica las columnas a continuación. Proporciona claridad, especialmente si los datos no son descriptivos o son ambiguos. Los encabezados deben ser cortos, descriptivos y relevantes, usando caso de título. Evite encabezados que sean demasiado largos para el contenido en las filas a continuación.
  • Columnas: Ordene las columnas por prioridad o de una manera que cuente una historia coherente con los datos. dimensione las columnas según su contenido, con columnas estrechas para contenido pequeño y columnas más anchas para párrafos.
  • Filas: Las filas deben admitir texto, botones, enlaces e iconos para mejorar la presentación de datos.
  • Sin datos: Las listas vacías deben usar el componente AdminConfigAreaEmptyList con un botón CTA y una etiqueta para guiar al usuario hacia la creación de nuevos registros

:hammer_and_wrench: Implementación

Hay una pequeña colección de clases CSS que deben usarse con tablas para que funcionen bien en móvil y escritorio.

Los elementos <table> deben tener la clase d-table aplicada.

Los elementos <thead> deben tener la clase d-table__header aplicada.

Los elementos <tr> deben tener la clase d-table__row aplicada.

Los elementos <td> que contienen mucho texto descriptivo (generalmente la columna más a la izquierda) deben usar las clases d-table__cell --overview. Todas las demás celdas deben usar d-table__cell --detail.

Los elementos <td> con las clases d-table__cell --overview pueden envolver el contenido interno de la fila en un enlace que lleve al administrador directamente a la página Editar/Mostrar para la fila. Este enlace debe seguir esta estructura y tener la clase CSS d-table__overview-link aplicada. Idealmente, se debe usar el componente LinkTo pero <a> también está bien siempre que se use con getURL.

La clase d-table__overview-name debe aplicarse a la parte del nombre aquí, pero no a la descripción.

<td class="d-table__cell --overview">
  <LinkTo
    class="d-table__overview-link"
    @route="adminPlugins.show.explorer.details"
    @model={{query.id}}
  >
    <strong class="query-name d-table__overview-name">{{query.name}}</strong>
    {{#if query.is_default}}
      <span class="query-badge">{{i18n
          "explorer.default_query"
        }}</span>
    {{/if}}
    <div class="query-desc">{{query.description}}</div>
  </LinkTo>
</td>
<td class="d-table__cell --overview">
  <a class="d-table__overview-name admin-flag-item__name d-table__overview-link" href={{this.editUrl}}>
    {{@flag.name}}
  </a>
</td>

Los elementos <td> que envuelven los botones en cada fila deben tener las clases CSS d-table-cell --controls aplicadas. Esto asegura que los botones estén alineados. Cada botón también debe tener la clase btn-small aplicada.

Para móvil, cada elemento <td> excepto el d-table-cell --overview también debe incluir un <div> con la clase d-table__mobile-label, que contiene una etiqueta I18n que es la misma que la del <th> para esa columna:

<td class="d-table__cell --detail">
  <div class="d-table__mobile-label">
    {{i18n "chat.incoming_webhooks.emoji"}}
  </div>
  {{replaceEmoji webhook.emoji}}
</td>

Esto muestra la fila de la tabla en un formato basado en tarjetas más fácil de leer en móvil:

Para menús desplegables [...], se debe usar DMenu con DropdownMenu, aquí hay un ejemplo:

<DMenu
  @identifier="backup-item-menu"
  @title={{i18n "more_options"}}
  @icon="ellipsis-vertical"
  class="btn-small"
>
  <:content>
    <DropdownMenu as |dropdown|>
      <dropdown.item>
        <DButton ...[args de botón aquí] />
      </dropdown.item>
      <dropdown.item>
        <DButton ...[args de botón aquí] />
      </dropdown.item>
    </DropdownMenu>
  </:content>
</DMenu>

Los interruptores en la fila de la tabla se manejan usando el componente DToggleSwitch:

<DToggleSwitch
  @state={{this.enabled}}
  class="admin-flag-item__toggle {{@flag.name_key}}"
  {{on "click" (fn this.toggleFlagEnabled @flag)}}
/>

Poniéndolo todo junto, aquí hay un ejemplo mínimo de una tabla de administración:

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>Nombre</th>
        <th>Descripción</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <tr class="d-table__row">
        <td class="d-table__cell --overview">
          <LinkTo @route="admin.exampleRoute" class="d-table__overview-link">
            <span class="d-table__overview-name">Elemento de ejemplo</span>
            <span class="d-table__overview-about">Una descripción corta</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">Descripción</span>
          Aquí hay contenido detallado
        </td>
        <td class="d-table__cell --controls">
          <div class="d-table__cell-actions">
            <button class="btn btn-default btn-small">Editar</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

5.e Ruta de tercer nivel

Una ruta de tercer nivel es aquella a la que solo se puede acceder desde un área de configuración. Estas generalmente vienen en forma de rutas de edición/nuevas como esta para banderas:

Aquí es donde se colocarán los formularios usando FormKit en la mayoría de los casos.

Use las rutas RESTful estándar para estas:

Acción Ruta
Nuevo <recurso>/new
Editar <recurso>/:id/edit

y asegúrese de que las rutas también estén enrutadas en el backend. (Recargar la página nueva o de edición no debe resultar en un error.)

:art: Diseño

Uso

  • Prefiera tener estas rutas de tercer nivel en lugar de tener formularios en línea en la ruta principal o dentro de una tabla. Las rutas de edición y nuevas independientes son las mejores, ya que se pueden enlazar fácilmente.
  • No muestre la parte superior de la interfaz de usuario de la página (migas de pan, encabezado de página y subencabezado)
  • En su lugar, muestre un único enlace “Volver a X” que permita al administrador llegar al área de configuración principal
  • El contenido de la página debe estar envuelto en al menos una AdminConfigAreaCard
  • Cualquier subtítulo en la página debe hacerse con tarjetas de área de configuración

:hammer_and_wrench: Implementación

Hay un simple componente BackButton que se puede usar en la parte superior de la página para volver:

<BackButton
  @route="adminConfig.flags"
  @label="admin.config_areas.flags.back"
/>

6. Páginas de configuración de configuración filtrada

Muchas de nuestras páginas de configuración de la interfaz de administración son simples listas de configuraciones del sitio filtradas. Esto permite a los administradores encontrar grupos relacionados de configuraciones sin verse abrumados por la lista completa de “Todas las configuraciones del sitio”, hasta que creemos páginas de configuración más especializadas como /admin/config/about/.

:hammer_and_wrench: Implementación

Hay algunas cosas que necesita agregar a una de estas rutas. Primero, puede mostrar toda una category de configuraciones del sitio que son las claves de nivel superior en site_settings.yml (por ejemplo, branding:), o puede usar un area de configuración.

Las configuraciones del sitio pueden vivir en múltiples areas, y puede mostrar una o más en la misma página.

  1. Agregue una ruta al mapa de rutas de administración debajo de adminConfig, por ejemplo:
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. Agregue un nuevo archivo .js de ruta, el archivo coincidirá con una ruta como frontend/discourse/admin/routes/admin-config/localization.js dependiendo del nombre de su nueva ruta. Esto debe heredar de AdminConfigWithSettingsRoute e incluir un titleToken().
import { i18n } from "discourse-i18n";
import AdminConfigWithSettingsRoute from "../admin-config-with-settings-route";

export default class AdminConfigLocalizationRoute extends AdminConfigWithSettingsRoute {
  titleToken() {
    return i18n("admin.config.localization.title");
  }
}
  1. Agregue un controlador, esto es principalmente para habilitar la búsqueda y filtrado de configuración. Debe heredar de AdminAreaSettingsBaseController:
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. Finalmente, agregue un archivo de plantilla de ruta en formato .gjs, en una ruta como frontend/discourse/admin/templates/admin-config/localization/settings.gjs. Esto debe contener el DPageHeader y las migas de pan normales, pero para mostrar las configuraciones necesita AdminAreaSettings.
<div class="admin-config-page__main-area">
  <AdminAreaSettings
    @showBreadcrumb={{false}}
    @area="localization"
    @path="/admin/config/localization"
    @filter={{@controller.filter}}
    @adminSettingsFilterChangedCallback={{@controller.adminSettingsFilterChangedCallback}}
  />
</div>

Las cosas importantes a cambiar aquí son @path, y @area (o alternativamente use @categories). Como se mencionó anteriormente, complete esto con el área de configuración del sitio que desea mostrar, o las categorías.

7. Orientación general

  • Los slugs de URL deben usar guiones (-) para indicar espacios en palabras, en lugar de guiones bajos (_).

  • Todo el texto en las interfaces de administración debe seguir las directrices de formato de texto descritas aquí:

8. Plugins

Algunos plugins necesitan una interfaz de usuario de configuración en profundidad para su plugin (por ejemplo, IA, Automatización, Gamificación) en lugar de tener solo una colección de configuraciones del sitio. Por ejemplo, aquí está Discourse AI:

Algunos ejemplos de plugins que usan esto son:

:art: Diseño

Uso

  • Se deben seguir las directrices generales de la interfaz de usuario de administración al crear interfaces de usuario de plugins independientes.

:hammer_and_wrench: Implementación

Enrutamiento de Ember

  • Todas las plantillas de ruta estarán bajo
    admin/assets/javascripts/discourse/templates/admin-plugins/show/
  • Todos los archivos js de ruta estarán bajo admin/assets/javascripts/discourse/routes/ y
    prefijados con admin-plugins-show-
  • El mapa de rutas de administración debe estar en un archivo como admin-PLUGIN-NAME-plugin-route-map.js
  • El mapa de rutas debe tener una estructura como esta. La parte importante es que
    usamos admin.adminPlugins.show como resource.
export default {
  resource: "admin.adminPlugins.show",

  path: "/plugins",

  map() {
    this.route("discourse-ai-personas", { path: "ai-personas" }, function () {
      this.route("new");
      this.route("show", { path: "/:id" });
    });
  },
};
  • El ejemplo actual de cómo funciona todo esto se ve en el plugin Discourse AI, si va a /admin/plugins/discourse-ai/ai-personas
  • Si solo tiene una ruta de “nivel superior”, por ejemplo, una que no define subrutas, entonces la ruta de la plantilla será algo como admin/assets/javascripts/discourse/templates/admin-plugins/show/your-route-name.gjs. Si hay subrutas, entonces entra en el terreno de necesitar plantillas index.gjs, show.gjs, y new.gjs, etc.

Navegación

Los plugins pueden mostrar su navegación en una barra lateral interna, o en la barra de navegación con pestañas superior. Esta última es altamente recomendada, y en el futuro el soporte de la barra lateral interna puede eliminarse.

Servidor

  • add_admin_route aún se usa para mostrar las rutas de administración personalizadas en la barra lateral de administración y desde el índice /plugins con las pestañas a lo largo de la parte superior. Básicamente, esto define la página raíz de la interfaz de usuario de su plugin.
    • use_new_show_route: true debe pasarse como un argumento adicional aquí para que se use la nueva página de muestra del plugin.

Convenciones de UI

  • Cada ruta de índice para el plugin debe mostrar un componente DPageSubheader para describir la intención de esa ruta y agregar cualquier botón de acción relacionado.
  • Los botones de acción que necesitan renderizarse en el encabezado principal de la página del plugin deben usar el outlet admin-plugin-config-page-actions con un componente dedicado. El mejor lugar para hacer esto es en el mismo inicializador donde se usa addAdminPluginConfigurationNav.
    • plugin y actions se pasan como outletArgs. plugin es la representación del modelo del plugin actual, por lo que se puede acceder al nombre del plugin y otras cosas, actions son los componentes de botones de acción producidos por DPageHeader.
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

Temas relacionados:

10 Me gusta

Y

todavía no funcionan. Creo que el segundo es -23 en lugar de -24.

5 Me gusta

Me alegra mucho ver esto publicado en meta. Meses de trabajo dedicados a esto, y lo utilizaremos para estandarizar la interfaz de usuario y la navegación de cada página en la interfaz de administración.

¿Deberíamos quizás eliminar esa tabla de contenido y usar discotoc en su lugar? Creo que sería menos frágil, aunque me gusta ver la tabla de contenido al principio de la publicación.

7 Me gusta

¡Gracias @Moin, todo arreglado!

He realizado este cambio, de lo contrario, es simplemente una tabla de contenido duplicada.

4 Me gusta

Se dividió una publicación en un nuevo tema: Mostrar nombre de usuario en la pestaña del navegador cuando se está en administración de usuarios